昨天半夜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 还是 max osx 的 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.logapache.log 我都配置了。

不看不知道,吓一跳:

1)demo.com_apache.log 中都是正常的200请求:

980871222-592a7c945d0c0_articlex.png

2)demo.com_nginx.log 中也都正常,但是需要注意的是:

  1. 请求都是 HTTP/2.0 请求
  2. 访问一次网站,会出现好几十甚至一百次链接请求(这个我把日志清空后,访问一次,nginx访问日志就出现了N多条)
  3. 请求都是200的

1.png

7. 确定了问题最终出现在nginx上面,而且是反向代理的问题。

三、解决

前后折腾了将近一天,最后在 stackoverflow 上找到了同样的问题,问题说:

safari 因为使用HTTP/2.0 请求而拿不到response

其中提到了我在别的问题中也看到的一个内容,已经有人在nginx中讨论过这个问题:

【"Upgrade" header should not be proxied over h2】

隐藏 Nginx 的 Upgrade header

具体为什么,可以去nginx上的讨论看看,很详细。

操作:

修改 nginx proxy配置中 proxy_hide_header 成 Upgrade

proxy_hide_header Upgrade