0%

HTTP消息在服务器端的路由

在上一篇文章中,我们介绍了客户端如何与服务器建立起连接,那么这篇文章中,将介绍服务器接收到连接以后,又怎样把HTTP消息进行路由和处理的常规流程。这里重点将介绍HOST这个请求头部。

HOST头部

  • HOST = uri-host [":" port] (ABNF对它的定义)
    • HTTP/1.1规范要求,不传递Host头部则返回400错误响应码(为什么HTTP/1.1规范要加入这样一个要求呢?因为在HTTP/1.0这个版本中,是没有HOST头部的。因为HTTP/1.0所在的上世纪90年代中,域名相对是比较少的,每一个服务器的ip地址仅对应一个域名,所以当用户已经对你的服务器建立起连接以后,你是不需要考虑匹配那个域名对应的服务的。但是后来我们发现,HTTP域名众多,但是ip地址相对比较少,所以我们引入了HOST头部。)
    • 为防止HTTP/1.0时代的陈旧的代理服务器还在我们的网络中,发向正向代理的请求request-target必须以absolute-form形式出现
      • request-line = method SP request-target SP HTTP-version CRLF
      • absolute-form = absolute-URI
        • absolute-URI = scheme ":" hier-part ["?" query ]

规范和实现间是有差距的

  • 关于Host头部:https://tools.ietf.org/html/rfc7230#section-5.4
    • A cliend MUST send a Host header field in all HTTP/1.1 request messages.
    • A server MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message that lacks a Host header field and to any request message that contains more than one Host header field or a Host header field with an invalid field-value.

Host头部与消息的路由

(这里我们以典型的nginx来处理HOST头部的流程,来演示大部分的Web服务器在建立好TCP连接以后,究竟是怎样来寻找消息的处理模块的)

  1. 建立TCP连接
    • 确定服务器的ip地址
  2. 接收请求
  3. 寻找虚拟主机
    • 匹配Host头部域名(请求行URI中,可能拿到了absolute-form,也就是绝对形式中因为这里可以取到域名,或者从Header中的Host头部也可以取到域名,拿到这个域名以后,就会和这台Web服务器所支持的所有域名进行匹配,匹配选中以后,就会选中相应的模块进行处理)
  4. 寻找URI的处理代码(接着进行第二步的路由匹配,就是按照URI中的Path路径,一一匹配相应的代码,找到处理请求的代码,然后开始访问相应的资源)
    • 匹配URI
  5. 执行处理请求的代码
    • 访问资源
  6. 生成HTTP响应
    1. 各中间件基于PF架构串行修改响应
  7. 发送HTTP响应
  8. 记录访问日志

小结

这篇文章中介绍了HOST头部,以及如何基于HOST进行消息的路由,这里我们所介绍的服务器根据HOST头部路由的流程,与大多数Web服务器相似,对我们具有参考价值。