From 1b033423dcc43b51752013cb8807051e66917d58 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sat, 1 Aug 2020 13:51:47 +0200 Subject: [PATCH] Fix asPath of rewrite without basePath (#15760) Fixes https://github.com/vercel/next.js/issues/15755 --- packages/next/client/index.js | 12 +---- .../next/next-server/lib/router/router.ts | 7 ++- test/integration/basepath/test/index.test.js | 53 +++++++++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/packages/next/client/index.js b/packages/next/client/index.js index fc7d439a8a..23fe1c7a4c 100644 --- a/packages/next/client/index.js +++ b/packages/next/client/index.js @@ -9,7 +9,7 @@ import { RouterContext } from '../next-server/lib/router-context' import { isDynamicRoute } from '../next-server/lib/router/utils/is-dynamic' import * as envConfig from '../next-server/lib/runtime-config' import { getURL, loadGetInitialProps, ST } from '../next-server/lib/utils' -import { delBasePath } from '../next-server/lib/router/router' +import { hasBasePath, delBasePath } from '../next-server/lib/router/router' import initHeadManager from './head-manager' import PageLoader from './page-loader' import measureWebVitals from './performance-relayer' @@ -52,15 +52,7 @@ envConfig.setConfig({ let asPath = getURL() // make sure not to attempt stripping basePath for 404s -if ( - page !== '/404' && - !( - page === '/_error' && - hydrateProps && - hydrateProps.pageProps && - hydrateProps.pageProps.statusCode === 404 - ) -) { +if (hasBasePath(asPath)) { asPath = delBasePath(asPath) } diff --git a/packages/next/next-server/lib/router/router.ts b/packages/next/next-server/lib/router/router.ts index b6ac61c8ee..44822b6650 100644 --- a/packages/next/next-server/lib/router/router.ts +++ b/packages/next/next-server/lib/router/router.ts @@ -30,6 +30,10 @@ function buildCancellationError() { }) } +export function hasBasePath(path: string): boolean { + return path === basePath || path.startsWith(basePath + '/') +} + export function addBasePath(path: string): string { return basePath ? path === '/' @@ -269,7 +273,6 @@ export default class Router implements BaseRouter { if (as.substr(0, 2) !== '//') { // in order for `e.state` to work on the `onpopstate` event // we have to register the initial route upon initialization - this.changeState( 'replaceState', formatWithValidation({ pathname: addBasePath(pathname), query }), @@ -450,7 +453,7 @@ export default class Router implements BaseRouter { this.abortComponentLoad(this._inFlightRoute) } - const cleanedAs = delBasePath(as) + const cleanedAs = hasBasePath(as) ? delBasePath(as) : as this._inFlightRoute = as // If the url change is only related to a hash change diff --git a/test/integration/basepath/test/index.test.js b/test/integration/basepath/test/index.test.js index 593d9b23e9..8eef6545ed 100644 --- a/test/integration/basepath/test/index.test.js +++ b/test/integration/basepath/test/index.test.js @@ -141,6 +141,38 @@ const runTests = (context, dev = false) => { expect(html).toContain('getServerSideProps') }) + it('should have correct asPath for rewrite without basePath', async () => { + const browser = await webdriver(context.appPort, '/rewrite-no-basePath') + expect(await browser.eval(() => window.location.pathname)).toBe( + '/rewrite-no-basePath' + ) + expect(await browser.eval(() => window.next.router.asPath)).toBe( + '/rewrite-no-basePath' + ) + expect(await browser.eval(() => window.next.router.pathname)).toBe('/gssp') + }) + + it('should have correct asPath for rewrite without basePath on back()', async () => { + const browser = await webdriver(context.appPort, '/rewrite-no-basePath') + await browser.eval(() => (window.navigationMarker = true)) + await browser.eval(() => window.next.router.push('/hello')) + await check( + () => browser.eval(() => window.location.pathname), + '/docs/hello' + ) + await browser.back() + await check( + () => browser.eval(() => window.location.pathname), + '/rewrite-no-basePath' + ) + await check( + () => browser.eval(() => window.next.router.asPath), + '/rewrite-no-basePath' + ) + expect(await browser.eval(() => window.next.router.pathname)).toBe('/gssp') + expect(await browser.eval(() => window.navigationMarker)).toBe(true) + }) + it('should redirect with basePath by default', async () => { const res = await fetchViaHTTP( context.appPort, @@ -216,6 +248,27 @@ const runTests = (context, dev = false) => { expect(pathname).toBe('/missing') }) + it('should handle 404 urls that start with basePath', async () => { + const browser = await webdriver(context.appPort, '/docshello') + expect(await browser.eval(() => window.next.router.asPath)).toBe( + '/docshello' + ) + expect(await browser.eval(() => window.location.pathname)).toBe( + '/docshello' + ) + }) + + it('should navigating back to a non-basepath 404 that starts with basepath', async () => { + const browser = await webdriver(context.appPort, '/docshello') + await browser.eval(() => window.next.router.push('/hello')) + await browser.waitForElementByCss('#pathname') + await browser.back() + check(() => browser.eval(() => window.location.pathname), '/docshello') + expect(await browser.eval(() => window.next.router.asPath)).toBe( + '/docshello' + ) + }) + it('should update dynamic params after mount correctly', async () => { const browser = await webdriver(context.appPort, '/docs/hello-dynamic') const text = await browser.elementByCss('#slug').text()