mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 21:07:46 +00:00
[next]: ensure user rewrites match to action outputs (#11628)
The builder normalizes user rewrites that target pages that have special outputs (`.rsc`, `.prefetch.rsc`). When we added support for `.action` outputs, we need to perform this same normalization to ensure that user rewrites still match. If the rewrite was a greedy match (eg `/:path*`) it'd be ok, but more specific rewrites would have the issue.
This commit is contained in:
5
.changeset/smart-horses-rescue.md
Normal file
5
.changeset/smart-horses-rescue.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@vercel/next': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Ensure user rewrites still match to action outputs
|
||||||
@@ -252,9 +252,19 @@ export async function serverBuild({
|
|||||||
|
|
||||||
for (const rewrite of afterFilesRewrites) {
|
for (const rewrite of afterFilesRewrites) {
|
||||||
if (rewrite.src && rewrite.dest) {
|
if (rewrite.src && rewrite.dest) {
|
||||||
|
// ensures that userland rewrites are still correctly matched to their special outputs
|
||||||
|
// PPR should match .prefetch.rsc, .rsc, and .action
|
||||||
|
// non-PPR should match .rsc and .action
|
||||||
|
// we only add `.action` handling to the regex if flagged on in the build
|
||||||
|
const rscSuffix = isAppPPREnabled
|
||||||
|
? `(\\.prefetch)?\\.rsc${hasActionOutputSupport ? '|\\.action' : ''}`
|
||||||
|
: hasActionOutputSupport
|
||||||
|
? '(\\.action|\\.rsc)'
|
||||||
|
: '\\.rsc';
|
||||||
|
|
||||||
rewrite.src = rewrite.src.replace(
|
rewrite.src = rewrite.src.replace(
|
||||||
/\/?\(\?:\/\)\?/,
|
/\/?\(\?:\/\)\?/,
|
||||||
`(?<rscsuff>${isAppPPREnabled ? '(\\.prefetch)?' : ''}\\.rsc)?(?:/)?`
|
`(?<rscsuff>${rscSuffix})?(?:/)?`
|
||||||
);
|
);
|
||||||
let destQueryIndex = rewrite.dest.indexOf('?');
|
let destQueryIndex = rewrite.dest.indexOf('?');
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,26 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
|||||||
expect(body).toContain(JSON.stringify(['id', '1', 'd']));
|
expect(body).toContain(JSON.stringify(['id', '1', 'd']));
|
||||||
expect(body).not.toContain(JSON.stringify(['id', '1.action', 'd']));
|
expect(body).not.toContain(JSON.stringify(['id', '1.action', 'd']));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work when a rewrite targets an action', async () => {
|
||||||
|
const targetPath = `${basePath}/rsc/static`;
|
||||||
|
const canonicalPath = `/rewrite/${basePath}/rsc/static`;
|
||||||
|
const actionId = findActionId(targetPath, runtime);
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${ctx.deploymentUrl}${canonicalPath}`,
|
||||||
|
generateFormDataPayload(actionId)
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200);
|
||||||
|
expect(res.headers.get('x-matched-path')).toBe(targetPath + '.action');
|
||||||
|
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||||
|
if (runtime === 'node') {
|
||||||
|
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||||
|
} else {
|
||||||
|
expect(res.headers.get('x-edge-runtime')).toBe('1');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('pages', () => {
|
describe('pages', () => {
|
||||||
|
|||||||
@@ -1 +1,14 @@
|
|||||||
module.exports = {};
|
module.exports = {
|
||||||
|
rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/rewrite/rsc/static',
|
||||||
|
destination: '/rsc/static',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/rewrite/edge/rsc/static',
|
||||||
|
destination: '/edge/rsc/static',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user