admin管理员组文章数量:1410712
Under node.js 16.13.1 (Windows), code like this worked (assume a server exists and works fine):
import net from 'net';
let socket = net.createConnection({
host: 'localhost',
port: 12345
})
After updating to node.js 17.7.2, the above now throws ECONNREFUSED (connection refused) errors. However, it works fine with '0.0.0.0' instead of 'localhost'.
In fact, even the documented default of "localhost" (thanks VLAZ) fails on 17.7.2:
// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345});
// connects with both versions:
net.createConnection({port:12345,host:'0.0.0.0'});
// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345,host:'localhost'});
I've confirmed that the behavior depends on the version of node. I can reliably avoid / reproduce the behavior at will by switching node versions, using any code that establishes a network connection.
I have a fair amount of code with hosts that default to "localhost". I'd rather not update all of that to "0.0.0.0" if I don't have to. More tedious is that often the user provides the host address and expects "localhost" to work, so now I have to add logic that converts "localhost" to "0.0.0.0" every time I create a socket with a user-specified host address. I mean, I'll do what I have to do, but this kind of stinks.
My question is: What happened between 16.13.1 and 17.7.2 that made "localhost" not useable any more? Is it a bug, or some intentional change? And, is there a way to make it work again or do I have to find+replace "localhost" with "0.0.0.0" everywhere now?
I suspect a lot of the "connection refused to localhost" errors that people ask about on the internet are related to whatever changed...
Update: It seems to have something to do with changes in how interfaces are enumerated (or something like that) in 17, rather than the specific use of "localhost".
For example, with the following test setup:
- Three TCP servers created with node: one for the default address, one with "0.0.0.0" explicitly set, and one with "localhost" explicitly set.
- Three clients attempting to connect to each server, one to default host, one to "0.0.0.0", one to "localhost".
Then with 16.13.1:
Listening on default | Listening on 0.0.0.0 | Listening on localhost | |
---|---|---|---|
Connect to default | OK | OK | OK |
Connect to 0.0.0.0 | OK | OK | OK |
Connect to localhost | OK | OK | OK |
Under node.js 16.13.1 (Windows), code like this worked (assume a server exists and works fine):
import net from 'net';
let socket = net.createConnection({
host: 'localhost',
port: 12345
})
After updating to node.js 17.7.2, the above now throws ECONNREFUSED (connection refused) errors. However, it works fine with '0.0.0.0' instead of 'localhost'.
In fact, even the documented default of "localhost" (thanks VLAZ) fails on 17.7.2:
// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345});
// connects with both versions:
net.createConnection({port:12345,host:'0.0.0.0'});
// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345,host:'localhost'});
I've confirmed that the behavior depends on the version of node. I can reliably avoid / reproduce the behavior at will by switching node versions, using any code that establishes a network connection.
I have a fair amount of code with hosts that default to "localhost". I'd rather not update all of that to "0.0.0.0" if I don't have to. More tedious is that often the user provides the host address and expects "localhost" to work, so now I have to add logic that converts "localhost" to "0.0.0.0" every time I create a socket with a user-specified host address. I mean, I'll do what I have to do, but this kind of stinks.
My question is: What happened between 16.13.1 and 17.7.2 that made "localhost" not useable any more? Is it a bug, or some intentional change? And, is there a way to make it work again or do I have to find+replace "localhost" with "0.0.0.0" everywhere now?
I suspect a lot of the "connection refused to localhost" errors that people ask about on the internet are related to whatever changed...
Update: It seems to have something to do with changes in how interfaces are enumerated (or something like that) in 17, rather than the specific use of "localhost".
For example, with the following test setup:
- Three TCP servers created with node: one for the default address, one with "0.0.0.0" explicitly set, and one with "localhost" explicitly set.
- Three clients attempting to connect to each server, one to default host, one to "0.0.0.0", one to "localhost".
Then with 16.13.1:
Listening on default | Listening on 0.0.0.0 | Listening on localhost | |
---|---|---|---|
Connect to default | OK | OK | OK |
Connect to 0.0.0.0 | OK | OK | OK |
Connect to localhost | OK | OK | OK |
But with 17.7.2:
Listening on default | Listening on 0.0.0.0 | Listening on localhost | |
---|---|---|---|
Connect to default | OK | ECONNREFUSED | OK |
Connect to 0.0.0.0 | OK | OK | ECONNREFUSED |
Connect to localhost | OK | ECONNREFUSED | OK |
Now that's with servers created with node; also same node version for servers and clients. In my original case, my server was created with C++ and the standard socket()
API, bound to INADDR_ANY
(0.0.0.0).
Test code:
import net from 'net';
console.log(process.version);
const accepted = detail => socket => socket.write(detail, ()=>socket.end());
const serversReady = () => [
new Promise(resolve => net.createServer(accepted('default')).listen(12345, function(){resolve(this)})),
new Promise(resolve => net.createServer(accepted('localhost')).listen(12346, 'localhost', function(){resolve(this)})),
new Promise(resolve => net.createServer(accepted('0.0.0.0')).listen(12347, '0.0.0.0', function(){resolve(this)}))
];
const ports = [[12345,'default'], [12346,'localhost'], [12347,'0.0.0.0']];
const hosts = [{}, {host:'localhost'}, {host:'0.0.0.0'}];
const clientsDone = () => ports.map(([port,whichserver]) => hosts.map(host => new Promise((resolve, reject) => {
let opts = {...host, port:port};
net.createConnection(opts)
.on('error', e => (console.log(opts, 'to:'+whichserver, 'error', e.message), reject(e)))
.on('data', d => console.log(opts, 'to:'+whichserver, 'read', d.toString()))
.on('end', () => resolve());
}))).flat();
Promise.all(serversReady())
.then(servers => Promise.allSettled(clientsDone()).then(() => servers))
.then(servers => servers.forEach(s => s.close()));
More on this after work but figured I'd post this little bit sooner rather than later. Will check 18 too.
Share Improve this question edited Jun 16, 2022 at 19:31 Jason C asked Jun 16, 2022 at 15:41 Jason CJason C 40.5k15 gold badges135 silver badges198 bronze badges 6-
Doesn't seem like the docs have anything to say here. In fact, it should be correct. The object passed to
createConnection()
is passed tosocket.connect()
and that documentation states thathost
is expected to be a string and it is even defaulted to'localhost'
. The documentation looks the same for v16 – VLAZ Commented Jun 16, 2022 at 15:51 -
@VLAZ Very strange. It's definitely associated with the version. In fact, I just confirmed that
socket.connect({port:1234})
(with defaulted host) fails on 17.7.2 and succeeds on 16.13.1. Now I'm wondering if maybe 17.7.2 enumerates network interfaces differently or something? – Jason C Commented Jun 16, 2022 at 16:29 -
1
Dunno. Might be a bug somewhere, as you suggest. I don't know why it would ever fail - I'd expect to just use the OS to connect to the address. Which should try to resolve
localhost
from wherever it's held nowadays (I think I've not seen it in the hosts file). But I don't see how such a functionality would be different for different Node versions, if it's just expecting the outside to resolve this. Which suggests it's not actually what happens. But it's a mystery to me why. – VLAZ Commented Jun 16, 2022 at 16:33 - Maybe try Node 18? Or a different version of 17? To try and isolate if it's some sort of bug. If it also behaves the same in 18, then it seems like a change of some sort. – VLAZ Commented Jun 16, 2022 at 16:35
- 3 Maybe "localhost" gets resolved to the IPv6 address and fails? Try to test with "127.0.0.1" and "::1", if one works and not the other. – gre_gor Commented Jun 16, 2022 at 18:54
1 Answer
Reset to default 5I quote answer from @richardlau
Node.js no longer re-sorts results of IP address lookups and returns them as-is (i.e. it no longer ignores how your OS has been configured). You can change the behaviour via the verbatim option to dns.lookup() or set the --dns-result-order mand line option to change the default.
You could try:
ping localhost
in you cmd or terminal. If it shows:
Reply from 127.0.0.1
it means your system prefer ipv4 address to resolve localhost. If it shows:
Reply from ::1
it means your system prefer ipv6 address.
You could change system setting to prefer ipv4. Node.js will resolve localhost to 127.0.0.1 as you expect.
本文标签: javascriptNodejs 16 gt 17 changed resolution of quotlocalhostquotStack Overflow
版权声明:本文标题:javascript - Node.js 16 -> 17 changed resolution of "localhost"? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744240561a2596767.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论