From 5f7caf2765cc88e3f2fe62417e1b2828c96c4f47 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 21 Sep 2022 10:50:28 +0200 Subject: [PATCH 1/2] v12.3.2-canary.0 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/next-bundle-analyzer/package.json | 2 +- packages/next-codemod/package.json | 2 +- packages/next-env/package.json | 2 +- packages/next-mdx/package.json | 2 +- packages/next-plugin-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- 16 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lerna.json b/lerna.json index 34bd0fd6ae494d..258e54c72d1ac7 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "12.3.1" + "version": "12.3.2-canary.0" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 2e9cd6d4a45385..a7ab39f0a1820f 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "12.3.1", + "version": "12.3.2-canary.0", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 4757609169e5e8..532fc3a72ca147 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "ESLint configuration used by NextJS.", "main": "index.js", "license": "MIT", @@ -9,7 +9,7 @@ "directory": "packages/eslint-config-next" }, "dependencies": { - "@next/eslint-plugin-next": "12.3.1", + "@next/eslint-plugin-next": "12.3.2-canary.0", "@rushstack/eslint-patch": "^1.1.3", "@typescript-eslint/parser": "^5.21.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 043622086d7e89..801d903f990731 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "ESLint plugin for NextJS.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 0d8e54ecf68bd8..72318cd3d97e21 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "12.3.1", + "version": "12.3.2-canary.0", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index b785bc248a3932..b0c701219b952f 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "12.3.1", + "version": "12.3.2-canary.0", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index bdfa78165e98c8..e38620f1710cea 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "12.3.1", + "version": "12.3.2-canary.0", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index 4f3494b43cdac7..c0ea228acc6a34 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "12.3.1", + "version": "12.3.2-canary.0", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 52916bd81e1809..6009f7375f19b7 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "12.3.1", + "version": "12.3.2-canary.0", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index 1edfe30cda574d..b065aee308e64a 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index 4cde648288553b..d1a32f050530eb 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index 6c30933d68b1f9..cad052d086abed 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "12.3.1", + "version": "12.3.2-canary.0", "private": true, "scripts": { "build-native": "napi build --platform -p next-swc-napi --cargo-name next_swc_napi native --features plugin", diff --git a/packages/next/package.json b/packages/next/package.json index 79c76b77cf1fca..543cb1ac2aed22 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -68,7 +68,7 @@ ] }, "dependencies": { - "@next/env": "12.3.1", + "@next/env": "12.3.2-canary.0", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", @@ -119,11 +119,11 @@ "@hapi/accept": "5.0.2", "@napi-rs/cli": "2.7.0", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "12.3.1", - "@next/polyfill-nomodule": "12.3.1", - "@next/react-dev-overlay": "12.3.1", - "@next/react-refresh-utils": "12.3.1", - "@next/swc": "12.3.1", + "@next/polyfill-module": "12.3.2-canary.0", + "@next/polyfill-nomodule": "12.3.2-canary.0", + "@next/react-dev-overlay": "12.3.2-canary.0", + "@next/react-refresh-utils": "12.3.2-canary.0", + "@next/swc": "12.3.2-canary.0", "@segment/ajv-human-errors": "2.1.2", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index c83baa837d4b3e..50fe5926156a24 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index c1f20f24ec94ae..907be4826daff3 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "12.3.1", + "version": "12.3.2-canary.0", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4da886576a755e..aee0111858f5a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -367,7 +367,7 @@ importers: packages/eslint-config-next: specifiers: - '@next/eslint-plugin-next': 12.3.1 + '@next/eslint-plugin-next': 12.3.2-canary.0 '@rushstack/eslint-patch': ^1.1.3 '@typescript-eslint/parser': ^5.21.0 eslint-import-resolver-node: ^0.3.6 @@ -423,12 +423,12 @@ importers: '@hapi/accept': 5.0.2 '@napi-rs/cli': 2.7.0 '@napi-rs/triples': 1.1.0 - '@next/env': 12.3.1 - '@next/polyfill-module': 12.3.1 - '@next/polyfill-nomodule': 12.3.1 - '@next/react-dev-overlay': 12.3.1 - '@next/react-refresh-utils': 12.3.1 - '@next/swc': 12.3.1 + '@next/env': 12.3.2-canary.0 + '@next/polyfill-module': 12.3.2-canary.0 + '@next/polyfill-nomodule': 12.3.2-canary.0 + '@next/react-dev-overlay': 12.3.2-canary.0 + '@next/react-refresh-utils': 12.3.2-canary.0 + '@next/swc': 12.3.2-canary.0 '@segment/ajv-human-errors': 2.1.2 '@swc/helpers': 0.4.11 '@taskr/clear': 1.1.0 From 2b9afcfea3ce1f43833da26324b88693f2b11c8c Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 21 Sep 2022 15:47:31 +0200 Subject: [PATCH 2/2] Change flight querystring to header (#40752) --- .../client/components/app-router.client.tsx | 34 +++++---- packages/next/server/app-render.tsx | 26 +++++-- packages/next/server/base-server.ts | 2 +- packages/next/server/next-server.ts | 3 +- packages/next/server/web/adapter.ts | 19 +++-- packages/next/server/web/next-url.ts | 74 +------------------ test/e2e/app-dir/app/middleware.js | 2 +- test/e2e/app-dir/index.test.ts | 19 ++++- test/e2e/app-dir/rsc-basic.test.ts | 47 +++++++----- test/e2e/switchable-runtime/index.test.ts | 22 +++--- 10 files changed, 111 insertions(+), 137 deletions(-) diff --git a/packages/next/client/components/app-router.client.tsx b/packages/next/client/components/app-router.client.tsx index d788d719dda633..f933f4d1bb0b33 100644 --- a/packages/next/client/components/app-router.client.tsx +++ b/packages/next/client/components/app-router.client.tsx @@ -29,11 +29,9 @@ import { } from './hooks-client-context' import { useReducerWithReduxDevtools } from './use-reducer-with-devtools' -function urlToUrlWithoutFlightParameters(url: string): URL { +function urlToUrlWithoutFlightMarker(url: string): URL { const urlWithoutFlightParameters = new URL(url, location.origin) - urlWithoutFlightParameters.searchParams.delete('__flight__') - urlWithoutFlightParameters.searchParams.delete('__flight_router_state_tree__') - urlWithoutFlightParameters.searchParams.delete('__flight_prefetch__') + // TODO-APP: handle .rsc for static export case return urlWithoutFlightParameters } @@ -45,22 +43,26 @@ export async function fetchServerResponse( flightRouterState: FlightRouterState, prefetch?: true ): Promise<[FlightData: FlightData, canonicalUrlOverride: URL | undefined]> { - const flightUrl = new URL(url) - const searchParams = flightUrl.searchParams - // Enable flight response - searchParams.append('__flight__', '1') - // Provide the current router state - searchParams.append( - '__flight_router_state_tree__', - JSON.stringify(flightRouterState) - ) + const headers: { + __flight__: '1' + __flight_router_state_tree__: string + __flight_prefetch__?: '1' + } = { + // Enable flight response + __flight__: '1', + // Provide the current router state + __flight_router_state_tree__: JSON.stringify(flightRouterState), + } if (prefetch) { - searchParams.append('__flight_prefetch__', '1') + // Enable prefetch response + headers.__flight_prefetch__ = '1' } - const res = await fetch(flightUrl.toString()) + const res = await fetch(url.toString(), { + headers, + }) const canonicalUrl = res.redirected - ? urlToUrlWithoutFlightParameters(res.url) + ? urlToUrlWithoutFlightMarker(res.url) : undefined // Handle the `fetch` readable stream that can be unwrapped by `React.use`. diff --git a/packages/next/server/app-render.tsx b/packages/next/server/app-render.tsx index 8d47e3411cbab9..12a87e12a84f6e 100644 --- a/packages/next/server/app-render.tsx +++ b/packages/next/server/app-render.tsx @@ -1,4 +1,4 @@ -import type { IncomingMessage, ServerResponse } from 'http' +import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http' import type { LoadComponentsReturnType } from './load-components' import type { ServerRuntime } from '../types' @@ -493,6 +493,20 @@ function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined { return nonce } +const FLIGHT_PARAMETERS = [ + '__flight__', + '__flight_router_state_tree__', + '__flight_prefetch__', +] as const + +function headersWithoutFlight(headers: IncomingHttpHeaders) { + const newHeaders = { ...headers } + for (const param of FLIGHT_PARAMETERS) { + delete newHeaders[param] + } + return newHeaders +} + export async function renderToHTMLOrFlight( req: IncomingMessage, res: ServerResponse, @@ -545,8 +559,8 @@ export async function renderToHTMLOrFlight( ComponentMod, } = renderOpts - const isFlight = query.__flight__ !== undefined - const isPrefetch = query.__flight_prefetch__ !== undefined + const isFlight = req.headers.__flight__ !== undefined + const isPrefetch = req.headers.__flight_prefetch__ !== undefined // Handle client-side navigation to pages directory if (isFlight && isPagesDir) { @@ -569,8 +583,8 @@ export async function renderToHTMLOrFlight( * Router state provided from the client-side router. Used to handle rendering from the common layout down. */ const providedFlightRouterState: FlightRouterState = isFlight - ? query.__flight_router_state_tree__ - ? JSON.parse(query.__flight_router_state_tree__ as string) + ? req.headers.__flight_router_state_tree__ + ? JSON.parse(req.headers.__flight_router_state_tree__ as string) : {} : undefined @@ -584,7 +598,7 @@ export async function renderToHTMLOrFlight( | typeof import('../client/components/hot-reloader.client').default | null - const headers = req.headers + const headers = headersWithoutFlight(req.headers) // TODO-APP: fix type of req // @ts-expect-error const cookies = req.cookies diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index cccb74732abed3..788aadf6613776 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -1032,7 +1032,7 @@ export default abstract class Server { // Don't delete query.__flight__ yet, it still needs to be used in renderToHTML later const isFlightRequest = Boolean( - this.serverComponentManifest && query.__flight__ + this.serverComponentManifest && req.headers.__flight__ ) // we need to ensure the status code if /404 is visited directly diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 4ca035f9800953..57ca093018fba8 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -825,7 +825,7 @@ export default class NextNodeServer extends BaseServer { if ( this.nextConfig.experimental.appDir && - (renderOpts.isAppPath || query.__flight__) + (renderOpts.isAppPath || req.headers.__flight__) ) { const isPagesDir = !renderOpts.isAppPath return appRenderToHTMLOrFlight( @@ -981,7 +981,6 @@ export default class NextNodeServer extends BaseServer { __nextDataReq: query.__nextDataReq, __nextLocale: query.__nextLocale, __nextDefaultLocale: query.__nextDefaultLocale, - __flight__: query.__flight__, } as NextParsedUrlQuery) : query), // For appDir params is excluded. diff --git a/packages/next/server/web/adapter.ts b/packages/next/server/web/adapter.ts index 0a03f3f8936c5f..c808a2b02f8235 100644 --- a/packages/next/server/web/adapter.ts +++ b/packages/next/server/web/adapter.ts @@ -35,6 +35,12 @@ class NextRequestHint extends NextRequest { } } +const FLIGHT_PARAMETERS = [ + '__flight__', + '__flight_router_state_tree__', + '__flight_prefetch__', +] as const + export async function adapter(params: { handler: NextMiddleware page: string @@ -58,11 +64,12 @@ export async function adapter(params: { requestUrl.pathname = '/' } - // Preserve flight data. - const flightSearchParameters = requestUrl.flightSearchParameters + const requestHeaders = fromNodeHeaders(params.request.headers) // Parameters should only be stripped for middleware if (!isEdgeRendering) { - requestUrl.flightSearchParameters = undefined + for (const param of FLIGHT_PARAMETERS) { + requestHeaders.delete(param) + } } // Strip internal query parameters off the request. @@ -74,7 +81,7 @@ export async function adapter(params: { init: { body: params.request.body, geo: params.request.geo, - headers: fromNodeHeaders(params.request.headers), + headers: requestHeaders, ip: params.request.ip, method: params.request.method, nextConfig: params.request.nextConfig, @@ -112,8 +119,6 @@ export async function adapter(params: { if (rewriteUrl.host === request.nextUrl.host) { rewriteUrl.buildId = buildId || rewriteUrl.buildId - rewriteUrl.flightSearchParameters = - flightSearchParameters || rewriteUrl.flightSearchParameters response.headers.set('x-middleware-rewrite', String(rewriteUrl)) } @@ -151,8 +156,6 @@ export async function adapter(params: { if (redirectURL.host === request.nextUrl.host) { redirectURL.buildId = buildId || redirectURL.buildId - redirectURL.flightSearchParameters = - flightSearchParameters || redirectURL.flightSearchParameters response.headers.set('Location', String(redirectURL)) } diff --git a/packages/next/server/web/next-url.ts b/packages/next/server/web/next-url.ts index 5f05ec8e8ddb85..9ed9fc34a4a2c2 100644 --- a/packages/next/server/web/next-url.ts +++ b/packages/next/server/web/next-url.ts @@ -15,12 +15,6 @@ interface Options { } } -const FLIGHT_PARAMETERS = [ - '__flight__', - '__flight_router_state_tree__', - '__flight_prefetch__', -] as const - const REGEX_LOCALHOST_HOSTNAME = /(?!^https?:\/\/)(127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|::1|localhost)/ @@ -31,28 +25,6 @@ function parseURL(url: string | URL, base?: string | URL) { ) } -function parseFlightParameters( - searchParams: URLSearchParams -): Record | undefined { - let flightSearchParameters: Record = {} - let flightSearchParametersUpdated = false - for (const name of FLIGHT_PARAMETERS) { - const value = searchParams.get(name) - if (value === null) { - continue - } - - flightSearchParameters[name] = value - flightSearchParametersUpdated = true - } - - if (!flightSearchParametersUpdated) { - return undefined - } - - return flightSearchParameters -} - const Internal = Symbol('NextURLInternal') export class NextURL { @@ -118,9 +90,6 @@ export class NextURL { this[Internal].buildId = pathnameInfo.buildId this[Internal].locale = pathnameInfo.locale ?? defaultLocale this[Internal].trailingSlash = pathnameInfo.trailingSlash - this[Internal].flightSearchParameters = parseFlightParameters( - this[Internal].url.searchParams - ) } private formatPathname() { @@ -137,22 +106,7 @@ export class NextURL { } private formatSearch() { - const flightSearchParameters = this[Internal].flightSearchParameters - // If no flight parameters are set, return the search string as is. - // This is a fast path to ensure URLSearchParams only has to be recreated on Flight requests. - if (!flightSearchParameters) { - return this[Internal].url.search - } - - // Create separate URLSearchParams to ensure the original search string is not modified. - const searchParams = new URLSearchParams(this[Internal].url.searchParams) - // If any exist this loop is always limited to the amount of FLIGHT_PARAMETERS. - for (const name in flightSearchParameters) { - searchParams.set(name, flightSearchParameters[name]) - } - - const params = searchParams.toString() - return params === '' ? '' : `?${params}` + return this[Internal].url.search } public get buildId() { @@ -163,32 +117,6 @@ export class NextURL { this[Internal].buildId = buildId } - public get flightSearchParameters() { - return this[Internal].flightSearchParameters - } - - public set flightSearchParameters( - flightSearchParams: Record | undefined - ) { - if (flightSearchParams) { - for (const name of FLIGHT_PARAMETERS) { - // Ensure only the provided values are set - if (flightSearchParams[name]) { - this[Internal].url.searchParams.set(name, flightSearchParams[name]) - } else { - // Delete the ones that are not provided as flightData should be overridden. - this[Internal].url.searchParams.delete(name) - } - } - } else { - for (const name of FLIGHT_PARAMETERS) { - this[Internal].url.searchParams.delete(name) - } - } - - this[Internal].flightSearchParameters = flightSearchParams - } - public get locale() { return this[Internal].locale ?? '' } diff --git a/test/e2e/app-dir/app/middleware.js b/test/e2e/app-dir/app/middleware.js index 4dfacac7fc684b..8057bba59bfa13 100644 --- a/test/e2e/app-dir/app/middleware.js +++ b/test/e2e/app-dir/app/middleware.js @@ -20,7 +20,7 @@ export function middleware(request) { : 'redirect' const internal = ['__flight__', '__flight_router_state_tree__'] - if (internal.some((name) => request.nextUrl.searchParams.has(name))) { + if (internal.some((name) => request.headers.has(name))) { return NextResponse[method](new URL('/internal/failure', request.url)) } diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 9dc1ef82d10b52..93bb4ed7ddeab8 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -38,13 +38,28 @@ describe('app dir', () => { it('should use application/octet-stream for flight', async () => { const res = await fetchViaHTTP( next.url, - '/dashboard/deployments/123?__flight__' + '/dashboard/deployments/123', + {}, + { + headers: { + __flight__: '1', + }, + } ) expect(res.headers.get('Content-Type')).toBe('application/octet-stream') }) it('should use application/octet-stream for flight with edge runtime', async () => { - const res = await fetchViaHTTP(next.url, '/dashboard?__flight__') + const res = await fetchViaHTTP( + next.url, + '/dashboard', + {}, + { + headers: { + __flight__: '1', + }, + } + ) expect(res.headers.get('Content-Type')).toBe('application/octet-stream') }) diff --git a/test/e2e/app-dir/rsc-basic.test.ts b/test/e2e/app-dir/rsc-basic.test.ts index 4d5196ffcad32d..95b2f3457717b9 100644 --- a/test/e2e/app-dir/rsc-basic.test.ts +++ b/test/e2e/app-dir/rsc-basic.test.ts @@ -94,7 +94,8 @@ describe('app dir - react server components', () => { '__nextDefaultLocale', '__nextIsNotFound', '__flight__', - '__flight_router_path__', + '__flight_router_state_tree__', + '__flight_prefetch__', ] const hasNextInternalQuery = inlineFlightContents.some((content) => @@ -110,14 +111,15 @@ describe('app dir - react server components', () => { beforePageLoad(page) { page.on('request', (request) => { requestsCount++ - const url = request.url() - if ( - url.includes('__flight__=1') && - // Prefetches also include `__flight__` - !url.includes('__flight_prefetch__=1') - ) { - hasFlightRequest = true - } + return request.allHeaders().then((headers) => { + if ( + headers.__flight__ === '1' && + // Prefetches also include `__flight__` + headers.__flight_prefetch__ !== '1' + ) { + hasFlightRequest = true + } + }) }) }, }) @@ -215,14 +217,14 @@ describe('app dir - react server components', () => { const browser = await webdriver(next.url, '/root', { beforePageLoad(page) { page.on('request', (request) => { - const url = request.url() - if ( - url.includes('__flight__=1') && - // Prefetches also include `__flight__` - !url.includes('__flight_prefetch__=1') - ) { - hasFlightRequest = true - } + return request.allHeaders().then((headers) => { + if ( + headers.__flight__ === '1' && + headers.__flight_prefetch__ !== '1' + ) { + hasFlightRequest = true + } + }) }) }, }) @@ -336,7 +338,16 @@ describe('app dir - react server components', () => { }) it('should support streaming for flight response', async () => { - await fetchViaHTTP(next.url, '/?__flight__=1').then(async (response) => { + await fetchViaHTTP( + next.url, + '/', + {}, + { + headers: { + __flight__: '1', + }, + } + ).then(async (response) => { const result = await resolveStreamResponse(response) expect(result).toContain('component:index.server') }) diff --git a/test/e2e/switchable-runtime/index.test.ts b/test/e2e/switchable-runtime/index.test.ts index 774efac58a7110..153cc5abde65fc 100644 --- a/test/e2e/switchable-runtime/index.test.ts +++ b/test/e2e/switchable-runtime/index.test.ts @@ -119,10 +119,11 @@ describe('Switchable runtime', () => { const browser = await webdriver(context.appPort, '/node', { beforePageLoad(page) { page.on('request', (request) => { - const url = request.url() - if (/\?__flight__=1/.test(url)) { - flightRequest = url - } + return request.allHeaders().then((headers) => { + if (headers.__flight__ === '1') { + flightRequest = request.url() + } + }) }) }, }) @@ -136,7 +137,7 @@ describe('Switchable runtime', () => { () => browser.eval('document.documentElement.innerHTML'), /This is a SSR RSC page/ ) - expect(flightRequest).toContain('/node-rsc-ssr?__flight__=1') + expect(flightRequest).toContain('/node-rsc-ssr') }) it.skip('should support client side navigation to ssg rsc pages', async () => { @@ -678,10 +679,11 @@ describe('Switchable runtime', () => { const browser = await webdriver(context.appPort, '/node', { beforePageLoad(page) { page.on('request', (request) => { - const url = request.url() - if (/\?__flight__=1/.test(url)) { - flightRequest = url - } + request.allHeaders().then((headers) => { + if (headers.__flight__ === '1') { + flightRequest = request.url() + } + }) }) }, }) @@ -691,7 +693,7 @@ describe('Switchable runtime', () => { expect(await browser.elementByCss('body').text()).toContain( 'This is a SSR RSC page.' ) - expect(flightRequest).toContain('/node-rsc-ssr?__flight__=1') + expect(flightRequest).toContain('/node-rsc-ssr') }) it.skip('should support client side navigation to ssg rsc pages', async () => {