Safari 10 无法使用 Node.js (iisnode) 加载 https - 垃圾邮件请求

Safari 10 fails to load https with Node.js (iisnode) - spams requests

我们使用 iisnode (https://github.com/Azure/iisnode) 在 IIS 上通过 Node.js 版本 14 提供各种服务和 API。在过去的几个月里,我们收到了来自使用 Safari 的用户的报告,他们无法使用其中的某些服务。

我已将问题缩小到 https URLs - http 工作正常。如果我在 iOS 10.3.3 上的 Safari 10 中输入测试页面的 https URL,浏览器加载栏会在同一个地方停留 60 秒,然后放弃并显示消息:“Safari 无法打开页面因为服务器停止响应。"

这是 iisnode 服务器上 运行 的 Node.js 服务器代码:

const http = require("http");
const server = http.createServer(async(req, res) => {
    if (req.url === "/test" && req.method === "GET") {
        console.log(`Request to /test at ${Date.now()}`);
        res.writeHead(200, { "Content-Type": "text/plain" });
        res.end(`/test at ${Date.now()}`);
    }
});
server.listen(process.env.PORT, () => {
    console.log(`server started on port: ${process.env.PORT}`);
});

将 Safari 导航到 /test 会产生以下 iisnode 日志:

server started on port: \.\pipe678fe-c6de-448e-96c4-6c79ca947214
Request to /test at 1644335072668
Request to /test at 1644335072888
Request to /test at 1644335072993
Request to /test at 1644335073079
Request to /test at 1644335073156
Request to /test at 1644335073242
...

iisnode 日志显示服务器收到请求并成功响应。事实上,Safari 每隔 100 毫秒左右重复一次请求,Node.js 应用似乎已成功响应所有请求。

请注意,我可以成功访问服务器上通过 ColdFusion 或 Classic ASP 提供的 https 页面,因此这是 Node.js 更具体的内容。

我可以在 iOS 10.3.3 上使用 Safari 10 在 iPhone 和 iPad 上重复这个问题。不幸的是,我无法在这些设备上的不同浏览器中进行测试,因为这些应用程序需要更高版本的 iOS。

这些版本的 Safari 工作正常:

我猜这与 Safari(或 iOS)拒绝 https 证书有关,但我不确定如何获得更多详细信息。我已经尝试在我的 MacBook 上打开开发者控制台来解决问题 iPhone 但它没有给出无法加载 https 页面的原因。

我用下面的代码解决了这个问题:

const server = http.createServer(async (req, res) => {
    res.removeHeader("Connection");

据我所知,从 IIS 转发到 Node.js 进程的请求是通过 http 和 http/1 进行的,因此来自 Node.js 的响应包括隐含的 header “联系”。 IIS 在将响应发送回客户端时包含 header,即使它是通过 https 上的 HTTP/2 这样做的。当禁止的“连接”header 包含在 HTTP/2 上时,某些版本的 Safari 会失败,因此它会继续重试请求。

删除此 header 解决了我们通过 IISNode 运行 拥有的 Node.js 个应用程序的问题,包括使用 Express.js 和库存 [=33] 的应用程序=] API(与前面的示例一样)。

此问题只发生在 https 上,因为 HTTP/2 需要 https。

非常感谢以下帖子让我开始寻找解决方案: