Skip to content

Commit fc36a77

Browse files
committed
[FIX] Explicitly bind to IPv4 loopback
In some environments, 'localhost' might resolve to the IPv6 loopback address '::1' which is often unexpected. This can especially lead to problems where other tools might resolve 'localhost' differently in the same environment. This change explicitly binds to the IPv4 loopback address '127.0.0.1' instead of resolving the address from 'localhost'. In case remote connections are allowed, no host is specified so that Node.js binds to either the unspecified IPv4 oder -IPv6 address (which usually also accepts IPv4 connections) [1] [1] https://nodejs.org/docs/latest-v25.x/api/net.html#serverlistenport-host-backlog-callback
1 parent 0213a08 commit fc36a77

File tree

2 files changed

+11
-10
lines changed

2 files changed

+11
-10
lines changed

lib/server.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,19 @@ function _listen(app, port, changePortIfInUse, acceptRemoteConnections) {
2626
const options = {};
2727

2828
if (!acceptRemoteConnections) {
29-
options.host = "localhost";
30-
}
29+
// Unless remote connections are allowed, bind to the IPv4 loopback address
30+
options.host = "127.0.0.1";
31+
} // If remote connections are allowed, do not set host so the server listens on all supported interfaces
3132

32-
const host = options.host || "127.0.0.1";
33+
const portScanHost = options.host || "127.0.0.1";
3334
let portMax;
3435
if (changePortIfInUse) {
3536
portMax = port + 30;
3637
} else {
3738
portMax = port;
3839
}
3940

40-
portscanner.findAPortNotInUse(port, portMax, host, function(error, foundPort) {
41+
portscanner.findAPortNotInUse(port, portMax, portScanHost, function(error, foundPort) {
4142
if (error) {
4243
reject(error);
4344
return;
@@ -49,15 +50,15 @@ function _listen(app, port, changePortIfInUse, acceptRemoteConnections) {
4950
`EADDRINUSE: Could not find available ports between ${port} and ${portMax}.`);
5051
error.code = "EADDRINUSE";
5152
error.errno = "EADDRINUSE";
52-
error.address = host;
53+
error.address = portScanHost;
5354
error.port = portMax;
5455
reject(error);
5556
return;
5657
} else {
5758
const error = new Error(`EADDRINUSE: Port ${port} is already in use.`);
5859
error.code = "EADDRINUSE";
5960
error.errno = "EADDRINUSE";
60-
error.address = host;
61+
error.address = portScanHost;
6162
error.port = portMax;
6263
reject(error);
6364
return;

test/lib/server/ports.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ test.serial("Start server - Port is already taken and an error occurs", async (t
5454
);
5555
t.is(
5656
error.address,
57-
"localhost",
57+
"127.0.0.1",
5858
"Correct error address"
5959
);
6060
t.is(
@@ -89,7 +89,7 @@ test.serial("Start server together with node server - Port is already taken and
8989
});
9090

9191
t.deepEqual(server.port, nextFoundPort, "Resolves with correct port");
92-
const request = supertest(`http://localhost:${nextFoundPort}`);
92+
const request = supertest(`http://127.0.0.1:${nextFoundPort}`);
9393
const result = await request.get("/index.html");
9494
if (result.error) {
9595
t.fail(result.error.text);
@@ -181,7 +181,7 @@ test.serial(
181181
);
182182
t.is(
183183
error.address,
184-
"localhost",
184+
"127.0.0.1",
185185
"Correct error address"
186186
);
187187
t.is(
@@ -213,7 +213,7 @@ test.serial("Start server twice - Port is already taken and the next one is used
213213
});
214214
t.deepEqual(serveResult2.port, nextFoundPort, "Resolves with correct port");
215215

216-
const request = supertest(`http://localhost:${nextFoundPort}`);
216+
const request = supertest(`http://127.0.0.1:${nextFoundPort}`);
217217
const result = await request.get("/index.html");
218218
if (result.error) {
219219
t.fail(result.error.text);

0 commit comments

Comments
 (0)