Skip to content

Commit

Permalink
[middleware] Fix hydration for rewrites to dynamic pages (#32534)
Browse files Browse the repository at this point in the history
Fixes #32302 

This PR fixes an issue on hydration where we rewrote using a middleware to a dynamic path. In such cases we need to run preflight to find out the middleware operation metadata.

## Bug

- [X] Related issues linked using `fixes #number`
- [X] Integration tests added
- [X] Errors have helpful link attached, see `contributing.md`
  • Loading branch information
javivelasco committed Dec 15, 2021
1 parent e75361f commit 3da1f17
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
13 changes: 8 additions & 5 deletions packages/next/shared/lib/router/router.ts
Expand Up @@ -1134,11 +1134,14 @@ export default class Router implements BaseRouter {
resolvedAs = delLocale(delBasePath(resolvedAs), this.locale)

/**
* If the route update was triggered for client-side hydration then
* do not check the preflight request. Otherwise when rendering
* a page with refresh it might get into an infinite loop.
* If the route update was triggered for client-side hydration and
* the rendered route is not dynamic do not check the preflight
* request as it is not necessary.
*/
if ((options as any)._h !== 1) {
if (
(options as any)._h !== 1 ||
isDynamicRoute(removePathTrailingSlash(pathname))
) {
const effect = await this._preflightRequest({
as,
cache: process.env.NODE_ENV === 'production',
Expand All @@ -1158,7 +1161,7 @@ export default class Router implements BaseRouter {
} else if (effect.type === 'redirect' && effect.destination) {
window.location.href = effect.destination
return new Promise(() => {})
} else if (effect.type === 'refresh') {
} else if (effect.type === 'refresh' && as !== window.location.pathname) {
window.location.href = as
return new Promise(() => {})
}
Expand Down
@@ -0,0 +1,5 @@
const PartsPage = () => {
return <div className="title">Parts page</div>
}

export default PartsPage
Expand Up @@ -57,6 +57,10 @@ export async function middleware(request) {
return fetch(url)
}

if (url.pathname.endsWith('/dynamic-replace')) {
return NextResponse.rewrite('/_interface/dynamic-path')
}

return new Response(null, {
headers: {
'req-url-basepath': request.nextUrl.basePath,
Expand Down
11 changes: 11 additions & 0 deletions test/integration/middleware/core/test/index.test.js
Expand Up @@ -455,6 +455,17 @@ function interfaceTests(locale = '') {
)
expect(res.headers.get('x-dynamic-path')).toBe('true')
})

it(`${locale} renders correctly rewriting to a different dynamic path`, async () => {
const browser = await webdriver(
context.appPort,
'/interface/dynamic-replace'
)
const element = await browser.elementByCss('.title')
expect(await element.text()).toEqual('Parts page')
const logs = await browser.log()
expect(logs.every((log) => log.source === 'log')).toEqual(true)
})
}

function getCookieFromResponse(res, cookieName) {
Expand Down

0 comments on commit 3da1f17

Please sign in to comment.