HTTP 协议详解
HTTP 协议(HyperText Transfer Protocol,超文本传输协议)是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的,但也可以用于其他目的。HTTP 遵循经典的客户端—服务端模型,客户端打开一个连接以发出请求,然后等待直到收到服务器端响应。HTTP 是无状态协议,这意味着服务器不会在两个请求之间保留任何数据(状态)。
HTTP 特点
- HTTP 协议构建于 TCP/IP 协议之上,是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。
- HTTP 是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP 是媒体独立的(灵活):这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过 HTTP 发送。客户端以及服务器指定使用适合的 MIME-type 内容类型。
- HTTP 是无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP 各版本区别
摘要
- 0.9
- 仅支持 GET
- 纯文本
- 无状态
- 无链接
- 1.0
- GET, POST, HEAD
- 头信息
- 状态码
- 多字符集支持
- 多部分发送(multi-part type
- 权限(authorization)
- 缓存(cache)
- 内容编码(content encoding)等
- keep-alive (手动长连接)
- 1.1
- TCP 复用(可建立 6 个长链接)
- 请求部分内容 (文件断点续传的基础)
- host 头域
- 2.0
- 多路复用(同一个链接并发处理多个请求)
- 服务器推送
详细
- 0.9
- 只允许客户端发送一种 GET 请求
- 只支持纯文本一种内容,服务器只能回应 HTML 格式的字符串
- 具有典型的无状态无链接特性,每个事务独立进行处理,事务结束时就释放这个连接。
- 1.0
- 支持更多的请求方法
- GET 请求指定的页面信息,并返回实体主体。
- HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
- POST 向指定资源提交数据进行处理请求,数据被包含在请求体中,可能会导致新的资源的建立和/或已有资源的修改。
- PUT 从客户端向服务器传送的数据取代指定的文档的内容。
- PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新 。
- DELETE 请求服务器删除指定的页面。
- TRACE 回显服务器收到的请求,主要用于测试或诊断。
- OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求
- CONNECT 保留将来使用
- HTTP 的请求和回应格式也发生了变化,除了要传输的数据之外,每次通信都包含头信息,用来描述一些信息
- 增加了状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等
- HTTP1.0 版本虽然是支持长链接,但是默认情况还是短连接,需要使用 keep-alive 参数来告知服务器建立一个长链接。短连接的主要缺点就是每个 TCP 链接只能发送一个请求,发送数据完毕,链接就会关闭,如果还要请求其他资源就必须要再创建一个连接,TCP 的链接成本是很高的,因为服务器和客户端之间建立链接需要进行三次握手,并且链接初始的时候发送速率是比较慢的,所以 HTTP1.0 版本的性能比较差。
- 支持更多的请求方法
- 1.1
- HTTP1.1 最大的变化就是引入了长链接,也就是 TCP 链接默认是不关闭的可以被多个请求复用。客户端或者服务器如果长时间发现对方没有活动就会关闭链接,但是规范的做法是客户端在最后一个请求的时候要求服务器关闭链接。对于同一个域名,目前浏览器支持建立 6 个长链接。
- HTTP1.1 支持只发送 header 头信息不带任何 body 信息,如果服务器认为客户端有权限请求指定数据那就返回 100,没有就返回 401,当客户端收到 100 的时候可以才把要请求的信息发给服务器。并且 1.1 还支持了请求部分内容,如果当前客户端已经有一部分资源了,只需要向服务器请求另外的部分资源即可,这也是支持文件断点续传的基础。
- 1.1 版本中增加了 host 处理,在 HTTP1.0 中认为每台服务器都绑定一个唯一的 ip 地址,因此在 URL 中并没有传递主机名,但是随着虚拟机技术的发展,可能在一台物理机器上存在多个虚拟主机,并且他们共享了一个 ip 地址,http1.1 中请求消息和响应消息都支持 host 头域,如果不存在还会报出错误
- 虽然 1.1 版本对 1.0 有了很大的提升但是他还是存在缺点,在同一个 TCP 里边所有数据的通信都是按照次序的,服务器只有处理完一个回应,才会解决下一个回应要是前边某个回应处理的比较慢,就会出现后边很多回应等待的情况,这就是常说的队头阻塞。
- 2.0
- HTTP2.0 版本中支持多路复用,支持同一个链接并发处理多个请求,并且并发请求的数量要比以前高出很多的数量级。当然 http1.1 版本中也支持创建多个 TCP 链接来处理多个并发的请求,但是创建 TCP 链接本身也是存在开销的,并且在链接创建初期传输的速度是比较慢的
- 之前我们说从 1.0 版本开始请求和响应增加了 header,header 里边带有大量信息,并且每次都要重新进行发送,2.0 版本通过算法把 header 进行了压缩这样数据体积就更小,在网络上传输就更快。
- HTTP2.0 还支持服务器推送,服务器推送是当客户端请求一定数据的时候,服务器会额外的推送一些客户端可能会用到的信息,这样当客户端再次请求这个信息的时候,就可以直接从本机缓存中读取而不需要再次向服务器请求数据了。
浏览器中从输出 URL 到返回页面的过程
- 进行 DNS 域名解析,浏览器向 DNS 服务器查找输入 URL 对应的 IP 地址
- 浏览器根据 IP 地址与目标 web 服务器在 80 端口上建立 TCP 连接
- 浏览器向 web 服务器地址,发送 HTTP 请求
- web 服务器处理请求,并发送处理结果
- 浏览器得到响应,关闭 TCP 连接
- 浏览器解析 HTML,渲染 DOM
HTTP 状态码
状态码是由 3 位数组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息–表示请求已接收,继续处理。
- 100 客户必须继续发出请求
- 101 客户要求服务器根据请求转换 HTTP 协议版本
2xx:成功–表示请求已被成功接收、理解、接受。
- 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
- 201 (已创建) 请求成功并且服务器创建了新的资源。
- 202 (已接受) 服务器已接受请求,但尚未处理。
- 204 服务器成功处理了请求,但不需要返回任何实体内容
3xx:重定向–要完成请求必须进行更进一步的操作。
- 300 (多种选择) 针对请求,服务器可执行多种操作。
- 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
- 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
- 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4xx:客户端错误–请求有语法错误或请求无法实现。
- 400 (错误请求) 服务器不理解请求的语法。
- 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
- 403 (禁止) 服务器拒绝请求。
- 404 (找不到)
5xx:服务器端错误–服务器未能实现合法的请求。
- 500 (服务器内部错误) 服务器遇到错误,无法完成请求。
- 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
- 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
- 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
- 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
- 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
HTTP Headers
HTTP 标头(header)允许客户端和服务器通过 HTTP 请求(request)或者响应(response)传递附加信息。一个 HTTP 标头由它的名称(不区分大小写)后跟随一个冒号(:),冒号后跟随它具体的值。该值之前的空格会被忽略。
根据不同的消息上下文,标头可以分为:
请求标头 包含有关要获取的资源或客户端或请求资源的客户端的更多信息。 响应标头 包含有关响应的额外信息,例如响应的位置或者提供响应的服务器。 表示标头 包含资源主体的信息,例如主体的 MIME 类型或者应用的编码/压缩方案。 有效负荷标头 包含有关有效载荷数据表示的单独信息,包括内容长度和用于传输的编码。
请求头
- Accept
- Accept 请求报头域用于指定客户端接受哪些类型的信息。eg:Accept:image/gif,表明客户端希望接受 GIF 图象格式的资源;Accept:text/html,表明客户端希望接受 html 文本。
- Accept-Encoding
- Accept-Encoding 请求报头域类似于 Accept,但是它是用于指定可接受的内容编码。eg:Accept-Encoding:gzip.deflate.如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受。
- Accept-Language
- Accept-Language 请求报头域类似于 Accept,但是它是用于指定一种自然语言。eg:Accept-Language:zh-cn.如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。
- Accept-Charset
- Accept-Charset 请求报头域用于指定客户端接受的字符集。eg:Accept-Charset:iso-8859-1, gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
- Cache-Control: no-cache
- Connection: keep-alive
- close
- Authorization
- Authorization 请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为 401(未授权),可以发送一个包含 Authorization 请求报头域的请求,要求服务器对其进行验证。
- Host(发送请求时,该报头域是必需的)
- Host 请求报头域主要用于指定被请求资源的 Internet 主机和端口号,如
Host:www.alvinhtml.cn:80
- Host 请求报头域主要用于指定被请求资源的 Internet 主机和端口号,如
- User-Agent
- 操作系统的名称和版本,浏览器的名称和版本。
- Referer:
http://www.google.com
从哪个链接跳过来的。 - Sec-Fetch-Dest Chrome 自定头,表示请求的发起方式,如果该请求是作为页面直接打开的,比如在地址栏上回车,这个值会是 document,如果是用
<img>
标签发起的图片请求,这个值会是 image,如果用 XHR/fetch 发起的,这个值会是 empty,等等。
响应头
- Location
- Location 响应报头域用于重定向接受者到一个新的位置。Location 响应报头域常用在更换域名的时候。
- Server
- Server 响应报头域包含了服务器用来处理请求的软件信息。与 User-Agent 请求报头域是相对应的。
实体报头
请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文(eg:有无实体正文)和请求所标识的资源的元信息。常用的实体报头:
- Content-Encoding (内容编码)
- Content-Encoding 实体报头域被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得 Content-Type 报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding 这样用于记录文档的压缩方法,eg:Content-Encoding:gzip
- Content-Language
- Content-Language 实体报头域描述了资源所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读者。eg:Content-Language:da
- Content-Length
- Content-Length 实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。
- Content-Type
- Content-Type 实体报头域用语指明发送给接收者的实体正文的媒体类型。
- application/x-www-form-urlencoded
- 浏览器的原生 form 表单
- 提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码
- multipart/form-data
- POST 数据提交的方式
- application/json
- 消息主体是序列化后的 JSON 字符串
- text/xml
- 是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范
- Content-Type: text/html;charset=GB2312
- 消息主体是 html
- application/x-www-form-urlencoded
- Content-Type 实体报头域用语指明发送给接收者的实体正文的媒体类型。
- date: Fri, 29 May 2020 06:11:05 GMT
- connection: close
- Last-Modified
- Last-Modified 实体报头域用于指示资源的最后修改日期和时间。
- Expires
- Expires 实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载,缩短响应时间和降低服务器负载)的页面,我们可以使用 Expires 实体报头域指定页面过期的时间。eg:Expires:Thu,15 Sep 2006 16:23:12 GMT,HTTP1.1 的客户端和缓存必须将其他非法的日期格式(包括 0)看作已经过期。eg:为了让浏览器不要缓存页面,我们也可以利用 Expires 实体报头域,设置为 0,jsp 中程序如下:response.setDateHeader("Expires","0");
- Transfer-Encoding: chunked (传输编码)
- 传输编码方式:分块编码(chunked)
Range 基本介绍
Range 是在 HTTP/1.1 中新增的一个字段,这个特性也是我们使用的迅雷等支持多线程下载以及断点下载的核心机制。
首先客户端会发起一个带有 Range: bytes=0-xxx 的请求,如果服务端支持 Range,则会在响应头中添加 Accept-Ranges: bytes 来表示支持 Range 的请求,之后客户端才可能发起带 Range 的请求。服务端通过请求头中的 Range: bytes=0-xxx 来判断是否是进行 Range 处理,如果这个值存在而且有效,则只发回请求的那部分文件内容,响应的状态码变成 206,表示 Partial Content,并设置 Content-Range。如果无效,则返回 416 状态码,表明 Request Range Not Satisfiable。如果请求头中不带 Range,那么服务端则正常响应,也不会设置 Content-Range 等。
Range 的格式为:Range:(unit=first byte pos)-[last byte pos]