Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support fn in headers option #3267

Merged
merged 5 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/Server.js
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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