Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions examples/headers/array/README.md
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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 (typeof headers === "object" && !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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Loading