一、URL-俗称“网址”
HTTP 使用 URL(Uniform Resource Locator,统一资源定位符)来定位资源,它是 URI(Uniform Resource Identifier,统一资源标识符)的子集,URL 在 URI 的基础上增加了定位能力
URI 除了包含 URL,还包含 URN(Uniform Resource Name,统一资源名称),它只是用来定义一个资源的名称,并不具备定位该资源的能力
urlencode、urldecode
像 : / ? 等这样的字符, 已经被 url 当做特殊含义理解了,因此这些字符不能随意出现,否则需要对其进行转义
例如,‘+’ 经过 urlencode 被转义成了 “%2B”
而 urldecode 就是 urlencode 的逆过程
二、HTTP 报文
1、请求报文
- 第一行是请求行,包含用于请求的方法、URL 和 HTTP 版本
- 接下来的多行都是首部(Header),包含请求首部、通用首部、实体首部以及 HTTP 的 RFC 中未定义的其他首部(Cookie 等)
- 一个空行用来分隔首部和主体(Body),Body 允许为空字符串,如果 Body 存在, 则 Header 中会有一个 Content-Length 属性用于标识 Body 长度
2、响应报文
- 第一行是状态行,包含HTTP 版本、表明响应结果的状态码和状态码描述
- 接下来的多行都是首部(Header),包含响应首部、通用首部、实体首部以及 HTTP 的 RFC 中未定义的其他首部(Cookie 等)
- 一个空行用来分隔首部和主体(Body),Body 允许为空字符串,如果 Body 存在, 则 Header 中会有一个 Content-Length 属性用于标识 Body 长度
此时可能会有疑问,示例 Header 中也没有 Content-Length 属性啊,但请注意,服务器返回了一个 html 页面,而且 Header 中的 Transfer-Encoding(HTTP/1.1) 属性值是 chunked
三、HTTP 请求方法
方法 | 说明 | 支持的 HTTP 版本 | 注意 |
---|---|---|---|
GET | 获取资源 | 1.0、1.1 | 常用方法 |
POST | 传输主体 | 1.0、1.1 | 常用方法 |
PUT | 传输文件 | 1.0、1.1 | 鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件,存在安全问题,因此一般的 Web 网站不使用 |
HEAD | 获取报文首部 | 1.0、1.1 | |
DELETE | 删除文件 | 1.0、1.1 | 鉴于 HTTP/1.1 的 DELETE 方法自身也不带验证机制,所以一般的 Web 网站也不使用 |
OPTIONS | 访问支持的方法 | 1.1 | |
TRACE | 追踪路径 | 1.1 | TRACE 方法不怎么常用,而且还容易受到 XST(Cross-Site Tracing,跨站追踪) 攻击 |
CONNECT | 要求用隧道协议连接代理 | 1.1 | 使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输 |
LINK | 建议和资源之间的联系 | 1.0 | |
UNLIKE | 断开连接关系 | 1.0 |
四、HTTP 状态码
类别 | 原因短语 | |
---|---|---|
1xx | Informational(信息性状态码) | 接收的请求正在处理 |
2xx | Success(成功状态码) | 请求正常处理完毕 |
3xx | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4xx | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5xx | Server Error(服务器错误状态码) | 服务器处理请求出错 |
常见的状态码如下:
-
200:OK,从客户端发来的请求在服务器端被正常处理了,在响应报文内,随状态码一起返回的信息会因方法的不同而发生改变,比如,使用 GET 方法时,对应请求资源的实体会作为响应返回,而使用 HEAD 方法时,在响应中只返回首部,不会返回主体部分
-
204:No Content,请求已成功处理,但在返回的响应报文中不包含主体部分,一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用,比如,当从浏览器发出请求处理后,返回 204 响应,那么浏览器显示的页面不发生更新
-
206:Partial Content,客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求,响应报文中包含由 Content-Range 指定范围的实体内容
-
301:Moved Permanently,永久性重定向
-
302:Found,临时性重定向
-
303:See Other,和 302 有着相同的功能,但 303 明确表示客户端应当采用 GET 方法获取资源
301、302 标准是禁止将 POST 方法改变成 GET 方法的,但当 301、302、303 响应状态码返回时,几乎所有的浏览器都会把 POST 改成 GET,并删除请求报文内的主体,之后请求会自动再次发送
-
304:Not Modified,客户端发送附带条件的请求(附带条件的请求是指采用 GET 方法的请求报文中包含 If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since 中任一首部)时,服务器端允许请求访问资源,但未满足条件的情况。304 状态码返回时,不包含任何响应的主体部分。304 虽然呗划分在 3xx 类别中,但是和重定向没有关系
-
307:Temporary Redirect,临时重定向,与 302 有着相同的含义,但 307 会遵守浏览器标准,不会从 POST 变成
GET,但是,对于处理响应时的行为,每种浏览器有可能出现不同的情况 -
400:Bad Request,请求报文中存在语法错误
-
401:Unauthorized,发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息,如果之前已进行过一次请求,则表示用户认证失败
-
403:Forbidden,请求被拒绝,服务器端没有必要给出拒绝的详细理由,但如果想作说明的话,可以在主体部分对原因进行描述,这样就能让用户看到了
-
404:Not Found,服务器上无法找到请求的资源,除此之外,也可以在服务器端拒绝请求且不想说明理由时使用
-
500:Internal Server Error,服务器端在执行请求时发生了错误
-
503:Service Unavailable,服务器暂时处于超负载或正在进行停机维护,现在无法处理请求
五、HTTP 首部
1、首部
常见的首部见下:
- Content-Type:数据类型(text/html 等)
- Content-Length:Body 长度
- Host:客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上
- User-Agent:声明用户的操作系统和浏览器版本信息
- referer:当前页面是从哪个页面跳转过来的
- location:搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问
- Cookie:用于在客户端存储少量信息. 通常用于实现会话(session)功能
1.1、HTTP/1.1 首部
通用首部
首部名 | 说明 |
---|---|
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 | 对请求中 URL 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
响应首部
首部名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推送资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定 URL |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP 服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体首部
首部名 | 说明 |
---|---|
Allow | 资源可支持的 HTTP 方法 |
Content-Encoding | 主体适用的编码方式 |
Content-Language | 主体的自然语言 |
Content-Length | 主体的大小(单位:字节) |
Content-Location | 替代对应资源的 URL |
Content-MD5 | 主体的报文摘要 |
Content-Range | 主体的位置范围 |
Content-Type | 主体的媒体类型 |
Expires | 主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
1.2、非 HTTP/1.1 的其他首部
在 HTTP/1.1 协议通信交互中使用到的首部,不限于 RFC2616 中定义的上述 47 种,还有一些非正式的首部,如 Cookie、Set-Cookie 和 Content-Dispostion 等都定义在 RFC4229 HTTP Header Field Registrations,它们的使用频率也很高
1.3、压缩传输的内容编码
内容编码指将主体压缩,客户端负责解码,其中,常见的内容编码如下:
- gzip:GNU zip
- compress:UNIX 系统的标准压缩
- default:zlib
- identity:不进行压缩
1.4、分割发送的分块传输编码
分块传输编码(Chunked Transfer Encoding)指将主体分块,每一块都会用十六进制来标记块的大小,而最后一块会使用 0(CR+LF) 来标记,客户端接收后进行解码,让浏览器逐步显示页面
1.5、发送多种数据的多部分对象集合
一份报文主体内可含有多类型主体,另,多部分对象集合可以嵌套使用,其中,包含的对象如下:
- multipart/from-data
在 Web 表单文件上传时使用
- multipart/byteranges
状态码 206 响应报文包含了多个范围的内容时使用
1.6、获取部分内容的范围请求
1.7、内容协商返回最合适的内容
2、长短连接
HTTP 协议的初始版本中,每进行一次 HTTP 通信就要断开一次 TCP 连接
以当年的通信情况来说,因为都是些容量很小的文本传输,所以即使这样也没有多大问题,可随着 HTTP 的普及,文档中包含大量图片的情况多了起来,比如,使用浏览器浏览一个包含多张图片的 HTML 页面时,在发送请求访问 HTML 页面资源的同时,也会请求该页面里包含的其他资源,因此,每次的请求都会造成无谓的 TCP 连接建立和断开,增加通信量的开销
为了解决上述 TCP 连接的问题,想出了持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或 HTTP connection reuse)的方法,持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态
持久连接的好处在于减少了 TCL 连接的重复创建和断开所造成的额外开销,减轻了服务器端的负载,另外,减少开销的那部分时间,使 HTTP 请求和响应能够更早地结束,这样 Web 页面的显示速度也就相应提高了
HTTP/1.1,默认长连接,如果想断开连接,需要由客户端或服务器端任意一端使用 Connection: close 明确提出断开连接
HTTP/1.1 以前,默认短连接,如果想用长连接,需要指定 Connection: Keep-Alive
3、管线化
持久连接使得多数请求以管线化(pipelining)方式发送成为可能,从前发送请求后需等待并收到响应,才能发送下一个请求,管线化技术出现后,不用等待响应亦可直接发送下一个请求,这样就能够做到同时并行发送多个请求,而不需要一个接一个地等待响应了
比如,当请求一个包含 10 张图片的 HTML Web 页面,与挨个连接相比,用持久连接可以让请求更快结束,而管线化技术则比持久连接还要快,请求数越多,时间差就越明显
4、Cookie
HTTP 是一种不保存状态,即无状态(stateless)协议,HTTP 协议自身不对请求和响应之间的通信状态进行保存,也就是说在 HTTP 这个级别,协议对于发送过的请求或响应都不做持久化处理
使用 HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生,协议本身并不保留之前一切的请求或响应报文的信息,这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的,可是,随着 Web 的不断发展,因无状态而导致业务处理变得棘手的情况增多了,比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态,针对这个实例,网站为了能够掌握是谁送出的请求,需要保存用户的状态,HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术
Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态,Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-cookie 的首部字段信息,通知客户端保存 Cookie,当下次客户端再往服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去,服务端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息
上图展示了发生 Cookie 交互的场景,HTTP 请求报文和响应报文的内容如下: