Fix middleware header propagation (#30288)
This commit is contained in:
parent
2f329d2fd4
commit
3828ebea3c
6 changed files with 68 additions and 13 deletions
|
@ -624,7 +624,7 @@ export default class Server {
|
|||
|
||||
const subreq = params.request.headers[`x-middleware-subrequest`]
|
||||
const subrequests = typeof subreq === 'string' ? subreq.split(':') : []
|
||||
|
||||
const allHeaders = new Headers()
|
||||
let result: FetchEventResult | null = null
|
||||
|
||||
for (const middleware of this.middleware || []) {
|
||||
|
@ -667,6 +667,10 @@ export default class Server {
|
|||
},
|
||||
})
|
||||
|
||||
for (let [key, value] of result.response.headers) {
|
||||
allHeaders.append(key, value)
|
||||
}
|
||||
|
||||
if (!this.renderOpts.dev) {
|
||||
result.waitUntil.catch((error) => {
|
||||
console.error(`Uncaught: middleware waitUntil errored`, error)
|
||||
|
@ -681,6 +685,10 @@ export default class Server {
|
|||
|
||||
if (!result) {
|
||||
this.render404(params.request, params.response, params.parsed)
|
||||
} else {
|
||||
for (let [key, value] of allHeaders) {
|
||||
result.response.headers.set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -1156,7 +1164,11 @@ export default class Server {
|
|||
|
||||
for (const [key, value] of result.response.headers.entries()) {
|
||||
if (key !== 'content-encoding') {
|
||||
res.setHeader(key, value)
|
||||
if (key.toLowerCase() === 'set-cookie') {
|
||||
res.setHeader(key, value.split(', '))
|
||||
} else {
|
||||
res.setHeader(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,25 +20,28 @@ export function notImplemented(name: string, method: string): any {
|
|||
)
|
||||
}
|
||||
|
||||
export function fromNodeHeaders(object: NodeHeaders) {
|
||||
const headers: { [k: string]: string } = {}
|
||||
for (let headerKey in object) {
|
||||
const headerValue = object[headerKey]
|
||||
if (Array.isArray(headerValue)) {
|
||||
headers[headerKey] = headerValue.join('; ')
|
||||
} else if (headerValue) {
|
||||
headers[headerKey] = String(headerValue)
|
||||
export function fromNodeHeaders(object: NodeHeaders): Headers {
|
||||
const headers = new Headers()
|
||||
for (let [key, value] of Object.entries(object)) {
|
||||
const values = Array.isArray(value) ? value : [value]
|
||||
for (let v of values) {
|
||||
if (v !== undefined) {
|
||||
headers.append(key, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
export function toNodeHeaders(headers?: Headers): NodeHeaders {
|
||||
const object: NodeHeaders = {}
|
||||
const result: NodeHeaders = {}
|
||||
if (headers) {
|
||||
for (const [key, value] of headers.entries()) {
|
||||
object[key] = value.includes(';') ? value.split(';') : value
|
||||
result[key] = value
|
||||
if (key.toLowerCase() === 'set-cookie') {
|
||||
result[key] = value.split(', ')
|
||||
}
|
||||
}
|
||||
}
|
||||
return object
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -15,6 +15,16 @@ export async function middleware(request, ev) {
|
|||
next.headers.set('x-nested-header', 'valid')
|
||||
}
|
||||
|
||||
// Ensure deep can append to this value
|
||||
if (url.searchParams.get('append-me') === 'true') {
|
||||
next.headers.append('x-append-me', 'top')
|
||||
}
|
||||
|
||||
// Ensure deep can append to this value
|
||||
if (url.searchParams.get('cookie-me') === 'true') {
|
||||
next.headers.append('set-cookie', 'chocochip')
|
||||
}
|
||||
|
||||
// Sends a header
|
||||
if (url.pathname === '/responses/header') {
|
||||
next.headers.set('x-first-header', 'valid')
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function middleware(request, _event) {
|
||||
const next = NextResponse.next()
|
||||
next.headers.set('x-deep-header', 'valid')
|
||||
next.headers.append('x-append-me', 'deep')
|
||||
next.headers.append('set-cookie', 'oatmeal')
|
||||
return next
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
function Deep() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Deep</h1>
|
||||
<p>This is a deep page with deep middleware, check the headers</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Deep
|
|
@ -325,6 +325,17 @@ function responseTests(locale = '') {
|
|||
)
|
||||
expect(res.headers.get('x-first-header')).toBe('valid')
|
||||
})
|
||||
|
||||
it(`${locale} should respond with top level headers and append deep headers`, async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
`${locale}/responses/deep?nested-header=true&append-me=true&cookie-me=true`
|
||||
)
|
||||
expect(res.headers.get('x-nested-header')).toBe('valid')
|
||||
expect(res.headers.get('x-deep-header')).toBe('valid')
|
||||
expect(res.headers.get('x-append-me')).toBe('top, deep')
|
||||
expect(res.headers.raw()['set-cookie']).toEqual(['chocochip', 'oatmeal'])
|
||||
})
|
||||
}
|
||||
|
||||
function interfaceTests(locale = '') {
|
||||
|
|
Loading…
Reference in a new issue