Skip to content

Commit

Permalink
feat: allow array for headers option (#3847)
Browse files Browse the repository at this point in the history
  • Loading branch information
snitin315 committed Sep 16, 2021
1 parent 71da079 commit 9911437
Show file tree
Hide file tree
Showing 11 changed files with 320 additions and 9 deletions.
36 changes: 36 additions & 0 deletions examples/headers/array/README.md
@@ -0,0 +1,36 @@
# headers option as an object

Adds headers to all responses.

**webpack.config.js**

```js
module.exports = {
// ...
devServer: {
headers: [
{
key: "X-Foo",
value: "value1",
},
{
key: "X-Bar",
value: "value2",
},
],
},
};
```

To run this example use the following command:

```console
npx webpack serve --open
```

## What should happen

1. The script should open `http://localhost:8080/`.
2. You should see the text on the page itself change to read `Success!`.
3. Open the console in your browser's devtools and select the _Network_ tab.
4. Find `main.js`. The response headers should contain `X-Foo: value1` and `X-Bar: value2`.
6 changes: 6 additions & 0 deletions examples/headers/array/app.js
@@ -0,0 +1,6 @@
"use strict";

const target = document.querySelector("#target");

target.classList.add("pass");
target.innerHTML = "Success!";
22 changes: 22 additions & 0 deletions examples/headers/array/webpack.config.js
@@ -0,0 +1,22 @@
"use strict";

// our setup function adds behind-the-scenes bits to the config that all of our
// examples need
const { setup } = require("../../util");

module.exports = setup({
context: __dirname,
entry: "./app.js",
devServer: {
headers: [
{
key: "X-Foo",
value: "value1",
},
{
key: "X-Bar",
value: "value2",
},
],
},
});
15 changes: 12 additions & 3 deletions lib/Server.js
Expand Up @@ -1845,10 +1845,19 @@ class Server {
headers = headers(req, res, this.middleware.context);
}

// eslint-disable-next-line guard-for-in
for (const name in headers) {
res.setHeader(name, headers[name]);
const allHeaders = [];

if (!Array.isArray(headers)) {
// eslint-disable-next-line guard-for-in
for (const name in headers) {
allHeaders.push({ key: name, value: headers[name] });
}
headers = allHeaders;
}

headers.forEach((header) => {
res.setHeader(header.key, header.value);
});
}

next();
Expand Down
24 changes: 24 additions & 0 deletions lib/options.json
Expand Up @@ -369,8 +369,32 @@
"description": "Allows to configure the server's listening socket for TLS (by default, dev server will be served over HTTP).",
"link": "https://webpack.js.org/configuration/dev-server/#devserverhttps"
},
"HeaderObject": {
"type": "object",
"additionalProperties": false,
"properties": {
"key": {
"description": "key of header.",
"type": "string"
},
"value": {
"description": "value of header.",
"type": "string"
}
},
"cli": {
"exclude": true
}
},
"Headers": {
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/definitions/HeaderObject"
},
"minItems": 1
},
{
"type": "object"
},
Expand Down
19 changes: 17 additions & 2 deletions test/__snapshots__/validate-options.test.js.snap.webpack4
Expand Up @@ -223,13 +223,26 @@ exports[`options validate should throw an error on the "devMiddleware" option wi
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverdevmiddleware"
`;

exports[`options validate should throw an error on the "headers" option with '[]' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be a non-empty array."
`;

exports[`options validate should throw an error on the "headers" option with '[{"foo":"bar"}]' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers[0] has an unknown property 'foo'. These properties are valid:
object { key?, value? }"
`;

exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be one of these:
object { … } | function
[object { key?, value? }, ...] (should not have fewer than 1 item) | object { … } | function
-> Allows to set custom headers on response.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* options.headers should be an array:
[object { key?, value? }, ...] (should not have fewer than 1 item)
* options.headers should be an object:
object { … }
* options.headers should be an instance of function."
Expand All @@ -238,10 +251,12 @@ exports[`options validate should throw an error on the "headers" option with '1'
exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be one of these:
object { … } | function
[object { key?, value? }, ...] (should not have fewer than 1 item) | object { … } | function
-> Allows to set custom headers on response.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* options.headers should be an array:
[object { key?, value? }, ...] (should not have fewer than 1 item)
* options.headers should be an object:
object { … }
* options.headers should be an instance of function."
Expand Down
19 changes: 17 additions & 2 deletions test/__snapshots__/validate-options.test.js.snap.webpack5
Expand Up @@ -223,13 +223,26 @@ exports[`options validate should throw an error on the "devMiddleware" option wi
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverdevmiddleware"
`;

exports[`options validate should throw an error on the "headers" option with '[]' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be a non-empty array."
`;

exports[`options validate should throw an error on the "headers" option with '[{"foo":"bar"}]' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers[0] has an unknown property 'foo'. These properties are valid:
object { key?, value? }"
`;

exports[`options validate should throw an error on the "headers" option with '1' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be one of these:
object { … } | function
[object { key?, value? }, ...] (should not have fewer than 1 item) | object { … } | function
-> Allows to set custom headers on response.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* options.headers should be an array:
[object { key?, value? }, ...] (should not have fewer than 1 item)
* options.headers should be an object:
object { … }
* options.headers should be an instance of function."
Expand All @@ -238,10 +251,12 @@ exports[`options validate should throw an error on the "headers" option with '1'
exports[`options validate should throw an error on the "headers" option with 'false' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.headers should be one of these:
object { … } | function
[object { key?, value? }, ...] (should not have fewer than 1 item) | object { … } | function
-> Allows to set custom headers on response.
-> Read more at https://webpack.js.org/configuration/dev-server/#devserverheaders
Details:
* options.headers should be an array:
[object { key?, value? }, ...] (should not have fewer than 1 item)
* options.headers should be an object:
object { … }
* options.headers should be an instance of function."
Expand Down
20 changes: 20 additions & 0 deletions test/e2e/__snapshots__/headers.test.js.snap.webpack4
@@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`headers option as a function returning an array should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as a function returning an array should handle GET request with headers: page errors 1`] = `Array []`;

exports[`headers option as a function returning an array should handle GET request with headers: response headers x-bar 1`] = `"value2"`;

exports[`headers option as a function returning an array should handle GET request with headers: response headers x-foo 1`] = `"value1"`;

exports[`headers option as a function returning an array should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as a function should handle GET request with headers as a function: console messages 1`] = `Array []`;

exports[`headers option as a function should handle GET request with headers as a function: page errors 1`] = `Array []`;
Expand All @@ -19,6 +29,16 @@ exports[`headers option as a string should handle GET request with headers: resp

exports[`headers option as a string should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as an array of objects should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as an array of objects should handle GET request with headers: page errors 1`] = `Array []`;

exports[`headers option as an array of objects should handle GET request with headers: response headers x-bar 1`] = `"value2"`;

exports[`headers option as an array of objects should handle GET request with headers: response headers x-foo 1`] = `"value1"`;

exports[`headers option as an array of objects should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as an array should handle GET request with headers as an array: console messages 1`] = `Array []`;

exports[`headers option as an array should handle GET request with headers as an array: page errors 1`] = `Array []`;
Expand Down
20 changes: 20 additions & 0 deletions test/e2e/__snapshots__/headers.test.js.snap.webpack5
@@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`headers option as a function returning an array should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as a function returning an array should handle GET request with headers: page errors 1`] = `Array []`;

exports[`headers option as a function returning an array should handle GET request with headers: response headers x-bar 1`] = `"value2"`;

exports[`headers option as a function returning an array should handle GET request with headers: response headers x-foo 1`] = `"value1"`;

exports[`headers option as a function returning an array should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as a function should handle GET request with headers as a function: console messages 1`] = `Array []`;

exports[`headers option as a function should handle GET request with headers as a function: page errors 1`] = `Array []`;
Expand All @@ -19,6 +29,16 @@ exports[`headers option as a string should handle GET request with headers: resp

exports[`headers option as a string should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as an array of objects should handle GET request with headers: console messages 1`] = `Array []`;

exports[`headers option as an array of objects should handle GET request with headers: page errors 1`] = `Array []`;

exports[`headers option as an array of objects should handle GET request with headers: response headers x-bar 1`] = `"value2"`;

exports[`headers option as an array of objects should handle GET request with headers: response headers x-foo 1`] = `"value1"`;

exports[`headers option as an array of objects should handle GET request with headers: response status 1`] = `200`;

exports[`headers option as an array should handle GET request with headers as an array: console messages 1`] = `Array []`;

exports[`headers option as an array should handle GET request with headers as an array: page errors 1`] = `Array []`;
Expand Down

0 comments on commit 9911437

Please sign in to comment.