浏览器什么时候会在 http 请求头中添加 proxy-connection: keepalive

2017-12-01 13:23:47 +08:00
 wcsjtu

对于 http 代理服务器来说, 浏览器发过来的 proxy-connection: keepalive 意味着什么?

C <--------> P <---------> S

http 代理服务器接收到这样的头部后,是要同时保持 CP、PS 连接,还是只用保持 CP 连接就行了?

还有另外一个问题,浏览器发给 http 代理的请求, 都是下面这样的么?

GET http://www.163.com/ HTTP/1.1
User-Agent: blabla
Host: www.163.com

还是会出现起始行不包含 host, 只有 uri 的报文

GET / HTTP/1.1
Host: www.163.com

6357 次点击
所在节点    程序员
20 条回复
choury
2017-12-01 13:37:28 +08:00
代理会把这个头改成 connection: keepalive 然后发给 S,自己啥也不干,因为这个头不是给它看的
xiaxiaocao
2017-12-01 13:46:24 +08:00
http1.0 时代的产物。老旧的代理,如果设置 connection: keepalive,代理原样转发给服务器,服务器会以为要建立长久连接,但是代理并不支持,这样就出问题了。
所以改为设置 proxy-connection: keepalive,如果是新的代理,支持 keepalive,它会认得这个头,并改成 connection: keepalive 转发给服务器,顺利建立持久连接;如果是老的代理,它不认识,会原样转发,这时候服务器也不会建立持久连接。完美。
wcsjtu
2017-12-01 13:46:34 +08:00
@choury 就等于是说, 如果 S 回复 keepalive, 对于 P 来说,要同时维持两条连接?
xiaxiaocao
2017-12-01 13:49:11 +08:00
代理请求的 URL 必须是完整路径,这个也是 Http1.0 规范
wcsjtu
2017-12-01 13:50:24 +08:00
@xiaxiaocao 嗯。这个头部就是为了解决哑代理的问题。 有一点我不太理解的是, 如果要复用之前的连接
C <--------> P <---------->S1
那么浏览器在 CP 上发来一个要转发给 S2 的请求怎么办?
wcsjtu
2017-12-01 13:53:26 +08:00
@xiaxiaocao 我最近在写 http 代理, 发现浏览器经常发起始行没有 host 的请求。 这样我就不知道这个包到底要发到哪去。。。。。。
xiaxiaocao
2017-12-01 14:12:07 +08:00
@wcsjtu 并没有说 CP 和 PS1 之间的连接是一一对应的,实际实现的时候也不会这样做。
至于你说的不是绝对路径 URL 的情况, 我现在也在用我写的代理,倒没有发现这种情况;应该可以用 Host 那个头来区别吧。
zhangysh1995
2017-12-01 14:14:07 +08:00
因为 HTTP 分为持久性和非持久性的链接,持久性的会保留下来链接。有兴趣的话下个 Wireshark 抓包,或者 burpsuite 都可以。可以看到网络模型五层的内容。
wcsjtu
2017-12-01 14:39:07 +08:00
@xiaxiaocao 那么可不可以这么认为,proxy-connection: keepalive, 只是为了复用 C 到 P 的连接?

而且对于 P 来说,一个 CP 对应多个 PS 的情况下, 数据在内部还要做一次中转?
wcsjtu
2017-12-01 14:41:03 +08:00
@zhangysh1995 蛤~ 我这个是代理的情况,两条连接, 不知道应该保持哪一条
wcsjtu
2017-12-01 14:54:31 +08:00
@xiaxiaocao 额~ 我傻 b 了,中转肯定是要的。。。。。。 只不过要在 P 内部记录 CP 到 PSi 的映射
xiaxiaocao
2017-12-01 14:54:48 +08:00
@wcsjtu CP 和 PS 之间都可以建立持久连接。比如代理实现的时候可以收到 C 的请求,然后跟 S 建立持久连接,然后收到一个 response 就发一个 connect close 会去关闭和 C 的连接,这样的都没问题。
HTTP 代理是要对每个 request 都做处理的,像 Accept-Encoding,Upgrade 这样的头都要看代理本身支持情况来修改,而不是直接用 client 传过来的。
xiaxiaocao
2017-12-01 14:57:49 +08:00
@wcsjtu 看实现吧,通常并不一定需要记录映射。你把 P 当作对 client 是一个 server,对 S 是一个 client,然后你如果连接 S 的时候用了一个本身支持连接池的 http client lib,那你用这个 lib 发请求的时候就会从连接池里拿一个对应的连接出来。
wcsjtu
2017-12-01 15:01:32 +08:00
@xiaxiaocao 我这样想的。如果 CP、PS 都是持久连接,而且是 1 对 1 的情况下,后续 C 的请求起始行就可以不带 host 信息了。 类似于 http CONNECT 和 socks5 那样,第一个包用来打通连接的,需要带上 C 的地址,后续的包就不用了。
wcsjtu
2017-12-01 15:02:53 +08:00
@wcsjtu 额, 上一条写错, 应该是需要带上 S 的地址
xiaxiaocao
2017-12-01 15:05:15 +08:00
@wcsjtu 这个我真不知道……按照 RFC 的说法,The absoluteURI form is REQUIRED when the request is being made to a proxy,所以这种不带 host 的情况,是不应该出现的。
wcsjtu
2017-12-01 15:21:21 +08:00
@xiaxiaocao 这个我也看到了。。。。。。那为什么我经常从 Request-URI 中解析 host 失败。。。。。还是滚回去检查代码吧。。。。。
wcsjtu
2017-12-01 15:33:09 +08:00
@xiaxiaocao 额~ 我在 rfc2068 里 8.1.3 节看到这句话

The proxy server MUST signal persistent connections separately with its clients and the origin servers (or other proxy servers) that it connects to. Each persistent connection applies to only one transport link.

这意味着 CP PS 是 1 对 1 的?
xiaxiaocao
2017-12-01 15:42:04 +08:00
@wcsjtu 看着是这个意思,那是我理解错了
tanxiong
2020-01-05 14:40:46 +08:00
@wcsjtu 按照这种说法, 如果 PC 之间的连接关闭了会怎么处理? S 感知不到, 并且 S 以为还继续和 C 维持长连接,这时候 S 往 P 发送数据呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/411098

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX