3月阅读周·HTTP权威指南:代理之与代理请求有关的一些棘手问题篇

举报
叶一一 发表于 2025/03/17 18:30:57 2025/03/17
【摘要】 引言HTTP(Hypertext Transfer Protocol,超文本传输协议[插图])是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于Web浏览器和Web服务器之间的双工通信。《HTTP权威指南》一书将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节介绍HTTP各方面的特性。纵观全书,对HTTP“为什么”这样做进行了详细的解...

引言

HTTP(Hypertext Transfer Protocol,超文本传输协议[插图])是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于Web浏览器和Web服务器之间的双工通信。

《HTTP权威指南》一书将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节介绍HTTP各方面的特性。纵观全书,对HTTP“为什么”这样做进行了详细的解释,而不仅仅停留在它是“怎么做”的。此外,这本书还介绍了很多HTTP应用程序正常工作所必需且重要的非HTTP技术。

这本书主要包括以下内容:

  • 第一部分描述了Web的基础构件与HTTP的核心技术
  • 第二部分重点介绍了Web系统的结构构造块:HTTP服务器、代理、缓存、网关以及机器人应用程序。
  • 第三部分提供了一套用于追踪身份、增强安全性以及控制内容访问的技术和技巧。
  • 第四部分涵盖HTTP报文主体和Web标准,前者包含实际内容,后者描述并处理主体内容。
  • 第五部分介绍了发布和传播Web内容的技巧。
  • 第六部分是一些很有用的参考附录,以及相关技术的教程。

代理

Web代理(proxy)服务器是网络的中间实体。代理位于客户端和服务器之间,扮演“中间人”的角色,在各端点之间来回传送HTTP报文。

与代理请求有关的一些棘手问题

代理URI与服务器URI的不同

除了一点之外,Web服务器报文和Web代理报文的语法是一样的。客户端向服务器而不是代理发送请求时,HTTP请求报文中的URI会有所不同。

客户端向Web服务器发送请求时,请求行中只包含部分URI(没有方案、主机或端口),如下例所示:

GET /index.html HTTP/1.0
User-Agent: SuperBrowser v1.3

但当客户端向代理发送请求时,请求行中则包含完整的URI。例如:

GET http://www.marys-antiques.com/index.html HTTP/1.0
User-Agent: SuperBrowser v1.3

为什么会有两种不同的请求格式,一种用于代理,另一种用于服务器呢?在原始的HTTP设计中,客户端会直接与单个服务器进行对话。不存在虚拟主机,也没有为代理制定什么规则。单个的服务器都知道自己的主机名和端口,所以,为了避免发送冗余信息,客户端只需发送部分URI即可,无需发送方案和主机(以及端口)。

代理出现之后,使用部分URI就有问题了。代理需要知道目标服务器的名称,这样它们才能建立自己与服务器的连接。基于代理的网关要知道URI的方案才能连接到FTP资源和其他方案上去。HTTP/1.0要求代理请求发送完整的URI,解决了这个问题,但它为服务器请求保留部分URI的形式(已经有相当多的服务器都改为支持完整URI了)。

因此,我们要将部分URI发送给服务器,将完整URI发送给代理。在显式地配置客户端代理设置的情况下,客户端就知道要发布哪种类型的请求了。

(1) 没有设置客户端使用代理时,它会发送部分URI。

(2) 设置客户端使用代理时,它会发送完整URI。

与虚拟主机一样的问题

代理“缺少方案/主机/端口”的问题与虚拟主机Web服务器面临的问题相同。虚拟主机Web服务器会在很多Web站点间共享同一个物理Web服务器。包含部分URI(比如/index.html)的请求到达时,虚拟主机Web服务器需要知道目的Web站点的主机名。

尽管它们出现的问题相似,但解决方法却有所不同:

  • 显式的代理要求在请求报文中使用完整URI来解决这个问题;
  • 虚拟主机Web服务器要求使用Host首部来承载主机和端口信息。

拦截代理会收到部分URI

只要客户端正确地实现了HTTP,它们就会在请求中包含完整的URI,发送给经过显式配置的代理。这样解决了部分问题,但还有一个问题:客户端并不总是知道它是在和代理进行对话,因为有些代理对客户端可能是不可见的。即使没有将客户端配置为使用代理,客户端的流量也可能会经过替代物或拦截代理。在这两种情况下,客户端都会认为它在与Web服务器进行对话,不会发送完整的URI。

  • 如前所述,反向代理是一个用来取代原始服务器的代理服务器,它通常会通过假扮服务器的主机名或IP地址来做到这一点。它会收到Web服务器请求,可能会向真正的服务器提供缓存的响应或者代理请求。客户端无法区分反向代理和Web服务器,因此它会发送部分URI。
  • 拦截代理 是网络流量中的代理服务器,它会拦截从客户端发往服务器的请求,并提供一个缓存响应,或对其进行转发。由于拦截代理拦截了从客户端到服务器的流量,所以它会收到发送给Web服务器的部分URI。

代理既可以处理代理请求,也可以处理服务器请求

由于将流量重定向到代理服务器的方式有所不同,通用的代理服务器既应该支持请求报文中的完整URI,也应该支持部分URI。如果是显式的代理请求,代理就应该使用完整URI,如果是Web服务器请求,就应该使用部分URI和虚拟Host首部。

使用完整和部分URI的规则如下所示。

  • 如果提供的是完整URI,代理就应该使用这个完整URI。
  • 如果提供的是部分URI,而且有Host首部,就应该用Host首部来确定原始服务器的名字和端口号。
  • 如果提供的是部分URI,而且没有Host首部,就要用其他方法来确定原始服务器:
    • 如果代理是代表原始服务器的替代物,可以用真实服务器的地址和端口号来配置代理;
    • 如果流量被拦截了,而且拦截者也可以提供原始的IP地址和端口,代理就可以使用拦截技术提供的IP地址和端口号;
    • 如果所有方法都失败了,代理没有足够的信息来确定原始服务器,就必须返回一条错误报文(通常是建议用户升级到支持Host首部的现代浏览器)。

转发过程中对URI的修改

代理服务器要在转发报文时修改请求URI的话,需要特别小心。对URI的微小修改,甚至是看起来无害的修改,都可能给下游服务器带来一些互操作性问题。

尤其是,现在已知有些代理会在将URI转发给下一跳节点之前将URI“规范”为标准格式。有些看起来无害的转换行为,比如用显式的“:80”来取代默认的HTTP端口,或者用适当的换码转义符来取代非法的保留字符以校正URI,就可能造成互操作性问题。

总之,代理服务器要尽量宽容一些。它们的目标不是成为强制实现严格协议一致性的“协议警察”,因为这样可能会严重破坏之前能正常工作的服务。

特别是,HTTP规范禁止一般的拦截代理在转发URI时重写其绝对路径部分。唯一的例外是可以用“/”来取代空路径。

URI的客户端自动扩展和主机名解析

根据是否有代理,浏览器对请求URI的解析会有所不同。没有代理时,浏览器会获取你输入的URI,尝试着寻找相应的IP地址。如果找到了主机名,浏览器会尝试相应的IP地址直到获得成功的连接为止。

但是,如果没有找到主机,很多浏览器都会尝试着提供某种主机名自动“扩展”机制,以防用户输入的是主机“简短”的缩写形式。

  • 很多浏览器会尝试着加入前缀www.和后缀.com,以防用户只输入了常见Web站点名的中间部分(比如,人们可以输入yahoo而不是www.yahoo.com)。
  • 有些浏览器甚至会将未解析出来的URI传递给第三方站点,这个站点会尝试着校正拼写错误,并给出一些用户可能希望访问的URI建议。
  • 而且,大多数系统中的DNS配置允许用户只输入主机名的前缀,然后DNS会自动搜索域名。如果用户位于域名oreilly.com的范围之内,并输入了主机名host7,DNS会自动尝试将其与host7.oreilly.com进行匹配。这并不是完整有效的主机名。

总结

对与代理服务器请求有关的一些比较棘手且易被误解的问题进行了解释,其中包括:

  • 代理请求中的URI和服务器请求中的URI有何不同;
  • 拦截和反向代理是如何将服务器主机信息隐藏起来的;
  • 修改URI的规则;
  • 代理是怎样影响浏览器的智能URI自动完成机制,或主机名扩展特性的。

作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。