Files
next.js/test/e2e/app-dir/ppr-root-param-rsc-fallback/app/[tenant]/layout.tsx
56d75a0b77 Fix invalid HTML response for route-level RSC requests in deployment adapter (#91541)
In a deployed environment, `onCacheEntryV2` determines whether a
postponed response is HTML-origin or RSC-origin by checking whether
meta.url ends with `.rsc`.

For some dynamic full-route RSC requests, Next was passing a URL with
query params into onCacheEntry, for example:
`/[tenant]/samples.rsc?nxtPtenant=tenant-x`

Because that string does not end with .rsc, `onCacheEntryV2`
misclassified the request as HTML and treated it as text/html instead of
an RSC response.

This PR normalizes the URL before passing it to `onCacheEntry`, so the
callback receives the pathname rather than the full URL-with-query.

---------

Co-authored-by: JJ Kasper <[email protected]>
2026-03-18 12:17:31 -07:00

53 lines
964 B
TypeScript

import { Suspense } from 'react'
import type { ReactNode } from 'react'
export function generateStaticParams() {
return [{ tenant: 'tenant-a' }, { tenant: 'tenant-b' }]
}
async function CachedTenantMarker({
params,
}: {
params: Promise<{ tenant: string }>
}) {
'use cache'
return (
<div hidden id="cached-tenant-marker">
{(await params).tenant}
</div>
)
}
async function EnsureTenant({
params,
}: {
params: Promise<{ tenant: string }>
}) {
const { tenant } = await params
if (typeof tenant !== 'string') {
throw new Error('Failed to read `tenant` from params')
}
return null
}
export default function TenantLayout({
children,
params,
}: {
children: ReactNode
params: Promise<{ tenant: string }>
}) {
return (
<>
<Suspense>{children}</Suspense>
<Suspense fallback={null}>
<CachedTenantMarker params={params} />
</Suspense>
<EnsureTenant params={params} />
</>
)
}