HTTP 全称超文本传输协议,是 OSI 七层模型中应用层协议,万维网数据通信的基础,通过它定义了用户到网站请求和应答的标准。
HTTP 协议采用请求/响应模型,客户端向服务端发送请求报文,请求报文包含请求的方法、URL、协议版本,请求头以及请求数据。服务端以一个状态行作为响应,响应的内容还包含协议的版本、成功或错误代码、服务端信息,响应头部和响应数据
URL:统一资源定位符,是 Internet 上标准资源的地址,URL 指示资源的位置以及用于访问它的协议
所谓请求/响应模型是指请求只能从客户端发出,服务端只负责响应,它本身不主动请求。下面我简单描述一次请求/响应全过程:
- 客户端与 web 服务器默认 HTTP 端口(80 端口)建立 TCP 套接字连接
- 客户端通过套接字发送请求报文,报文由请求行、请求头部、空行和请求数据四部分组成
- 服务端解析请求,定位请求资源,将资源副本写回 TCP 套接字,返回响应报文。响应报文包括状态行、响应头部、空行和响应数据
- 客户端(浏览器)解析服务端响应,在浏览器展示响应内容
- 默认服务端主动断开连接,客户端被动关闭连接,释放 TCP 连接
HTTP 报文格式如下图所示:
请求头部本质是一个传递额外信息的键值对,按功能分为:通用头、请求头,响应头和实体头
通用头客户端和服务端都可以,通常包含以下字段:
- Cache-Control:用来指定当前请求(回复)是否使用缓存机制
- Connection:客户端想要优先使用的连接类型
- Date:报文创建时间
- Trailer:实现说明在报文主体后记录哪些首部字段
- Transfer-Encoding:用来改变报文格式
- Upgrade:要求服务端升级到一个高版本协议
- Via:告诉服务端,这个请求是由哪些代理发出
- Warning:一般性警告,表示实体内容可能存在错误
HTTP 协议并没有规定一定使用使用 TCP/IP 协议或 TCP/IP 支持的层,它只关注下层提供可靠的传输,任何能提供这种保障的协议都可以被 HTTP 协议用到。因此 HTTP 可以使用 TCP 协议作为传输层协议
早期 HTTP 1.0 时期,HTTP 请求是无连接的,每个 HTTP 请求都需要先建立 TCP 连接,连接建立后发送并接收返回信息,之后断开连接。频繁的创建和断开 TCP 连接带来了大量的资源消耗,HTTP 1.1 时期引用 Keep-Alive 机制,默认开启。旧版本 HTTP 可以通过配置通用头开启 Keep-Alive 机制:
Connection: keep-alive
在 Keep-Alive 机制下,服务端在响应后保持 TCP 连接打开,之后浏览器可以复用这趟连接,通过 keep-alive timeout 参数控制连接持续的时间,保证连接最终能够被释放
Keep-Alive 机制不是一定有好处:如果用户量很大,达到千万甚至上亿,采用长连接需要服务端维护大量的 TCP 连接,性能反而更差
请求头只能在请求报文中使用,旨在告诉服务端一些额外信息,通常包含以下字段:
- Accept:告诉服务端自己允许哪些媒体类型
- Accept-Charset:申明可接受的字符集
- Accept-Encoding:申明可接受的编码方法
- Accept-Language:申明可接受的语言列表
- Authorization:需要认证资源的认证信息
- Expect:要求服务端做出特定的行为
- From:发出此请求的邮件地址
- Host:服务端域名以及监听的端口
- If-XXX:条件请求
- Max-Forwards:限制该消息可被代理网关转发的次数
- Range:表示请求某个实体的一部分
- Referer:浏览器所访问的前一个页面
- User-Agent:身份标识字符串
响应头只在响应报文中使用,便于为客户端提供信息,通常包含以下字段:
- Accept-Ranges:用于定义范围的单位
- Age:创建响应的时间
- ETag:唯一标识分配的资源
- Location:重定向后的 URL
- Retry-After:告诉客户端多久后再发送请求
- Server:告诉客户端服务端信息
- Vary:缓存控制
实体头用于应对实体本身,通常包含以下字段:
- Allow:对某网络资源有效请求行为,不允许则返回 405
- Content-encoding:返回内容编码格式
- Content-Length:返回内容的字节长度
- Content-Language:返回内容的语言
- Content-Location:请求资源可替代的备用地址
- Content-MD5:返回资源的 MD5 校验值
- Content-Range:在整个返回体中本部分的字节位置
- Content-Type:返回内容的类型
- Expires:响应过期的日期和时间
- Last-Modified:请求资源的最后修改时间
早期浏览器请求服务端时,为了保证浏览器能够加载完整的返回信息,一般通过 Content-Length 字段记录数据长度,因为静态资源服务端可以预先知道大小。对于动态加载的资源,需要使用 Transfer-Encoding: chunked 来代替 Content-Length
Transfer-Encoding: chunked 是 HTTP 1.1 引用的分块传输编码机制,早期一次请求返回所有数据,使用 chunked 可以将数据分为一系列数据报发送,此时服务端无需知道发送内容的大小,直到最后一个分块长度为 0 时,表示数据发送完毕,同样客户端可以以此为标识确定数据接收完毕
直到 HTTP 1.1 为止,HTTP 协议包含以下九种请求方法:
- GET:请求指定页面内容,通常用于读取数据
- POST:向指定资源提交数据进行处理请求,通常用于上传数据
- HEAD:类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
- PUT:替换指定的资源,没有的话就新增
- DELETE:请求服务端删除 URL 标识的资源数据
- CONNECT:将服务端作为代理,让服务端代替用户进行访问
- OPTIONS:向服务端发送该方法,会返回对指定资源所支持的 HTTP 请求方法
- TRACE:回显服务端收到的请求数据,即服务端返回自己收到的数据,主要用于测试和诊断
- PATCH:是对 PUT 方法的补充,用来对已知资源进行局部更新
就 web 开发来说,GET 请求一般用于请求资源,因为它会把参数暴露在 URL 地址中,不适合用来提交数据,并且 GET 请求长度有限,POST 请求将参数封装在主体中,支持更多的数据类型、字符格式和编码格式,并且 POST 请求大小无限制,更适合用来上传数据。
除 GET、POST 请求外,其它请求用的较少,一般情况下 PUT、DELETE 请求可以通过 POST 请求代替,其它请求常常用于测试或其它方面,一般不用于线上环境