ECONNREFUSED when making a request to localhost using fetch in Node.js

har*_*ryg 14 http fetch node.js

I'm getting some strange behaviour in Node when making a request to locally running server.

我有一个本地服务器侦听端口 4000。当使用node-fetch(或任何其他 Node fetch 实现)时,我ECONNREFUSED在向它发出请求时收到错误:

> fetch('http://localhost:4000')
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 345,
  [Symbol(trigger_async_id_symbol)]: 5
}
> Uncaught TypeError: fetch failed
    at Object.processResponse (node:internal/deps/undici/undici:5575:34)
    at node:internal/deps/undici/undici:5901:42 {
  cause: Error: connect ECONNREFUSED ::1:4000
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1195:16)
      at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
    errno: -61,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '::1',
    port: 4000
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以愉快地使用 或 Web 浏览器向该服务器发出请求,curl不会出现错误(尽管它看起来像是在 IPv4 之前尝试 IPv6):

$ curl localhost:4000 -v                                                                  
*   Trying ::1:4000...
* connect to ::1 port 4000 failed: Connection refused
*   Trying 127.0.0.1:4000...
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET / HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.77.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< cache-control: max-age=0, private, must-revalidate
< content-length: 9
< content-type: text/plain; charset=utf-8
< date: Thu, 26 May 2022 10:01:52 GMT
< server: Cowboy
< x-request-id: FvKfbzxLnVk2GewAAE9B
<
* Connection #0 to host localhost left intact
Run Code Online (Sandbox Code Playgroud)

如果我直接在 Node 中使用 IPv4 地址,它似乎可以工作:

> fetch('http://127.0.0.1:4000').then(r => console.log(r.status))
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 825,
  [Symbol(trigger_async_id_symbol)]: 799
}
> 200
Run Code Online (Sandbox Code Playgroud)

有什么想法导致此问题以及如何解决它吗?

更新:

作为一个实验,我断开了与本地网络的连接,一切又恢复正常了。这让我认为这是由我的网络 dns 配置产生的 DNS 解析方式引起的。但不知道为什么

tec*_*ape 28

将其放在条目文件开头的某个位置:

import dns from 'node:dns';
dns.setDefaultResultOrder('ipv4first');
Run Code Online (Sandbox Code Playgroud)


Flo*_*ild 7

某些版本的节点似乎首先使用 IPv6 解析 DNS,具体取决于您的环境。当您设置 时localhost,它会尝试获取::1可能不可用的 IPv6 地址。

您可以按照 tech-escape 的建议强制执行 DNS 解析顺序,设置硬编码的 IPv4 地址(例如,127.0.0.1而不是localhost)也可能“修复”该问题

开放问题: https: //github.com/nodejs/undici/issues/1602