diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 27316dd1fd3e035..f3cb0d914bbf816 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -763,7 +763,6 @@ export default class NextNodeServer extends BaseServer { params, page, appPaths: null, - isAppPath: false, }) if (handledAsEdgeFunction) { @@ -913,7 +912,6 @@ export default class NextNodeServer extends BaseServer { params: ctx.renderOpts.params, page, appPaths, - isAppPath, }) return null } @@ -2031,12 +2029,12 @@ export default class NextNodeServer extends BaseServer { params: Params | undefined page: string appPaths: string[] | null - isAppPath: boolean onWarning?: (warning: Error) => void }): Promise { let middlewareInfo: ReturnType | undefined - const page = params.page + const { query, page } = params + await this.ensureEdgeFunction({ page, appPaths: params.appPaths }) middlewareInfo = this.getEdgeFunctionInfo({ page, @@ -2048,21 +2046,20 @@ export default class NextNodeServer extends BaseServer { } // For middleware to "fetch" we must always provide an absolute URL - const isDataReq = !!params.query.__nextDataReq - const query = urlQueryToSearchParams(params.query).toString() - const locale = params.query.__nextLocale - // Use original pathname (without `/page`) instead of appPath for url - let normalizedPathname = params.page + const locale = query.__nextLocale + const isDataReq = !!query.__nextDataReq + const queryString = urlQueryToSearchParams(query).toString() if (isDataReq) { params.req.headers['x-nextjs-data'] = '1' } + let normalizedPathname = normalizeAppPath(page) if (isDynamicRoute(normalizedPathname)) { - const routeRegex = getNamedRouteRegex(params.page) + const routeRegex = getNamedRouteRegex(normalizedPathname) normalizedPathname = interpolateDynamicPath( - params.page, - Object.assign({}, params.params, params.query), + normalizedPathname, + Object.assign({}, params.params, query), routeRegex ) } @@ -2070,7 +2067,7 @@ export default class NextNodeServer extends BaseServer { const url = `${getRequestMeta(params.req, '_protocol')}://${ this.hostname }:${this.port}${locale ? `/${locale}` : ''}${normalizedPathname}${ - query ? `?${query}` : '' + queryString ? `?${queryString}` : '' }` if (!url.startsWith('http')) { diff --git a/test/e2e/app-dir/rsc-basic.test.ts b/test/e2e/app-dir/rsc-basic.test.ts index c9996fe5ec0d286..0debb6818399675 100644 --- a/test/e2e/app-dir/rsc-basic.test.ts +++ b/test/e2e/app-dir/rsc-basic.test.ts @@ -340,6 +340,20 @@ describe('app dir - react server components', () => { expect(head).toMatch(/{color:(\s*)blue;?}/) }) + it('should stick to the url without trailing /page suffix', async () => { + const browser = await webdriver(next.url, '/edge/dynamic') + const indexUrl = await browser.url() + + await browser.loadPage(`${next.url}/edge/dynamic/123`, { + disableCache: false, + beforePageLoad: null, + }) + + const dynamicRouteUrl = await browser.url() + expect(indexUrl).toBe(`${next.url}/edge/dynamic`) + expect(dynamicRouteUrl).toBe(`${next.url}/edge/dynamic/123`) + }) + it('should support streaming for flight response', async () => { await fetchViaHTTP(next.url, '/?__flight__=1').then(async (response) => { const result = await resolveStreamResponse(response) diff --git a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.server.js b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.server.js new file mode 100644 index 000000000000000..87bac2ff6be9ec8 --- /dev/null +++ b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/[id]/page.server.js @@ -0,0 +1,7 @@ +export default function page() { + return 'dynamic route [id] page' +} + +export const config = { + runtime: 'experimental-edge', +} diff --git a/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.server.js b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.server.js new file mode 100644 index 000000000000000..1b83f0120a6ab43 --- /dev/null +++ b/test/e2e/app-dir/rsc-basic/app/edge/dynamic/page.server.js @@ -0,0 +1,7 @@ +export default function page() { + return 'dynamic route index page' +} + +export const config = { + runtime: 'experimental-edge', +} diff --git a/test/e2e/app-dir/rsc-basic/next.config.js b/test/e2e/app-dir/rsc-basic/next.config.js index ca13fceaff38c09..eab44b6855ae317 100644 --- a/test/e2e/app-dir/rsc-basic/next.config.js +++ b/test/e2e/app-dir/rsc-basic/next.config.js @@ -7,4 +7,14 @@ module.exports = { appDir: true, serverComponents: true, }, + rewrites: async () => { + return { + afterFiles: [ + { + source: '/rewritten-to-edge-dynamic', + destination: '/edge/dynamic', + }, + ], + } + }, }