diff --git a/lib/Server.js b/lib/Server.js index 9e229ea98d..1dc2e0b7a3 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -2131,6 +2131,32 @@ class Server { }); } + { + /** + * + * @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-middleware", + path: "*", + middleware: optionsRequestResponseMiddleware, + }); + } + middlewares.push({ name: "webpack-dev-middleware", middleware: diff --git a/test/e2e/options-middleware.test.js b/test/e2e/options-middleware.test.js new file mode 100644 index 0000000000..dc267731e6 --- /dev/null +++ b/test/e2e/options-middleware.test.js @@ -0,0 +1,80 @@ +"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": "*", + }, + }, + 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;