Skip to content

Commit 23ed1df

Browse files
authored
feat: add option to align header priorization execution order (#981)
* feat: add option to align header priorization execution order Fixes #973 * chore: add initial changeset file * chore: pick open-next.config.local.ts changes as well * chore: fix feedback * chore: improve comment on test
1 parent 911ecd2 commit 23ed1df

File tree

7 files changed

+62
-4
lines changed

7 files changed

+62
-4
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/aws": minor
3+
---
4+
5+
feat: Add option to align with Next.js execution order for headers in middleware and next.config.js

examples/app-router/middleware.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ export function middleware(request: NextRequest) {
5050
// Response headers should show up in the client's response headers
5151
responseHeaders.set("response-header", "response-header");
5252

53+
// For dangerous.middlewareHeadersOverrideNextConfigHeaders we need to verify that middleware headers override next.config.js headers.
54+
if (path === "/headers/override-from-middleware") {
55+
responseHeaders.set("e2e-headers", "middleware");
56+
return NextResponse.json({}, { headers: responseHeaders });
57+
}
58+
5359
// Set the cache control header with custom swr
5460
// For: isr.test.ts
5561
if (path === "/isr" && !request.headers.get("x-prerender-revalidate")) {

examples/app-router/open-next.config.local.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export default {
1111
},
1212
},
1313

14+
dangerous: {
15+
middlewareHeadersOverrideNextConfigHeaders: true,
16+
},
17+
1418
imageOptimization: {
1519
override: {
1620
wrapper: "dummy",

examples/app-router/open-next.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const config = {
88
},
99
},
1010
functions: {},
11+
dangerous: {
12+
middlewareHeadersOverrideNextConfigHeaders: true,
13+
},
1114
buildCommand: "npx turbo build",
1215
};
1316

packages/open-next/src/core/routingHandler.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,22 @@ export default async function routingHandler(
129129
return middlewareEventOrResult;
130130
}
131131

132-
headers = {
133-
...middlewareEventOrResult.responseHeaders,
134-
...headers,
135-
};
132+
const middlewareHeadersPrioritized =
133+
globalThis.openNextConfig.dangerous
134+
?.middlewareHeadersOverrideNextConfigHeaders ?? false;
135+
136+
if (middlewareHeadersPrioritized) {
137+
headers = {
138+
...headers,
139+
...middlewareEventOrResult.responseHeaders,
140+
};
141+
} else {
142+
headers = {
143+
...middlewareEventOrResult.responseHeaders,
144+
...headers,
145+
};
146+
}
147+
136148
let isExternalRewrite = middlewareEventOrResult.isExternalRewrite ?? false;
137149
eventOrResult = middlewareEventOrResult;
138150

packages/open-next/src/types/open-next.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ export interface DangerousOptions {
8686
headersAndCookiesPriority?: (
8787
event: InternalEvent,
8888
) => "middleware" | "handler";
89+
90+
/**
91+
* Configuration option to prioritize headers set via middleware over headers set via the option in the Next config.
92+
*
93+
* The default will change to 'true' in v4.
94+
*
95+
* See also {@link https://nextjs.org/docs/app/api-reference/file-conventions/middleware#execution-order}
96+
*
97+
* @default false
98+
*/
99+
middlewareHeadersOverrideNextConfigHeaders?: boolean;
89100
}
90101

91102
export type BaseOverride = {

packages/tests-e2e/tests/appRouter/headers.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,20 @@ test("Headers", async ({ page }) => {
2828
// Request ID header should be set
2929
expect(headers["x-opennext-requestid"]).not.toBeFalsy();
3030
});
31+
32+
/**
33+
* Tests that the middleware headers are applied after next.config.js headers. Requires 'dangerous.middlewareHeadersOverrideNextConfigHeaders' to be set.
34+
*/
35+
test("Middleware headers override next.config.js headers", async ({ page }) => {
36+
const responsePromise = page.waitForResponse((response) => {
37+
return response.status() === 200;
38+
});
39+
await page.goto("/headers/override-from-middleware");
40+
41+
const response = await responsePromise;
42+
// Response header should be set
43+
const headers = response.headers();
44+
45+
// The next.config.js headers is overwritten by the middleware
46+
expect(headers["e2e-headers"]).toEqual("middleware");
47+
});

0 commit comments

Comments
 (0)