Open spthiel opened 8 months ago
Workaround for this for the time being:
fetch("http://127.0.0.1/", {
headers: {
host: "test.localhost"
}
});
@marco-ippolito there is the same issue (and workaround) on mac-os
For those suffering from this issue. I'd say a more future proof solution is to add your "subdomains" in /etc/hosts
(I'm not sure where it is in windows)
Add this to hosts
127.0.0.1 test.localhost
That should do the trick :)
With Node 18.18+ the workaround I posted is no longer possible (because node fetch disallowed setting the host header).
Instead use npm i undici
import {request} from "undici";
request("http://127.0.0.1/", {
headers: {
host: "test.localhost"
}
});
Also happens on mac, if not connected to internet. Steps to reproduce:
1- listen to port 3000 on localhost:
const http = require('http');
http.createServer((request, res) => {
res.write('Working!');
res.end();
}).listen(3000);
2- disconnect from wifi (works if connected) 3- try below:
// works:
await axios.get("http://localhost:3000")
// fails: Uncaught AxiosError: getaddrinfo ENOTFOUND test.localhost
await axios.get("http://test.localhost:3000")
info:
> process.versions
{
node: '20.3.1',
acorn: '8.8.2',
ada: '2.5.0',
ares: '1.19.1',
base64: '0.5.0',
brotli: '1.0.9',
cjs_module_lexer: '1.2.2',
cldr: '43.1',
icu: '73.2',
llhttp: '8.1.1',
modules: '115',
napi: '9',
nghttp2: '1.54.0',
openssl: '3.1.1',
simdutf: '3.2.12',
tz: '2023c',
undici: '5.22.1',
unicode: '15.0',
uv: '1.45.0',
uvwasi: '0.0.18',
v8: '11.3.244.8-node.9',
zlib: '1.2.11'
}
I suggest removing windows from bug title, as this seems to be non-OS specific issue.
one workaround could be to add subdomain.localhost to hosts in OS, but this seems like a bug to me, given curl and browsers are able to route localhost subdomains
Interesting observation, it seems like OS can't resolve the dns with subdomains if not connected to internet:
$ # connected to internet
$ dscacheutil -q host -a name localhost
name: localhost
ipv6_address: ::1
name: localhost
ip_address: 127.0.0.1
$ dscacheutil -q host -a name test.localhost
name: test.localhost
ipv6_address: ::1
name: test.localhost
ip_address: 127.0.0.1
$ # not connected to internet
$ dscacheutil -q host -a name localhost
name: localhost
ipv6_address: ::1
name: localhost
ip_address: 127.0.0.1
$ dscacheutil -q host -a name test.localhost
$
Interesting observation, it seems like OS can't resolve the dns with subdomains if not connected to internet:
$ # connected to internet
$ dscacheutil -q host -a name localhost
name: localhost
ipv6_address: ::1
name: localhost
ip_address: 127.0.0.1
$ dscacheutil -q host -a name test.localhost
name: test.localhost
ipv6_address: ::1
name: test.localhost
ip_address: 127.0.0.1
$ # not connected to internet
$ dscacheutil -q host -a name localhost
name: localhost
ipv6_address: ::1
name: localhost
ip_address: 127.0.0.1
$ dscacheutil -q host -a name test.localhost
$
here is a somewhat hacky fix, I think this should be handled in both OS and nodejs level, nevertheless:
var axios = require("axios")
var http_adapter = require('axios/lib/adapters/http')
var settle = require('axios/lib/core/settle')
// also works
await axios.get("http://testing.localhost:3000", {
adapter: (config) => {
const regex = /(?<prefix>^https?:\/\/)(?<subdomain>.*\.)(?<suffix>localhost.*)/gi
const subdomain_matches = Array.from(config.url.matchAll(regex))
if (subdomain_matches.length > 0) {
config.headers["Host"] = config.url
config.url = `${subdomain_matches[0].groups.prefix}${subdomain_matches[0].groups.suffix}`
}
return new Promise((resolve, reject) => {
http_adapter(config).then(response => {settle(resolve, reject, response)}).catch(reject)
})
}
})
although there is a solution with adapter, I suggest adding the localhost juggling inside nodejs package with proper testing so it can handle all users' request more robust out of box.
Version
Tested on v21.2.0, v20.9.0, v18.18.2
Platform
Microsoft Windows NT 10.0.19045.0 x64
Subsystem
No response
What steps will reproduce the bug?
fetch("http://test.localhost/")
How often does it reproduce? Is there a required condition?
Happens on windows every time
What is the expected behavior? Why is that the expected behavior?
Expected behaviour is ECONNREFUSED or content of what the webpage contains equally to how a node on Linux, cURL or a browser would handle it
What do you see instead?
Additional information
Recreated locally in a VM but also on an actual Windows device