From bb770ca4f3f3e81641b18335f1e52283534a144e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Sat, 3 Dec 2022 07:04:36 +0100 Subject: [PATCH] fix: properly handle `trailingSlash: true` and `rewrites` (#43641) Fixes #43623 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: Wyatt Johnson --- packages/next/shared/lib/router/adapters.tsx | 9 ++++++- .../app/next.config.js | 6 +++++ .../app/pages/index.js | 7 ++++++ .../trailingslash-with-rewrite/index.test.ts | 25 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/e2e/trailingslash-with-rewrite/app/next.config.js create mode 100644 test/e2e/trailingslash-with-rewrite/app/pages/index.js create mode 100644 test/e2e/trailingslash-with-rewrite/index.test.ts diff --git a/packages/next/shared/lib/router/adapters.tsx b/packages/next/shared/lib/router/adapters.tsx index 9bf0096abad2be7..ed237d3525fa063 100644 --- a/packages/next/shared/lib/router/adapters.tsx +++ b/packages/next/shared/lib/router/adapters.tsx @@ -117,7 +117,14 @@ export function PathnameContextProviderAdapter({ // any query strings), so it should have that stripped. Read more about the // `asPath` option over at: // https://nextjs.org/docs/api-reference/next/router#router-object - const url = new URL(router.asPath, 'http://f') + let url: URL + try { + url = new URL(router.asPath, 'http://f') + } catch (_) { + // fallback to / for invalid asPath values e.g. // + return '/' + } + return url.pathname }, [router.asPath, router.isFallback, router.isReady, router.pathname]) diff --git a/test/e2e/trailingslash-with-rewrite/app/next.config.js b/test/e2e/trailingslash-with-rewrite/app/next.config.js new file mode 100644 index 000000000000000..9f2a0ec8f0ac347 --- /dev/null +++ b/test/e2e/trailingslash-with-rewrite/app/next.config.js @@ -0,0 +1,6 @@ +module.exports = { + trailingSlash: true, + async rewrites() { + return [{ source: '/country/', destination: '/' }] + }, +} diff --git a/test/e2e/trailingslash-with-rewrite/app/pages/index.js b/test/e2e/trailingslash-with-rewrite/app/pages/index.js new file mode 100644 index 000000000000000..1236c5fdca1aefa --- /dev/null +++ b/test/e2e/trailingslash-with-rewrite/app/pages/index.js @@ -0,0 +1,7 @@ +export default function Home() { + return

Welcome home

+} + +export async function getStaticProps() { + return { props: {} } +} diff --git a/test/e2e/trailingslash-with-rewrite/index.test.ts b/test/e2e/trailingslash-with-rewrite/index.test.ts new file mode 100644 index 000000000000000..6929351f72fb3d9 --- /dev/null +++ b/test/e2e/trailingslash-with-rewrite/index.test.ts @@ -0,0 +1,25 @@ +import { join } from 'path' +import { createNext, FileRef } from 'e2e-utils' +import { NextInstance } from 'test/lib/next-modes/base' +import { fetchViaHTTP } from 'next-test-utils' + +describe('trailingSlash:true with rewrites and getStaticProps', () => { + let next: NextInstance + + if ((global as any).isNextDeploy) { + it('should skip for deploy mode for now', () => {}) + return + } + + beforeAll(async () => { + next = await createNext({ + files: new FileRef(join(__dirname, './app')), + }) + }) + afterAll(() => next.destroy()) + + it('should work', async () => { + const res = await fetchViaHTTP(next.url, '/country') + expect(await res.text()).toContain('Welcome home') + }) +})