Heroku 和 Google Cloud 运行 上的 HTTP 请求不同

HTTP request is not the same on Heroku and Google Cloud Run

我有一个 NodeJS/ExpressJS API 执行 HTTP 请求以在发送响应之前获得一些 JSON。这是代码片段:

const ipApiUrl = `https://ipapi.co/${ip}/json/`
const ipApiResponse = await axios.get(ipApiUrl)
console.log(ipApiResponse.data)
ipCountryCode = ipApiResponse.data.country_code

此代码在本地运行良好。它在 Heroku 上也能正常工作。但是,它 NOT 在 Google Cloud 运行.

上的工作方式相同

ipApiResponse.data 应该是这样的:

{
    "ip": "141.117.117.76",
    "city": "Toronto",
    "region": "Ontario",
    "region_code": "ON",
    "country": "CA",
    "country_code": "CA",
    ...
}

然而, 从 Google 云发送请求时 运行 API 我正在使用 returns 不同的东西.相反,我得到了这样的回应:

{ ip: '169.254.8.129', reserved: true }

我认为这个问题出在 Google Cloud 运行 或 Docker 上,因为我在向其他站点发出 HTTP 请求时也遇到了问题,例如 ipstack.com。

我正在使用 Docker 部署到 Google 云 运行。我的 Dockerfile 使用 node:10 并公开了 PORT 环境变量,如文档所述。除此 HTTP 请求外,其他一切正常。 axiosfetch 我都试过了。

您正在从私有 IP space 发送一个保留的 IP 地址。此地址在 public Internet 上无效。 IPAPI 返回的响应是正确的。

CIRD 块 169.254.0.0/16 中的 IP 地址称为自动私有 IP 地址。此范围内的地址通常用于本地保留网络功能,以及用于在网络上没有 DHCP 服务器的情况下自动分配 IP 地址的系统。该地址也可以因网络故障而分配。

解决方案是在您对 IPAPI 的请求中使用有效的 public IP 地址。如果您的代码正在检测此地址,那么您有一个编程错误。

注意:如果您试图通过检查网络接口来确定云 运行 服务的 IP 地址,则不能。云 运行 是一种在称为全球前端 (GFE) 的负载均衡器后面运行的服务。您将需要使用外部服务来询问 "what is my public IP address"。返回的 IP 地址将用于 GFE,而不用于您的云 运行 服务。

要在云 运行 应用程序上查找访问者的 IP 地址,您需要阅读 X-Forwarded-For header。

当您只查看请求或 TCP 连接上的 IP 地址时,您会看到将流量发送到您的应用程序的负载平衡器的内部 IP 地址。 (169.254.x.x 是在 RFC 3927 中定义的内部 IP 地址 space,这就是您看到 "reserved": true 的原因。)

所以,在 Express 中,尝试做:

var ip = req.header('X-Forwarded-For')