Closed microspec-chris closed 2 years ago
I solved this with the following code:
const server = http.createServer(async (req, res) => {
res.removeHeader("Connection");
From what I can tell the request forwarded from IIS to the Node.js process is over http and http/1 and so the response from Node.js includes the implicit header "Connection". IIS includes that header when sending the response back to the client, even though it does so via HTTP/2 over https. Certain versions of Safari fail when that forbidden "Connection" header is included over HTTP/2 so it continues to retry the request.
Removing this header solved the issue across the number of Node.js apps we have running through IISNode, include those using Express.js and those with stock Node.js APIs (as in the prior examples).
This issue only happened with https because https is required for HTTP/2.
Big thanks to the following posts which got me started on the solution:
We have various services and APIs served via Node.js version 14 on IIS using iisnode and generally we've been very pleased with the experience. In the last several months we've had reports from people using Safari that they can't use some of these services.
I've narrowed the problem down to https URLs - http works fine. If I enter the https URL of my test page in Safari 10 on iOS 10.3.3 the browser loading bar stays in the same place for 60 seconds then gives up with the message: "Safari could not open the page because the server stopped responding."
Here's the Node.js server code to run on the iisnode server:
Navigating Safari to /test yields the following iisnode log:
The iisnode log shows that the server received the requests and successfully served a response. In fact, Safari repeats the request every 100 ms or so, all of which the Node.js app appears to respond to successfully.
Note that I can successfully visit https pages on the server that are plain .htm files, or served via ColdFusion or Classic ASP, so this is something more specific to Node.js. I can also serve the Node.js app locally on my LAN with a self-signed cert and access the page at https://192.168.0.8.
I can duplicate this issue with both iPhone and iPad with Safari 10 on iOS 10.3.3. Unfortunately I can't test in a different browser on these devices since those apps require a higher version of iOS.
These versions of Safari work fine:
I'm guessing this has something to do with Safari (or iOS) rejecting the certificate for https but I'm not sure how to get further detail. I've tried opening the developer console on my MacBook for the problematic iPhone but it gave no errors about why the https page could not be loaded.
This question is also posted on Stack Overflow at https://stackoverflow.com/questions/71037910/safari-10-fails-to-load-https-with-node-js-iisnode-spams-requests