Skip to content

Commit 0a33e6a

Browse files
authored
feat: make allowedHosts accept localhost subdomains by default (#4357)
1 parent 088a318 commit 0a33e6a

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

lib/Server.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -2987,12 +2987,14 @@ class Server {
29872987
// an IPv6-address in URLs,
29882988
// these are removed from the hostname in url.parse(),
29892989
// so we have the pure IPv6-address in hostname.
2990-
// always allow localhost host, for convenience (hostname === 'localhost')
2990+
// For convenience, always allow localhost (hostname === 'localhost')
2991+
// and its subdomains (hostname.endsWith(".localhost")).
29912992
// allow hostname of listening address (hostname === this.options.host)
29922993
const isValidHostname =
29932994
(hostname !== null && ipaddr.IPv4.isValid(hostname)) ||
29942995
(hostname !== null && ipaddr.IPv6.isValid(hostname)) ||
29952996
hostname === "localhost" ||
2997+
(hostname !== null && hostname.endsWith(".localhost")) ||
29962998
hostname === this.options.host;
29972999

29983000
if (isValidHostname) {

test/e2e/__snapshots__/allowed-hosts.test.js.snap.webpack4

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ exports[`allowed hosts check host headers should always allow \`localhost\` if o
1818

1919
exports[`allowed hosts check host headers should always allow \`localhost\` if options.allowedHosts is auto: response status 1`] = `200`;
2020

21+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: console messages 1`] = `Array []`;
22+
23+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: page errors 1`] = `Array []`;
24+
25+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: response status 1`] = `200`;
26+
2127
exports[`allowed hosts check host headers should always allow any host if options.allowedHosts is all: console messages 1`] = `Array []`;
2228

2329
exports[`allowed hosts check host headers should always allow any host if options.allowedHosts is all: page errors 1`] = `Array []`;

test/e2e/__snapshots__/allowed-hosts.test.js.snap.webpack5

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ exports[`allowed hosts check host headers should always allow \`localhost\` if o
1818

1919
exports[`allowed hosts check host headers should always allow \`localhost\` if options.allowedHosts is auto: response status 1`] = `200`;
2020

21+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: console messages 1`] = `Array []`;
22+
23+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: page errors 1`] = `Array []`;
24+
25+
exports[`allowed hosts check host headers should always allow \`localhost\` subdomain if options.allowedHosts is auto: response status 1`] = `200`;
26+
2127
exports[`allowed hosts check host headers should always allow any host if options.allowedHosts is all: console messages 1`] = `Array []`;
2228

2329
exports[`allowed hosts check host headers should always allow any host if options.allowedHosts is all: page errors 1`] = `Array []`;

test/e2e/allowed-hosts.test.js

+41
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,47 @@ describe("allowed hosts", () => {
12091209
expect(pageErrors).toMatchSnapshot("page errors");
12101210
});
12111211

1212+
it("should always allow `localhost` subdomain if options.allowedHosts is auto", async () => {
1213+
const options = {
1214+
allowedHosts: "auto",
1215+
port: port1,
1216+
};
1217+
1218+
const headers = {
1219+
host: "app.localhost",
1220+
};
1221+
1222+
server = new Server(options, compiler);
1223+
1224+
await server.start();
1225+
1226+
({ page, browser } = await runBrowser());
1227+
1228+
page
1229+
.on("console", (message) => {
1230+
consoleMessages.push(message);
1231+
})
1232+
.on("pageerror", (error) => {
1233+
pageErrors.push(error);
1234+
});
1235+
1236+
const response = await page.goto(`http://127.0.0.1:${port1}/main.js`, {
1237+
waitUntil: "networkidle0",
1238+
});
1239+
1240+
if (!server.checkHeader(headers, "host")) {
1241+
throw new Error("Validation didn't fail");
1242+
}
1243+
1244+
expect(response.status()).toMatchSnapshot("response status");
1245+
1246+
expect(consoleMessages.map((message) => message.text())).toMatchSnapshot(
1247+
"console messages"
1248+
);
1249+
1250+
expect(pageErrors).toMatchSnapshot("page errors");
1251+
});
1252+
12121253
it("should always allow value from the `host` options if options.allowedHosts is auto", async () => {
12131254
const networkIP = Server.internalIPSync("v4");
12141255
const options = {

0 commit comments

Comments
 (0)