Skip to content

Commit 28f9597

Browse files
authored
feat: support fn in headers option (#3267)
Headers option now support function with req, res, context as params
1 parent 335a6ed commit 28f9597

6 files changed

+78
-17
lines changed

lib/Server.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -851,10 +851,14 @@ class Server {
851851
}
852852

853853
setContentHeaders(req, res, next) {
854-
if (this.options.headers) {
854+
let { headers } = this.options;
855+
if (headers) {
856+
if (typeof headers === 'function') {
857+
headers = headers(req, res, this.middleware.context);
858+
}
855859
// eslint-disable-next-line guard-for-in
856-
for (const name in this.options.headers) {
857-
res.setHeader(name, this.options.headers[name]);
860+
for (const name in headers) {
861+
res.setHeader(name, headers[name]);
858862
}
859863
}
860864

lib/options.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,14 @@
258258
"description": "Defines routes which are enabled by default, on by default and allows localhost. https://webpack.js.org/configuration/dev-server/#devserverfirewall"
259259
},
260260
"headers": {
261-
"type": "object",
261+
"anyOf": [
262+
{
263+
"type": "object"
264+
},
265+
{
266+
"instanceof": "Function"
267+
}
268+
],
262269
"description": "Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
263270
},
264271
"historyApiFallback": {

test/__snapshots__/validate-options.test.js.snap.webpack4

+18-3
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,26 @@ exports[`options validate should throw an error on the "firewall" option with '[
122122
- configuration.firewall should be an non-empty array."
123123
`;
124124

125+
exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
126+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
127+
- configuration.headers should be one of these:
128+
object { … } | function
129+
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
130+
Details:
131+
* configuration.headers should be an object:
132+
object { … }
133+
* configuration.headers should be an instance of function."
134+
`;
135+
125136
exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
126137
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
127-
- configuration.headers should be an object:
128-
object { … }
129-
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
138+
- configuration.headers should be one of these:
139+
object { … } | function
140+
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
141+
Details:
142+
* configuration.headers should be an object:
143+
object { … }
144+
* configuration.headers should be an instance of function."
130145
`;
131146

132147
exports[`options validate should throw an error on the "historyApiFallback" option with '' value 1`] = `

test/__snapshots__/validate-options.test.js.snap.webpack5

+18-3
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,26 @@ exports[`options validate should throw an error on the "firewall" option with '[
122122
- configuration.firewall should be an non-empty array."
123123
`;
124124

125+
exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
126+
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
127+
- configuration.headers should be one of these:
128+
object { … } | function
129+
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
130+
Details:
131+
* configuration.headers should be an object:
132+
object { … }
133+
* configuration.headers should be an instance of function."
134+
`;
135+
125136
exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
126137
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
127-
- configuration.headers should be an object:
128-
object { … }
129-
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
138+
- configuration.headers should be one of these:
139+
object { … } | function
140+
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
141+
Details:
142+
* configuration.headers should be an object:
143+
object { … }
144+
* configuration.headers should be an instance of function."
130145
`;
131146

132147
exports[`options validate should throw an error on the "historyApiFallback" option with '' value 1`] = `

test/server/headers-option.test.js

+25-5
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,31 @@ describe('headers option', () => {
4646

4747
it('GET request with headers as an array', (done) => {
4848
// https://github.com/webpack/webpack-dev-server/pull/1650#discussion_r254217027
49-
const expected = ['v7', 'v8', 'v9'].includes(
50-
process.version.split('.')[0]
51-
)
52-
? 'key1=value1,key2=value2'
53-
: 'key1=value1, key2=value2';
49+
const expected = 'key1=value1, key2=value2';
50+
req.get('/main').expect('X-Bar', expected).expect(200, done);
51+
});
52+
});
53+
54+
describe('as a function', () => {
55+
beforeAll((done) => {
56+
server = testServer.start(
57+
config,
58+
{
59+
headers: () => {
60+
return { 'X-Bar': ['key1=value1', 'key2=value2'] };
61+
},
62+
port,
63+
},
64+
done
65+
);
66+
req = request(server.app);
67+
});
68+
69+
afterAll(testServer.close);
70+
71+
it('GET request with headers as a function', (done) => {
72+
// https://github.com/webpack/webpack-dev-server/pull/1650#discussion_r254217027
73+
const expected = 'key1=value1, key2=value2';
5474
req.get('/main').expect('X-Bar', expected).expect(200, done);
5575
});
5676
});

test/validate-options.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ const tests = {
156156
failure: ['', []],
157157
},
158158
headers: {
159-
success: [{}, { foo: 'bar' }],
160-
failure: [false],
159+
success: [{}, { foo: 'bar' }, () => {}],
160+
failure: [false, 1],
161161
},
162162
historyApiFallback: {
163163
success: [{}, true],

0 commit comments

Comments
 (0)