Skip to content

Commit

Permalink
feat: support fn in headers option (#3267)
Browse files Browse the repository at this point in the history
Headers option now support function with req, res, context as params
  • Loading branch information
anshumanv committed May 11, 2021
1 parent 335a6ed commit 28f9597
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 17 deletions.
10 changes: 7 additions & 3 deletions lib/Server.js
Expand Up @@ -851,10 +851,14 @@ class Server {
}

setContentHeaders(req, res, next) {
if (this.options.headers) {
let { headers } = this.options;
if (headers) {
if (typeof headers === 'function') {
headers = headers(req, res, this.middleware.context);
}
// eslint-disable-next-line guard-for-in
for (const name in this.options.headers) {
res.setHeader(name, this.options.headers[name]);
for (const name in headers) {
res.setHeader(name, headers[name]);
}
}

Expand Down
9 changes: 8 additions & 1 deletion lib/options.json
Expand Up @@ -258,7 +258,14 @@
"description": "Defines routes which are enabled by default, on by default and allows localhost. https://webpack.js.org/configuration/dev-server/#devserverfirewall"
},
"headers": {
"type": "object",
"anyOf": [
{
"type": "object"
},
{
"instanceof": "Function"
}
],
"description": "Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
},
"historyApiFallback": {
Expand Down
21 changes: 18 additions & 3 deletions test/__snapshots__/validate-options.test.js.snap.webpack4
Expand Up @@ -122,11 +122,26 @@ exports[`options validate should throw an error on the "firewall" option with '[
- configuration.firewall should be an non-empty array."
`;

exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.headers should be one of these:
object { … } | function
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* configuration.headers should be an object:
object { … }
* configuration.headers should be an instance of function."
`;

exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.headers should be an object:
object { … }
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
- configuration.headers should be one of these:
object { … } | function
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* configuration.headers should be an object:
object { … }
* configuration.headers should be an instance of function."
`;

exports[`options validate should throw an error on the "historyApiFallback" option with '' value 1`] = `
Expand Down
21 changes: 18 additions & 3 deletions test/__snapshots__/validate-options.test.js.snap.webpack5
Expand Up @@ -122,11 +122,26 @@ exports[`options validate should throw an error on the "firewall" option with '[
- configuration.firewall should be an non-empty array."
`;

exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.headers should be one of these:
object { … } | function
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* configuration.headers should be an object:
object { … }
* configuration.headers should be an instance of function."
`;

exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
"ValidationError: Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.headers should be an object:
object { … }
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders"
- configuration.headers should be one of these:
object { … } | function
-> Adds headers to all responses. https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* configuration.headers should be an object:
object { … }
* configuration.headers should be an instance of function."
`;

exports[`options validate should throw an error on the "historyApiFallback" option with '' value 1`] = `
Expand Down
30 changes: 25 additions & 5 deletions test/server/headers-option.test.js
Expand Up @@ -46,11 +46,31 @@ describe('headers option', () => {

it('GET request with headers as an array', (done) => {
// https://github.com/webpack/webpack-dev-server/pull/1650#discussion_r254217027
const expected = ['v7', 'v8', 'v9'].includes(
process.version.split('.')[0]
)
? 'key1=value1,key2=value2'
: 'key1=value1, key2=value2';
const expected = 'key1=value1, key2=value2';
req.get('/main').expect('X-Bar', expected).expect(200, done);
});
});

describe('as a function', () => {
beforeAll((done) => {
server = testServer.start(
config,
{
headers: () => {
return { 'X-Bar': ['key1=value1', 'key2=value2'] };
},
port,
},
done
);
req = request(server.app);
});

afterAll(testServer.close);

it('GET request with headers as a function', (done) => {
// https://github.com/webpack/webpack-dev-server/pull/1650#discussion_r254217027
const expected = 'key1=value1, key2=value2';
req.get('/main').expect('X-Bar', expected).expect(200, done);
});
});
Expand Down
4 changes: 2 additions & 2 deletions test/validate-options.test.js
Expand Up @@ -156,8 +156,8 @@ const tests = {
failure: ['', []],
},
headers: {
success: [{}, { foo: 'bar' }],
failure: [false],
success: [{}, { foo: 'bar' }, () => {}],
failure: [false, 1],
},
historyApiFallback: {
success: [{}, true],
Expand Down

0 comments on commit 28f9597

Please sign in to comment.