diff --git a/lib/Server.js b/lib/Server.js index a9323ec7c7..3d76b7227b 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -200,6 +200,7 @@ const schema = require("./options.json"); * @property {boolean} [setupExitSignals] * @property {boolean | ClientConfiguration} [client] * @property {Headers | ((req: Request, res: Response, context: DevMiddlewareContext) => Headers)} [headers] + * @property {boolean} [optionsMethod] * @property {(devServer: Server) => void} [onAfterSetupMiddleware] * @property {(devServer: Server) => void} [onBeforeSetupMiddleware] * @property {(devServer: Server) => void} [onListening] @@ -2111,6 +2112,31 @@ class Server { middleware: this.setHeaders.bind(this), }); } + if (this.options.optionsMethod) { + /** + * + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next + * @returns {void} + * + */ + const optionsRequestResponseMiddleware = (req, res, next) => { + if (req.method === "OPTIONS") { + res.statusCode = 204; + res.setHeader("Content-Length", "0"); + res.end(); + return; + } + next(); + }; + + middlewares.push({ + name: "options-request-response", + path: "*", + middleware: optionsRequestResponseMiddleware, + }); + } middlewares.push({ name: "webpack-dev-middleware", diff --git a/lib/options.json b/lib/options.json index bd7a5a2f90..053fb71aed 100644 --- a/lib/options.json +++ b/lib/options.json @@ -445,6 +445,13 @@ "description": "Allows to set custom headers on response.", "link": "https://webpack.js.org/configuration/dev-server/#devserverheaders" }, + "OptionsMethod": { + "type": "boolean", + "description": "Response with 204 httpCode when receive an OPTIONS request", + "cli": { + "exclude": true + } + }, "HistoryApiFallback": { "anyOf": [ { @@ -1146,6 +1153,9 @@ "headers": { "$ref": "#/definitions/Headers" }, + "optionsMethod": { + "$ref": "#/definitions/OptionsMethod" + }, "historyApiFallback": { "$ref": "#/definitions/HistoryApiFallback" }, diff --git a/test/e2e/options-request-response.test.js b/test/e2e/options-request-response.test.js new file mode 100644 index 0000000000..cf4d498bc3 --- /dev/null +++ b/test/e2e/options-request-response.test.js @@ -0,0 +1,81 @@ +"use strict"; + +const webpack = require("webpack"); +const Express = require("express"); +const Server = require("../../lib/Server"); +const config = require("../fixtures/client-config/webpack.config"); +const runBrowser = require("../helpers/run-browser"); +const port = require("../ports-map")["options-request-response"]; + +const createWaiting = () => { + let reslove; + let reject; + const waiting = new Promise((resolve$, reject$) => { + reslove = resolve$; + reject = reject$; + }); + return { + reslove, + reject, + waiting, + }; +}; + +describe("handle options-request correctly", () => { + it("should response with 200 http code", async () => { + const compiler = webpack(config); + const [portForServer, portForApp] = port; + const closeApp = await (async () => { + const { reslove, waiting } = createWaiting(); + const app = new Express(); + app.get("/", (req, res) => { + res.sendStatus(200); + }); + const server = app.listen(portForApp, () => { + reslove(); + }); + await waiting; + return async () => { + const { reslove: reslove2, waiting: waiting2 } = createWaiting(); + server.close(() => { + reslove2(); + }); + await waiting2; + }; + })(); + const server = new Server( + { + port: portForServer, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": "*", + }, + optionsMethod: true, + }, + compiler + ); + await server.start(); + const { page, browser } = await runBrowser(); + const prefixUrl = "http://127.0.0.1"; + const htmlUrl = `${prefixUrl}:${portForServer}/test.html`; + const appUrl = `${prefixUrl}:${portForApp}`; + await page.goto(appUrl); + const responseStatus = []; + page.on("response", (res) => { + responseStatus.push(res.status()); + }); + await page.evaluate( + (url) => + window.fetch(url, { + headers: { + "another-header": "1", + }, + }), + htmlUrl + ); + await browser.close(); + await server.stop(); + await closeApp(); + expect(responseStatus).toEqual([204, 200]); + }); +}); diff --git a/test/ports-map.js b/test/ports-map.js index 65fd7b7597..4f1a9af647 100644 --- a/test/ports-map.js +++ b/test/ports-map.js @@ -79,6 +79,7 @@ const listOfTests = { "server-option": 1, "normalize-option": 1, "setup-middlewares-option": 1, + "options-request-response": 2, }; let startPort = 8089;