HTTP 协议
- HTTP(Hyper Text Transfer Protocol)超文本传输协议。
特点
- 基于 TCP 协议,默认端口 80。
- 基于请求响应模型。
- 无状态
版本历史
- 1.0,默认短连接,请求队列阻塞。
- 1.1,默认长连接,请求应答管线化不阻塞,增强缓存控制等。
- 2.0,在TCP上增加二进制分桢层,支持多路复用及优先级,头部压缩,服务器推送等。
- 高版本兼容低版本。
请求报文格式
- 请求行,起始行包括【请求方法 URI 版本号】。
- 请求方法,如GET/POST/HEAD/PUT/DELETE等。
- URI,请求的资源路径。
- 版本号,如HTTP/1.1。
- 请求头,键值对
- 字段名不区分大小写,可用符号-,不可用下划线。
- 字段名后紧跟冒号,字段值前可以多个空格。
- 不区分顺序。
- 空行,CRLF 换行符,\r\n
- 请求体,POST 请求的请求体。
响应报文格式
- 状态行,包括【版本号 状态码 状态描述】。
- 版本号,如HTTP/1.1。
- 状态码,三位数,如 200/404/500等。
- 响应头,键值对。
- 空行,CRLF 换行。
- 响应体,服务器响应的资源。
请求方法
- GET,获取信息,参数附在 URL 后,存在长度限制。
- POST,提交信息,数据在请求体中。
- HEAD,只请求头部。
- PUT,创建资源。
- DELETE,删除资源。
- PATCH,修改资源。
- OPTIONS,查询指定 URL 支持的 HTTP 方法。
请求头字段
- Host:服务器的域名或 IP 地址,如默认 80 端口可省略。
- Connection:keep-alive表示保持连接,close 为关闭连接。
- Accept:接受的内容各类型,如application/json。
- Accept-Encoding:接受的编码格式,如gzip。
- Accept-Language:接受的语言,如 zh-CN。
- Referer:前一个页面地址。
- Cache-Control:缓存控制,如no-cache不使用缓存。
- User-Agent:发起请求的用户代理,如浏览器或客户端软件。
- Cookie:发送给服务端的Cookie。
状态码
- 1XX,信息类,需继续请求。
- 2XX,成功类,200为 OK。
- 3XX,重定向类,301为永久重定向,302为临时重定向
- 304 未修改,客户端可以使用之前的缓存。
- 4XX,客户端错误,404为找不到资源。
- 5XX,服务器错误,500为服务器内部错误。
响应头字段
- Age:在缓存代理服务中驻留的时长,单位秒。
- Content-Length:内容长度,只有持久连接时才有效。
- Content-Type:内容类型,如text/html。
- Set-Cookie:设置 Cookie
- Expires
- 由HTTP1.0支持。
- 在响应头中返回 Expires,客户端根据该时间判断是否重新请求。
- 存在问题,服务器时间与客户端时间可能不一致。
- Cache-Control
- 由HTTP1.1支持,优先级高于 Expires。
- 逗号分隔值
- 值 no-store,不使用缓存
- 值 no-cache,未与服务端验证新鲜度前不允许返回客户端使用。
- 值 public 公有,可被中间层缓存。
- 值 private 私有,不可被中间层缓存。
- 值 max-age=秒,替代 Expire。
- Last-Modified
- 值为UTC时间,到秒。
- 表示资源最后修改时间,用于客户端判断缓存是否最新。
- 下次请求时头部会包含 If-Modified-Since。
- Etag
- 值为一个标识,资源发送修改会生成新的。
- 比Last-Modified(到秒)更准确。
- 下次请求时头部会包含 If-None-Match。
长连接、管线化和多路复用
- 长连接
- 长连接是指请求响应后不断开TCP连接。
- HTTP/1.1起,如果客户端不设置Connection,默认表示Keep-Alive长连接。
- 服务端如果支持长连接,则相应头Connection为Keep-Alive,开启长连接。
- 如果没有再请求,通过超时机制断开连接,linux的tcp保活时间是2小时(t1 + t2 * N)
- 管线化
- 管线化是解决请求响应模型的阻塞问题,只针对get/head请求。
- 多个请求管线化发起,服务端再按顺序管线化响应。
- 管线化仍然存在队头阻塞问题,因为必须确保响应的有序性。
- 浏览器通常会使用发起多个长连接的方式来缓解队头阻塞问题。
- 多路复用
- 多路复用是指在一个TCP连接上实现任意请求的并行传输。
- HTTP/2.0起支持多路复用。
- 底层是基于二进制分帧,每个请求有唯一流ID,分成多个帧传输,接收方组装得到。
URI
- URI(Uniform Resource Identifier),统一资源标识符。
- 用来唯一标识资源。
- 格式:scheme://[user:password@]host[:port]/path[?query][#fragment]
- scheme为协议,如http、https、ftp、ssh、smb等。
- user:password@为登录的用户和密码,非必需。
- host:port为主机名和端口,端口省略表示使用协议默认端口。
- path为资源所在的位置。
- query为查询参数,为key=val形式,多个用&隔开。
- fragment表示资源内的锚点。
- URI只能用ASCII码,非ASCII的字符和界定符需转为百分号编码(十六进制字节值,在前面加%号)。
- URL用来定位资源,URI只是标识资源。