HTTP

日常最常用的协议

默认端口80

重要功能


HTTP 1.1

  • 长连接(Keep Alive)
    创建连接有开销,长连接可以复用,默认长连接,无需加参数
  • 管线化(Pipeline)
    同一TCP连接上发起多个请求,不必等待上一个响应,但是响应顺序必须和请求顺序一致,相当于减轻了请求间等待,适合高延迟环境下
    由于实现复杂,中间代理也必须配合,并且其中前面的阻塞了会影响后续整体,一般浏览器默认不开启
  • 增加host字段

HTTP 2.0

  • 多路复用(Multiplexing)
    同一TCP连接上并发进行多个请求,响应顺序任意,多个请求相当于独立
    之前浏览器对同一时间,同一域名的连接数有限制,因此浏览器都是一批一批地多连接请求,多路复用后可以实现更大量的同时请求,而且对于TCP的慢启动有帮助
    之所以实现复用,避免数据混合在一起,基于传输层和应用层间的二进制分帧。相当于给每份数据打上标记,这样接收端就能区分开哪些数据是一起的,实现复用

  • 头数据压缩(Header Compression)
    一般消息主体部分压缩,而状态行和头部采用纯文本,由于每次携带cookie,并且头部信息重复,开销过大
    可以在服务端和浏览器同时维护一个字典,采用字典编码替换真实值,处理后传输量小,提高传输性能
    字典可以动态添加,根据传输逐渐补充,字典构建越全,压缩效果越好。

  • 服务器推送(Server Push)
    响应请求时顺便响应以后可能需要的其他资源,存在客户端本地,客户端使用时直接本地加载,无需再发起网络请求
    比如返回一个html,但是内部有js外链,服务器把js也一并返回,省去js的单独请求流程

格式


请求格式

1
2
3
4
请求行(请求方法 URL 协议版本)
请求头(字段名 值)
空行
请求数据

响应格式

1
2
3
4
状态行(协议版本 状态码 状态文字)
响应头(字段名 值)
空行
响应数据

body数据长度由头部字段Content-Length决定
如果很大无法提前预知长度,可以使用头部字段Transfer-Encoding: chunked
每个chunk包含自己的长度和内容,空行分隔,遇到长度0的chunk表示结束

请求方式


  • GET:幂等,请求资源
  • POST:非幂等,执行动作,可用于创建资源
  • PUT: 幂等,全量替换资源
  • PATCH:非幂等,部分修改资源,执行特定协议动作
  • DELETE:幂等,删除资源
  • HEAD:只返回响应头,用于测试资源有效性
  • TRACE:回显服务器收到的请求,用于测试或诊断。

常见状态码


1XX 指示信息

  • 101 Switching Protocols
    协议切换,响应头包含Upgrade,比如websocket建立时就会发送

2XX 成功

  • 200 OK
    请求成功处理,最常见于GET
  • 201 Created
    资源已创建,多用POST同步逻辑返回码
  • 202 Accepted
    已接受但尚未处理,多用于POST异步逻辑返回码
  • 204 No Content
    请求成功处理并且响应主体不包含内容,多用于PUT/DELETE返回
  • 206 Partial Content
    客户端进行范围请求请求头包含Range,响应头包含Content-Range字段
    可以实现断点续传

3XX 重定向

  • 301 Permanently Moved
    永久重定向,响应头Location包含新位置,后续都应访问新地址
  • 302 Found
    临时重定向,本次请求暂且使用新位置
    网址劫持(URL hijacking),搜索引擎遇到302,会评估原地址和新地址,选取其中一个进行收录
    如果有恶意网站故意302跳转到高质量网站,那么恶意网站可能凭借优质内容得以收录
  • 303 See Other
    资源存在另一地址,使用GET再次访问,和302功能类似,但强调GET访问
  • 304 Not Modified
    请求头包含If系列的字段(If-Match,If-Modified-Since),响应表示未满足条件,响应主体不包含内容
  • 305 Use Proxy
    需要通过特定代理才能访问,返回Location表示代理地址
  • 307 Temporary Redirect
    与302功能类似,但强调不更改请求类型,原来是POST那么再发起请求依然应该是POST
  • 308 Permanent Redirect
    301不更改请求类型的版本

