HTTP的作用
HTTP 协议和 TCP/IP 协议族内的其他众多的协议相同,用于客户端和服务器之间的通信。
在两台计算机之间使用 HTTP 协议通信时,在一条通信线路上必定有
一端是客户端,另一端则是服务器端。
通过请求和响应的交换达成通信
请求报文
GET /index.htm HTTP/1.1
Host: hackr.jp
起始行开头的GET表示请求访问服务器的类型,称为方法(method)。随后的字符串 /index.htm 指明了请求访问的资源对象,也叫做请求 URI(request-URI)。最后的 HTTP/1.1,即 HTTP 的版本
号,用来提示客户端使用的 HTTP 协议功能。
图:请求报文的构成
响应报文
HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 06:50:15 GMT
Content-Length: 362
Content-Type: text/html
<html>
……
在起始行开头的 HTTP/1.1 表示服务器对应的 HTTP 版本。
紧挨着的 200 OK 表示请求的处理结果的状态码(status code)和原因短语(reason-phrase)。下一行显示了创建响应的日期时间,是**首部字段(header field)**内的一个属性。
接着以一空行分隔,之后的内容称为资源实体的主体(entity body)。
图:响应报文的构成
HTTP 是不保存状态的协议
HTTP 是**一种不保存状态,即无状态(stateless)协议。**HTTP 协议自身不对请求和响应之间的通信状态进行保存。也就是说在 HTTP 这个级别,协议对于发送过的请求或响应都不做持久化处理。
请求 URI 定位资源
指定请求 URI 的方式有很多。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fpy47kl7-1579691459393)(https://i.loli.net/2020/01/22/8RhQNBLDvtXak4C.png)]
图:以 http://hackr.jp/index.htm 作为请求的例子
OPTIONS * HTTP/1.1
除此之外,如果不是访问特定资源而是对服务器本身发起请求,可以用一个 * 来代替请求 URI。
HTTP 方法
GET :获取资源
GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。
请求 | GET /index.html HTTP/1.1 Host: www.hackr.jp If-Modified-Since: Thu, 12 Jul 2012 07:30:00 GMT |
---|---|
响应 | 仅返回2012年7 月12日7 点30分以后更新过的index.html页面资源。如果未 有内容更新,则以状态码304 Not Modified作为响应返回 |
POST:传输实体主体
虽说 POST 的功能与 GET 很相似,但POST 的主要目的并不是获取响应的主体内容。
请求 | POST /submit.cgi HTTP/1.1 Host: www.hackr.jp Content-Length: 1560(1560字节的数据) |
---|---|
响应 | 返回 submit.cgi 接收数据的处理结果 |
PUT:传输文件
PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。
请求 | PUT /example.html HTTP/1.1 Host: www.hackr.jp Content-Type: text/html Content-Length: 1560(1560 字节的数据) |
---|---|
响应 | 响应返回状态码 204 No Content(比如 :该 html 已存在于服务器上) |
HEAD:获得报文首部
HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认URI 的有效性及资源更新的日期时间等。
请求 | HEAD /index.html HTTP/1.1 Host: www.hackr.jp |
---|---|
响应 | 返回index.html有关的响应首部 |
DELETE:删除文件
DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。
请求 | DELETE /example.html HTTP/1.1 Host: www.hackr.jp |
---|---|
响应 | 响应返回状态码 204 No Content(比如 :该 html 已从该服务器上删除) |
OPTIONS:询问支持的方法
OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。
请求 | OPTIONS * HTTP/1.1 Host: www.hackr.jp |
---|---|
响应 | HTTP/1.1 200 OK Allow: GET, POST, HEAD, OPTIONS (返回服务器支持的方法) |
TRACE:追踪路径
发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器端就将该数字减 1,当数值刚好减到 0 时,就停止继续传输,最后接收到请求的服务器端则返回状态码 200 OK 的响应。
请求 | TRACE / HTTP/1.1 Host: hackr.jp Max-Forwards: 2 |
---|---|
响应 | HTTP/1.1 200 OK Content-Type: message/http Content-Length: 1024 TRACE / HTTP/1.1 Host: hackr.jp Max-Forwards: 2(返回响应包含请求内容) |
CONNECT:要求用隧道协议连接代理
CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
请求 | CONNECT proxy.hackr.jp:8080 HTTP/1.1 Host: proxy.hackr.jp |
---|---|
响应 | HTTP/1.1 200 OK(之后进入网络隧道) |
持久连接
持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或HTTP connection reuse)的方法。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。
在 HTTP/1.1 中,所有的连接默认都是持久连接
管线化
不用等待响应亦可直接发送下一个请求。
使用 Cookie 的状态管理
Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。
服务器端发现客户端发送过来的 Cookie 后,会去**检查究竟是从哪一个客户端发来的连接请求,**然后对比服务器上的记录,最后得到之前的状态信息。
1. 请求报文(没有 Cookie 信息的状态)
GET /reader/ HTTP/1.1
Host: hackr.jp
*首部字段内没有Cookie的相关信息
2. 响应报文(服务器端生成 Cookie 信息)
HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Server: Apache
<Set-Cookie: sid=1342077140226724; path=/; expires=Wed,
10-Oct-12 07:12:20 GMT>
Content-Type: text/plain; charset=UTF-8
3. 请求报文(自动发送保存着的 Cookie 信息)
GET /image/ HTTP/1.1
Host: hackr.jp
Cookie: sid=1342077140226724
HTTP 报文结构
请求报文及响应报文的结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传!(img-OJJu8Gxy-1579691459396)(https://i.loli.net/2020/01/22/QON3kKBoJzaeHXS.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1VtZbkcY-1579691459399)(https://i.loli.net/2020/01/22/6XYeSlonrwdAcID.png)]
请求行
包含用于请求的方法,请求 URI 和 HTTP 版本。
状态行
包含表明响应结果的状态码,原因短语和 HTTP 版本。
首部字段
包含表示请求和响应的各种条件和属性的各类首部。
一般有 4 种首部,分别是:通用首部、请求首部、响应首部和实体首部。
编码提升传输速率
通过在传输时编码,能有效地处理大量的访问请求。
报文主体和实体主体的差异
通常,报文主体等于实体主体。只有当传输中进行编码操作时,实体主体的内容发生变化,才导致它和报文主体产生差异。
压缩传输的内容编码
内容编码指明应用在实体内容上的编码格式,并保持实体信息原样压缩。内容编码后的实体由客户端接收并负责解码。
常用的内容编码有以下几种。
- gzip(GNU zip)
- compress(UNIX 系统的标准压缩)
- deflate(zlib)
- identity(不进行编码)
分割发送的分块传输编码
在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。
分块传输编码会将实体主体分成多个部分(块)。每一块都会用**十六进制来标记块的大小,而实体主体的最后一块会使用“0(CR+LF)”**来标记。
发送多种数据的多部分对象集合
HTTP 协议中也采纳了多部分对象集合,发送的一份报文主体内**可含有多类型实体。**通常是在图片或文本文件等上传时使用。
多部分对象集合包含的对象如下。
- multipart/form-data
在 Web 表单文件上传时使用。
- multipart/byteranges
状态码 206(Partial Content,部分内容)响应报文包含了多个范围的内容时使用。
- multipart/form-data
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="field1"
Joe Blow
--AaB03x
Content-Disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
...(file1.txt的数据)...
--AaB03x--
- multipart/byteranges
HTTP/1.1 206 Partial Content
Date: Fri, 13 Jul 2012 02:45:26 GMT
Last-Modified: Fri, 31 Aug 2007 02:02:20 GMT
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 500-999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 7000-7999/8000
...(范围指定的数据)...
--THIS_STRING_SEPARATES--
使用 boundary 字符串来划分多部分对象集合指明的各类实体。
在boundary 字符串指定的各个实体的起始行之前插入“–”标记(例如:–AaB03x、–THIS_STRING_SEPARATES)
而在多部分对象集合对应的字符串的最后插入“–”标记(例如:–AaB03x–、--
THIS_STRING_SEPARATES–)作为结束。
获取部分内容的范围请求
对一份 10 000 字节大小的资源,如果使用范围请求,可以只请求5001~10 000 字节内的资源。
执行范围请求时,会用到首部字段 Range 来指定资源的 byte 范围。
byte 范围的指定形式如下。
-
5001~10 000 字节
Range: bytes=5001-10000
-
从 5001 字节之后全部的
Range: bytes=5001-
-
从一开始到 3000 字节和 5000~7000 字节的多重范围
Range: bytes=-3000, 5000-7000
针对范围请求,响应会返回状态码为 206 Partial Content 的响应报文。另外,对于多重范围的范围请求,响应会在首部字段 Content-Type 标明 multipart/byteranges 后返回响应报文。
如果服务器端无法响应范围请求,则会返回状态码 200 OK 和完整的实体内容。
内容协商返回最合适的内容
当浏览器的默认语言为英语或中文,访问相同 URI 的 Web 页面时,则会显示对应的英语版或中文版的 Web 页面。这样的机制称为内容协商(Content Negotiation)。