Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dev] Support request headers override in middleware (#8752)
Implements request headers override in middlewares. #### New middleware headers - `x-middleware-override-headers`: A comma separated list of *all* request header names. Headers not listed will be deleted. - `x-middleware-request-<name>`: A new value for the header `<name>`. ### Related Issues - #8724: Add helper functions for non-Next.js middlewares - vercel/next.js#41380: Next.js' implementation ### 📋 Checklist <!-- Please keep your PR as a Draft until the checklist is complete --> #### Tests - [ ] The code changed/added as part of this PR has been covered with tests - [ ] All tests pass locally with `yarn test-unit` #### Code Review - [ ] This PR has a concise title and thorough description useful to a reviewer - [ ] Issue from task tracker has a link to this PR
- Loading branch information
Showing
6 changed files
with
244 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
packages/cli/test/dev/fixtures/middleware-request-headers-override/api/dump-headers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default (req, res) => { | ||
res.json(req.headers); | ||
}; |
18 changes: 18 additions & 0 deletions
18
packages/cli/test/dev/fixtures/middleware-request-headers-override/middleware.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export default () => { | ||
return new Response(null, { | ||
headers: { | ||
'x-middleware-next': '1', | ||
'x-middleware-override-headers': | ||
'x-from-client-a,x-from-client-b,x-from-middleware-a,x-from-middleware-b,transfer-encoding', | ||
// Headers to be preserved. | ||
'x-middleware-request-x-from-client-a': 'hello from client', | ||
// Headers to be modified by the middleware. | ||
'x-middleware-request-x-from-client-b': 'hello from middleware', | ||
// Headers to be added by the middleware. | ||
'x-middleware-request-x-from-middleware-a': 'hello a!', | ||
'x-middleware-request-x-from-middleware-b': 'hello b!', | ||
// Headers not allowed by the dev server: will be ignored. | ||
'transfer-encoding': 'gzip, chunked', | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { Headers } from 'node-fetch'; | ||
import { applyOverriddenHeaders } from '../../../../src/util/dev/headers'; | ||
|
||
describe('applyOverriddenHeaders', () => { | ||
it('do nothing if x-middleware-override-headers is not set', async () => { | ||
const reqHeaders = { a: '1' }; | ||
const respHeaders = new Headers(); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ a: '1' }); | ||
}); | ||
|
||
it('adds a new header', async () => { | ||
const reqHeaders = { a: '1' }; | ||
const respHeaders = new Headers({ | ||
// Define a new header 'b' and keep the existing header 'a' | ||
'x-middleware-override-headers': 'a,b', | ||
'x-middleware-request-a': '1', | ||
'x-middleware-request-b': '2', | ||
}); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ a: '1', b: '2' }); | ||
}); | ||
|
||
it('delete the header if x-middleware-request-* is undefined', async () => { | ||
const reqHeaders = { a: '1', b: '2' }; | ||
const respHeaders = new Headers({ | ||
// Deletes a new header 'c' and keep the existing headers `a` and `b` | ||
'x-middleware-override-headers': 'a,b,c', | ||
'x-middleware-request-a': '1', | ||
'x-middleware-request-b': '2', | ||
}); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ a: '1', b: '2' }); | ||
}); | ||
|
||
it('updates an existing header', async () => { | ||
const reqHeaders = { a: '1', b: '2' }; | ||
const respHeaders = new Headers({ | ||
// Modifies the header 'b' and keep the existing header 'a' | ||
'x-middleware-override-headers': 'a,b', | ||
'x-middleware-request-a': '1', | ||
'x-middleware-request-b': 'modified', | ||
}); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ a: '1', b: 'modified' }); | ||
}); | ||
|
||
it('ignores headers listed in NONOVERRIDABLE_HEADERS', async () => { | ||
const reqHeaders = { a: '1', host: 'example.com' }; | ||
const respHeaders = new Headers({ | ||
// Define a new header 'b' and 'content-length' | ||
'x-middleware-override-headers': 'a,b,content-length', | ||
'x-middleware-request-a': '1', | ||
'x-middleware-request-b': '2', | ||
'x-middleware-request-content-length': '128', | ||
}); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ a: '1', b: '2', host: 'example.com' }); | ||
}); | ||
|
||
it('deletes an existing header', async () => { | ||
const reqHeaders = { a: '1', b: '2' }; | ||
const respHeaders = new Headers({ | ||
// Deletes the header 'a' and keep the existing header 'b' | ||
'x-middleware-override-headers': 'b', | ||
'x-middleware-request-b': '2', | ||
}); | ||
|
||
applyOverriddenHeaders(reqHeaders, respHeaders); | ||
expect(reqHeaders).toStrictEqual({ b: '2' }); | ||
}); | ||
}); |