4XX 客户端错误

  • 400 Bad Request
    报文语法错误,缺少请求体,缺少字段等,服务端无法处理
  • 401 Unauthorized
    需要HTTP认证(BASIC,DIGEST),响应头包含WWW-Authenticate字段标明使用哪种认证方式及相关认证信息,网页会弹窗要求输入认证信息
    也用于返回密码不匹配,token有误的情况,为了防止试探时也可以直接返回404
  • 403 Forbidden
    权限不足,拒绝访问
  • 404 Not Found
    没有相应资源,也可表示无理由拒绝访问
  • 405 Method Not Allowed
    资源存在,但是请求方法不对,返回Allow字段,说明支持的方法
  • 406 Not Acceptable
    无法满足Accept指定的格式
  • 408 Request Timeout
    发送请求超时
  • 409 Conflict
    存在冲突无法处理,比如数据版本不对,状态不满足
  • 410 Gone
    与404区别是资源以前存在,但是永久消失
    而404只强调当前不存在,不清楚过去的情况,也不能判定是否临时
  • 411 Length Required
    没有携带Content-Length
  • 412 Precondition Failed
    不满足if操作条件
  • 413 Payload Too Large
    发送的实体过大
  • 414 URI Too Long
    URL过长,可能是错把post发成了get
  • 415 Unsupported Media Type
    服务器不支持Content-Type指定的类型
  • 418 I’m a teapot
    彩蛋https://www.google.com/teapot
  • 421 Too many connections
    服务器观察到的请求IP(可能是网关或代理的)连接过多
  • 429 Too Many Requests
    访问频率过多

5XX 服务端错误

  • 500 Internal Server Error
    服务端故障
  • 501 Not Implemented
    服务端不支持
  • 502 Bad Gateway
    代理服务器从上游收到响应,但是无效
  • 503 Service Unavailable
    服务端超负载或正在维护,暂时无法处理请求
    响应头可能包含Retry-After字段
  • 504 Gateway Timeout
    代理服务器没有从上游收到响应,超时
  • 505 HTTP Version Not Supported
    HTTP版本不支持

HTTP隧道


很多情况下只开放80端口,只接受HTTP数据
可以将HTTP作为一种通道,把非HTTP协议数据包装成HTTP传输

HTTP报头


根据作用可以划分

  • 通用报头
  • 请求报头
  • 响应报头
  • 实体报头

内容协商

  • Accept与Content-Type
    Accept属于请求,表示期望服务端返回的格式,因为对方资源可能提供多种格式
    Content-Type属于实体,描述当前发送给对方的实体格式

条件操作

  • If-Match与ETag
    If-Match属于请求头,如果资源还保持特定ETag,就进行操作
    ETag属于响应头,描述资源状态,在资源发生改变时可以重新生成

  • If-Modified-Since与Last-Modified
    服务端比较,如果没变化直接返回304,不再发送资源

Cache策略

Cache-Control属于通用头,请求响应都可携带
请求时携带可以控制浏览器行为,比如强制刷新

缓存位置参数

  • private:只能浏览器缓存,即单个用户缓存,不能共享
  • public:浏览器或者CDN都能缓存,可以共享

缓存策略参数

  • no-cache:可以缓存但是使用前要确认有效性
  • no-store:不允许被缓存

过期参数

  • max-age:缓存有效期多少秒
  • must-revalidate:过期后,必须向服务器确认后才能使用

有效性确认通常使用ETag和Last-Modified机制

传输大小

如果能明确大小,那么Content-Length控制
如果不能明确大小,那么Transfer-Encoding: chunked表示分块传输,最后一块长度为0表示结束

长连接

标准请求应答后就关闭连接,加入Connection: Keep-Alive通知对方不要关闭,版本1.1起默认长连接,显式Connection: close才会关闭
长连接的缺点是占用资源,一般服务端都有timeout参数设置
也可以在HTTP头中指定,Keep-Alive: timeout=5, max=1000即保持连接5秒,最多发送1000次请求

长度制约


HTTP协议本身并没有规定GET的URL长度和POST负载长度
GET时URL长度限制来源于浏览器和服务器,不同厂商不同,一般2048字符是安全的
POST时负载长度限制来源于服务器,比如Tomcat默认长度2M,可以手动配置成无限制