今天在设置 nginx + apache2 时遇到 Safari 无法访问网站的问题,搜索到此解决方法,作者解释的非常详细,转载记录一下。
原文地址:http://www.ptbird.cn/nginx-apache-safari.html
原文标题:nginx 反向代理,safari 无法访问网站(HTTP/2.0 请求超时)的解决办法。
略微修改了部分格式。
昨天半夜 IOS 端开发者发现请求 API 无法拿到 response,一直是 timeout 。
排除了网络的原因,排除了客户端的原因,因为客户端请求其他的 API 都是成功的。
一、问题
iOS 开发使用 NSURLconnection 发送 HTTP POST 请求的时候,一直 timeout 。
继而发现 Safari 无法访问网站,但是 Chrome 和其他的浏览器都没有任何问题。
提前说一下,这个问题出现在 ngixn-1.9.0+/apache2.4 的反向代理上
我的服务器是 LANMP 组合的,其中 nginx 版本是 1.12.0,而 apache 的版本是 2.4
二、排查过程
1. 检查服务器通讯和网络原因
首先发现 iOS 端能够 ping 通服务器,但是新问题出现了 Safari 无法访问网站,同样的网站 Chrome 中能够访问。
2. 客户端排查
iOS 客户端开发者请求同样的 https API ,发现能够拿到 response,只有我的网站不行。
3. 网站系统排查
试了好几个 API 测试平台以及各种浏览器,发现都没有问题,最后发现:
苹果原生的应用 如 Safari,无论是 iOS 的 Safari 还是 macOS 的 Safari 都无法访问网站。
4. 排查 SSL 问题
因为我用的是 Let’s Encrypt 的 SSL 证书,因此测试了我其他使用 SSL 证书网站能否在 Safari 中打开, 发现都没问题。
5. 进一步排查网站系统
在排查过程中,发现当访问纯静态页面,如 https://www.demo.com/index2.html 的时候,没有任何问题,能够正常访问。
但是如果访问动态页面,如 https://www.demo.com/index2.php 的时候,都是错误的,也就是说 phpinfo() 都无法访问。
因此感觉问题可能出现在 nginx 或者是 apache 上。
6. 各种查资料
为此我在 segmentfault.com 上提问的问题也编辑了很多次,问清了 IOS 开发方面的一些概念后,最后确定了问题出现服务器方面。
所以在 stackoverflow 上各种关键字查,主要查的是
- nginx
- safari can not open website
在一个提问中发现,HTTP2 可能存在问题,因此我看了一下我的网站的 log,nginx.log 和 apache.log 我都配置了。
不看不知道,吓一跳:
demo.com_apache.log 中都是正常的 200 请求
demo.com_nginx.log 中也都正常,但是需要注意的是请求都是 HTTP/2.0 请求
访问一次网站,会出现好几十甚至一百次链接请求(这个我把日志清空后,访问一次,nginx 访问日志就出现了 N 多条),请求都是 200 的。
7. 确定了问题最终出现在 nginx 上面,而且是反向代理的问题。
三、解决
前后折腾了将近一天,最后在 stackoverflow 上找到了同样的问题,问题说:
Safari 因为使用 HTTP/2.0 请求而拿不到 response
问题地址: https://stackoverflow.com/questions/37762163/safari-fails-to-give-response-when-using-http-2
其中提到了我在别的问题中也看到的一个内容,已经有人在 nginx 中讨论过这个问题:
【”Upgrade” header should not be proxied over h2】
讨论地址:https://trac.nginx.org/nginx/ticket/915
隐藏 Nginx 的 Upgrade header
具体为什么,可以去 nginx 上的讨论看看,很详细。
操作:
修改 nginx proxy 配置中 proxy_hide_header 成 Upgrade
1 | proxy_hide_header Upgrade |