- Hyper Text Transfer Protocol,超文本传输协议
- 工作于客户端-服务端架构上,浏览器作为HTTP客户端通过URL向HTTP服务端发送请求
HTTP允许传输任意类型的数据对象,正在传输的类型由Content-Type标记
基础概念
URL
- URI Uniform Resource Identifier,统一资源标识符
- URI 包含 URL和URN
- 用来唯一地标识一个资源,访问资源的命名机制+存放资源的主机名+资源自身的名称
- URL Uniform Resource Locator,统一资源定位符
- 一种具体的URI
- 协议+主机地址+主机资源的具体地址
- URN Uniform Resource Name,统一资源名称
- 通过名字来标识资源
- URI Uniform Resource Identifier,统一资源标识符
- 请求报文

- 由请求行、请求头部、空行和请求数据四个部分组成
- 请求行
- 同来说明请求类型,要访问的资源及所使用的HTTP版本
- 请求头部
- 用来说明服务器要使用的附加信息
- 空行
- 请求头部后的空行是必须的
- 即使第四部分的请求数据为空,也必须有空行
- 请求数据也叫主体,可以添加任意地其他数据
响应报文
GET
- 请求指定的页面信息,并返回实体主体,主要用来获取资源
- POST
- 主要用来传输数据,可能会导致新的资源的建立或已有资源的修改
- HEAD
- 类似于GET,但返回的响应中没有具体内容,用于获取报头
- 主要用于确认URL的有效性及资源更新的日期时间等
- CONNECT
- 要求在于代理服务器通行时建立隧道
- 使用SSL、TLS协议把通信内容加密后经网络隧道传输
- OPTIONS
- 查询指定的URL能够支持的方法
- TRACE
- 追踪路径,服务器会把通信路径返回给客户端
- 发送请求时,在Max-Forwards首部字段填入数值,没经过一个服务器就会减1,当为0时停止传输
- 通常不会使用,易受XST(跨站追踪)攻击。主要用于测试或诊断
- PATCH
- 对资源进行部分修改,PUT只能完全替代原始资源
- PUT
- 从客户端向服务器传送的数据取代指定的文档的内容
- 由于自身不带验证机制,因此存在安全性问题,一般不适用
DELETE

- 1XX 信息
- 100 Continue :表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应
- 2xx 成功
- 200 OK
- 204 No Content :请求已经成功处理,但是返回的响应报文不包含实体的主体部分。一般在只需要从客户端往服务器发送信息,而不需要返回数据时使用
- 206 Partial Content :表示客户端进行了范围请求,响应报文包含由 Content-Range 指定范围的实体内容
- 3XX 重定向
- 301 Moved Permanently :永久性重定向
- 302 Found :临时性重定向
- 303 See Other :和 302 有着相同的功能,但是 303 明确要求客户端应该采用 GET 方法获取资源 注:虽然 HTTP 协议规定 301、302 状态下重定向时不允许把 POST 方法改成 GET 方法,但是大多数浏览器都会在 301、302 和 303 状态下的重定向把 POST 方法改成 GET 方法。304 Not Modified :如果请求报文首部包含一些条件,例如:If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,如果不满足条件,则服务器会返回 304 状态码
- 307 Temporary Redirect :临时重定向,与 302 的含义类似,但是 307 要求浏览器不会把重定向请求的 POST 方法改成 GET 方法
- 4XX 客户端错误
- 400 Bad Request :请求报文中存在语法错误
- 401 Unauthorized :该状态码表示发送的请求需要有认证信息(BASIC 认证、DIGEST 认证)。如果之前已进行过一次请求,则表示用户认证失败
- 403 Forbidden :请求被拒绝
- 404 Not Found
5XX 服务器错误
通用首部字段
- Cache-Control,控制缓存的行为
- Connection,控制不再转发给代理的首部字段、管理持久连接
- Date,创建报文的日期时间
- Pragma,报文指令
- Trailer,报文末端的首部一览
- Transfer-Encoding,指定报文主体的传输编码方式
- Upgrade,升级为其他协议
- Via,代理服务器的相关信息
- Warning,错误通知
- 请求首部字段
- Accept,用户代理可处理的媒体类型
- Accept-Charset,优先的字符集
- Accept-Encoding,优先的内容编码
- Accept-Language,优先的语言(自然语言)
- Authorization,Web认证信息
- Expect,期待服务器的特定行为
- From,用户的电子邮箱地址
- Host,请求资源所在服务器
- If-Match,比较实体标记(ETag)
- If-Modified-Since,比较资源的更新时间
- If-None-Match,比较实体标记(与If-Match相反)
- If-Range,资源未更新时发送实体Byte的范围请求
- If-Unmodified-Since,比较资源的更新时间(与If-Modified-Since相反)
- Max-Forwards,最大传输跳数
- Proxy-Authorization,代理服务器要求客户端的认证信息
- Range,实体的字节范围请求
- Referer,对请求中URI的原始获取方
- TE,传输编码的优先级
- User-Agent,HTTP客户端程序的信息
- 响应首部字段
- Accept-Ranges,是否接收字节范围请求
- Age,推算资源创建经过时间
- ETag,资源的匹配信息
- Location,令客户端重定向至指定URI
- Proxy-Authenticate,代理服务器对客户端的认证信息
- Retry-After,对再次发起请求的时机要求
- Server,HTTP服务器的安装信息
- Vary,代理服务器缓存的管理新
- WWW-Authenticate,服务器对客户端的认证信息
实体首部字段
连接管理

