当tinyproxy遇上php的soap

用例:

  1. 使用tinyproxy-1.8.3做代理
  2. php访问soap服务时,使用tinyproxy做代理访问http地址(不是https)
  3. http响应数据有点儿多,走的是Transfer-Encoding: chunked

 

问题:

  1. tinyproxy代理之后,响应头中 HTTP协议版本号为1.1,没有content-length, 也没有connection: close ,也没有Transfer-Encoding: chunked,对于这种尴尬的情况,client端就不方便处理了; curl会有如下警告: no chunk, no close, no size. Assume close to signal end
  2. 真实原因: curl虽然使用HTTP/1.1方式发送请求,但是tinyproxy对于所有http请求都以HTTP/1.0的方式转发(但是添加了Connection: close 头),最终的openresty(nginx行为也如此)却无视HTTP/1.0,执意返回HTTP/1.1 响应,并且使用Connection: close; tinyproxy直接透传HTTP/1.1 状态行,却丢弃了响应头中的Connection: close;(或许是tinyproxy以为自己总是工作在HTTP/1.0,所以不需要Connection: close 吧)

tinyproxy转发的请求:(发给nginx,nginx再代理转发给后面的openresty)

openresty收到的请求:

openresty响应:

openresty是藏在一个nginx后面的,nginx的响应:

 

分析:

原本HTTP/1.0 是不支持Host头的,但是很多client还是添加了,很多server也不介意(甚至喜欢)HTTP/1.0协议中使用Host头,参考: http://stackoverflow.com/questions/246859/http-1-0-vs-1-1

Connection 头也是http1.1中定义的,但是tinyproxy也用在了HTTP/1.0中了(难道为了兼容一些不守规矩的server端?),在HTTP/1.0和Connection头的暗示下,server端没有使用Content-length 或 Transfer-encoding也可以理解,也或许正式Connection头的存在,server端才选择响应HTTP/1.1

tinyproxy 源码片段:

tiny proxy发送请求:

由于tinyproxy上行的是http/1.0 ,所以会故意将请求头中的connection相关信息去掉,代码如下:

这个函数不仅在process_client_headers 中用到,也在 process_server_headers中用到

解决办法:

  1. 如果使用隧道代理的方式,tinyproxy就不会做上述多余的处理了,但是, php的soapclient强制写死的逻辑是:如果方式的是https,则使用隧道代理方式,否则,不走隧道代理方式,可是服务提供的就是http,不是https啊!!!!!!
  2. 修复tinyproxy的这个问题,修复方案:
  3. 换个proxy

 

疑问:

  1. 如果 content-length 不存在与http 1.0,那么http 1.0中的post请求,post数据长度如何表示?(难道也是关闭连接为止?

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据