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: allow array for headers option #3847

Merged
merged 8 commits into from Sep 16, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 (typeof headers === "object" && !Array.isArray(headers)) {
snitin315 marked this conversation as resolved.
Show resolved Hide resolved
// 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