- 短连接与长连接
- 当浏览器访问一个包含多张图片的HTML页面时,除了请求访问HTML页面资源,还会请求图片资源。如果每进行一次HTTP通信就要新建一个TCP连接,那么开销会很大
- 长连接只需要建立一次TCP连接就能进行多次HTTP通信
- 从HTTP/1.1开始默认是长连接的,如果要断开连接,需要由客户端或服务端提出断开,Connection:close;
- HTTP/1.1之前默认短链接,如需使用长连接,则使用Connection:Keep-Alive
- HTTP判断一个报文结束
- 无entity body,则”\r\n\r\n”(两个回车符)
- 有entity body,则用”Content-Length”判断
- 流水线
- 默认情况下,HTTP请求时按顺序发出的,下一个请求只有在当前请求收到响应之后才会被发出
- 由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间
- 流水线是在同一条长连接上发出连续的请求,而不用等待响应返回,这样可以避免连接延时
- Cookie
- HTTP/1.1引入Cookie来保存状态信息
- Cookie是服务器发送到浏览器并保存在本地的数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务器两个请求是否来自同一浏览器
- 新的浏览器API已经允许开发者直接将数据存储到本地,如使用Web Storage API或IndexedDB
- 用途
- 会话状态管理(如登录状态、购物车或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
- 创建过程
- 服务器发送的响应报文包含Set-Cookie首部字段
- 客户端得到响应报文后Cookie内容保存到浏览器中
- 客户端之后对同一个服务器发送请求时,会从浏览器中取出Cookie信息并通过Cookie请求首部字段发送给服务器
- 分类
- 会话期Cookie:浏览器关闭之后会被自动删除,也就是说仅在会话期内有效
- 持久性Cookie:指定一个特定的过期时间(Expires)或有效期(max-age)
- 作用域
- Domain标识指定了哪些主机可以接受Cookie,若不指定,默认为当前文档的主机(不包含子域名)
- 若指定了Domain,则一般包含子域名
- Path标识指定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)
- HttpOnly
- 标记为 HttpOnly的Cookie不能被JavaScript脚本调用
- 跨站脚本攻击(XSS)常常使用JavaScript的document.cookie API窃取用户的Cookie信息
- Secure
- 标记为Secure的Cookie只能通过被HTTPS协议加密过的请求发送给服务端
- 浏览器禁用Cookie
- 此时无法使用Cookie来保存用户信息,只能使用Session
- 不能再将Session ID存到Cookie,而是使用URL重写技术,将Session ID作为URL的参数进行传递
- Session
- 利用Session将用户信息存储在服务器端,存储在服务器端的信息更加安全
- 可以存储在服务器上的文件、数据库或内存中
- 使用Session维护用户登录状态的过程:
- 用户进行登录时,用户提交包含用户名和密码的表单,放入HTTP请求报文
- 服务器验证该用户名和密码,如正确则把用户信息存储到Redis,它在Redis中的Key称为Session ID
- 服务器返回的响应报文的Set-Cookie首部字段包含了这个Session ID,客户端收到响应报文之后将该Cookie值存入浏览器
- 客户端之后对同一个服务器进行请求时会包含该Cookie值,服务器收到之后提取出Session ID,从Redis中取出用户信息,继续之前的业务操作
- 与 Cookie 进行比较
- Cookie只能存储ASCII码字符串,而Session则可以存取任何类型的数据
- Cookie存在浏览器,容易被恶意查看
- 对于大型网站,如果用户所有的信息都存储在Session中,那么开销是非常大的
- 缓存
- 缓解服务器压力,降低客户端获取资源的延迟
- HTTP/1.1通过Cache-Control首部字段来控制缓存
- no-store,规定不能对请求或响应的任何一部分进行缓存
- co-cache,规定缓存服务器需要先向服务器验证缓存资源的有效性
- private,将资源作为私有缓存,只能被单独用户所使用,一般存储在用户浏览器中
- public,将资源作为公共缓存,可以被多个用户所使用,一般存储在代理服务器中
- 缓存过期机制
- max-age,表示缓存资源在缓存服务器中保存的时间
- 缓存验证
- ETag首部字段的含义,是资源的唯一标识
- URL不能唯一表示资源,如http://www.google.com/有中文和英文两个资源
- 可以将缓存资源的ETag值放入If-None-Match首部
- Last-Modified首部字段也可以用于缓存验证
- 内容协商
- 通过内容协商返回最合适的内容,如根据浏览器的默认语言返回中文界面还是英文界面
- 类型
- 服务端驱动
- 代理驱动
- Vary
- 在使用内容协商的情况下,只有当缓存服务器中的缓存满足内容协商条件时,才能使用该缓存,否则应该向源服务器请求该资源
- 内容编码
- 将实体主体进行压缩,从而减少传输的数据量
- 常见的内容编码有:gzip、compress、deflate、identity
- 浏览器发送Accept-Encoding首部,其中包含有它所支持的压缩算法,以及各自的优先级。服务器则从中选择一种,使用该算法对响应的消息主体进行压缩,并发送Content-Encoding首部来告知浏览器它选择了哪种算法
- 由于该内容协商过程是基于编码类型选择资源的展现形式,在响应的Vary首部至少要包含Content-Encoding
- 请求范围
- 若网络出现中断,服务器只发送了一部分数据,范围请求可以使得客户端只请求服务端未发送的那部分数据,从而避免服务器重新发送所有数据
- Range
- 在请求报文中添加Range首部字段指定请求的范围
- 请求成功的话服务器返回的响应包含206 Partial Content 状态码
- Accept-Ranges
- 响应首部字段Accept-Ranges用于告知客户端是否能处理范围请求,可以处理使用bytes,否则使用none
- 响应状态码
- 在请求成功的情况下,服务器返回 206 Partial Content 状态码
- 在请求的范围越界的情况下,服务器返回 416 Requested Range Not Satisfiable
- 在不支持范围请求的情况下,服务器返回 200 OK
- 分块传输编码
- Chunked Transfer Coding,可以把数据分割成多块,让浏览器逐步显示界面
- 多部分对象集合
- 一份报文主体内可含有多种类型的实体同时发送,每个部分之间用boundary字段定义的分隔符进行分隔,每个部分都可以有首部字段
- 如上传多个表单
- 虚拟主机
- HTTP/1.1使用虚拟主机技术,使得一台服务器拥有多个域名,并且在逻辑上可以看成多个服务器
通信数据转发
HTTP的安全问题
- 使用明文进行通信
- 不验证通信方的身份
- 无法验证报文的完整性
HTTPs不是新协议,而是让HTTP先和SSL通信,再由SSL和TCP通信,即HTTPs使用了隧道进行通信
HTTP/2.0
HTTP/1.x的缺陷
- 实现简单是以牺牲性能为代价的
- 客户端需要使用多个连接才能实现并发和缩短延迟
- 不会压缩请求和响应首部,从而导致不必要的网络流量
- 不支持有效的资源优先级,致使底层TCP连接的利用率低下
- 二进制分帧层
- 将报文分成HEADERS帧和DATA帧,都是二进制格式的
- 在通信过程中,只会有一个TCP连接存在,它承载了任意数量的双向数据流
- 一个数据流(Stream)都有一个唯一标识符和可选的优先级信息,用于承载双向信息
- 消息(Message)是与逻辑请求或响应对应的完整的一系列帧
- 帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装
- 服务端推送
- 在客户请求一个资源时,会把相关资源一起发送给客户端,客户端就不需要再次发起请求了
首部压缩
数据传输方式
- GET提交的数据放在URL之后,以?分割URL和传输数据,参数之间以&相连
- POST把提交的数据放在HTTP包的Body中
- 因为URL只支持ASCII码,因此GET的参数中如果存在中文等字符据需要先进行编码
- 保密性
- POST比GET好一点点
- 幂等性
- 同样的请求被执行多次的效果是一样的,服务器的状态也是一样的
- GET,HEAD,PUT和DELETE是幂等,POST不是
- 传输数据的大小
- HTTP协议没有对传输的数据大小进行限制,也没有对URL长度进行限制
- GET:特定浏览器和服务器对URL长度有限制
- POST:WEB服务器会规定post数据大小
- 速度
- GET产生一个TCP数据包,POST产生两个
- GET:浏览器把http header和data一并发送出去,服务器响应200(返回数据)
- POST:浏览器先发送header,服务器响应100 continue;再发送data,服务器响应200 OK(返回数据)

