http 是应用层协议,且是无状态的。它时基于 TCP/IP 的通信协议,用于在网络中传递数据,默认端口号 TCP 80.HTTP 规范指定如何构造客户端的请求数据并将起发送到服务器,以及服务器如何响应这些数据。
基本特性
有 3 个基本特性使得 HTTP 成为一个简单且强大的协议:
- HTPP 是无连接的,客户端和服务器仅在当前请求和响应期间是相互知道对方,进一步的请求会建立新的连接,就像客户端和服务器彼此是新的一样
- HTTP 是独立于媒体,与媒体无关的,这意味,只要客户端和服务器都知道如何处理数据内容,任何类型的数据都可以通过 HTTP 发送。因此,客户端和服务器都需要使用适当的
MIME-type
来指定内容类型 - HTTP 是无状态的,如上所述,HTTP 是无连接的,只在当前请求期间,客户端与服务器才能相互感知,之后,就会忘记对方。因此,客户端和服务器都不能在跨 web 页面的不同请求之间保留信息。
HTTP/1.0 为每个请求/响应交换 使用一个新连接,而 HTTP/1.1 一个连接可以用于一个或多个 请求/响应交换
基础架构
HTTP 协议是基于客户端/服务器架构的请求/响应协议。其中 web 浏览器,搜索引擎等充当 HTTP 的客户端,web 服务器充当服务器
Client 客户端
HTTP 客户端以 请求方法
+URL
+协议版本
的形式向服务器发送消息,然后通过 TCP/IP 连接发送一个类似 mime(MIME-like)的消息,其中包含请求修饰符
,客户机信息
,可能的主体内容
。
Server 服务器
HTTP 服务器使用一个状态行(消息协议版本
+ 成功或错误代码
)进行响应,然后是一个类似 mime 消息,其中包含服务器信息
,实体元信息
,可能的实体-主体信息
HTTP-参数
版本
HTTP/1.0
, HTTP/1.1
同一资源标识符(URI)
不区分大小写,一般语法
1 | URI = "http:" "//" host [":" port] [abs_path ["?" query]] |
- 如果
port
为空,则默认 HTTP 端口号 80; - 如果
abs_path
为空,则相对于/
- 除保留字符和有特殊含义的字符之外的字符会被进行编码,等效于
%
+十六进制编码
日期/时间格式
所有 HTTP 日期/时间戳,必须用格林威治时间表示 last-modified: Sat, 11 Apr 2020 02:05:18 GMT
字符集
指定客户端喜欢字符集,多个字符集用逗号分隔;如果未指定,默认为 US-ASCII
内容编码
在通过网络传递内容之前,使用编码算法对内容进行编码,主要用于在不丢失标识的情况下对文档进行压缩或其他转化。内容编码的值是大小写不敏感的,在HTTP/1.1
中,Accept-Encoding
和Content-Encoding
头字段中使用内容编码值
1 | Accept-encoding: gzip |
媒体类型
在Content-Type
和Accept
头字段中使用互联网媒体类型,以便提供开放的,可扩展的数据类型和类型协商。所有的媒体类型的值都在互联网号码分配机构(IANA)
注册,可查看媒体类型最新列表。
MIME 类型对大小写不敏感,其通用结构:type/subtype
独立类型
独立类型表明了对文件的分类
类型 | 说明 | 示例 |
---|---|---|
text |
普通文本,理论上是人可读的 | text/plain ,text/html ,text/css ,text/javascript |
image |
图像,包括 gif 动图 | image/gif ,image/png ,image/jpeg ,image/x-icon |
audio |
音频文件 | audio/midi ,audio/mpeg ,audio/webm ,audio/ogg |
video |
视频文件 | video/webm ,video/ogg |
application | 某种二级制数据 | application/octet-stream ,application/xml ,application/pdf |
复合(Multipart)类型
1 | multipart/form-data |
Multipart 类型表示细分领域的文件类型,是复合文件的一种表现方式。multipart/form-data
用于HTML Forms
和POST
方法;multipart/byteranges
使用状态码 206 Partial Content
来发送整个文件的子集。
HTTP 对不能处理的复合文件使用特殊的方式:将信息 直接传给浏览器(这是可能会建立一个“另存为”窗口,但是不知道如何去显示文件)
语言标签
HTTP 在Accept-Language
和Content-Language
字段使用语言标签,它是由一个主语言和一系列的子语(可能为空)言组成。不允许有空格,且大小写不敏感。
1 | Accept-language: en,zh-CN;q=0.9,zh;q=0.8,la;q=0.7 |
HTTP-header 字段
HTTP 消息头允许客户端和服务器通过请求,响应来传递附加信息。一个请求头由名称(不区分大小写)后跟一个冒号:
,冒号后再跟具体的值(不带换行符)组成。
根据不同上下文,消息头可分为:
General headers
: 同时适用于请求和响应消息,但是不能应用于内容本身。常见的有Date
,Cache-Control
,Connection
Request headers
: 包含更多有关要获取的资源或客户端本身信息的消息头Response headers
: 包含有关响应的补充信息Entity headers
: 包含有关实体主体的更多信息
通用的头字段
Cache-Control
: 被用在请求和响应中,通过指令来实现缓存机制。指令不区分大小写,具有可选参数,多个指令以逗号分隔- 缓存请求指令
- no-cache: 在没有与原始服务器成功验证的情况下,缓存不得使用。即在发送缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)
- no-store: 缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存
- max-age = seconds: 设置缓存存储的最大周期,超过该时间缓存被认为过期
- max-stale [=seconds]: 表示客户端愿意接受超过到期时间的响应。如果给定了时间,它的过期时间不得超过该时间。
- min-fresh= seconds: 表示客户端愿意接受还剩余多少秒过期的缓存
- only-if-cached: 表示客户端直接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。
- 缓存响应指令
- public: 表明响应可以被任何对象(包括 客户端,代理服务器,等待)缓存
- private: 响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存),私有缓存可以缓存响应内容,比如,对应用户的本地浏览器
- must-revalidate: 一旦资源过期,在成功向原始服务器验证之前,缓存不能用该资源响应后续请求
- proxy-revalidate: 代理重新验证指令,与
must-revalidate
作用相同,但它仅适用于共享缓存,被私有缓存忽略
- 缓存请求指令
Connection
: 决定当前事务完成后,是否关闭网络连接;值为”keep-alive”,网络连接是持久的,不会关闭,使得对同一服务器的请求可以继续在该连接上完成。”close”,关闭该网络连接Date
: 报文创建的日期和时间。在 HTTP 协议中,时间都是用格林威治标准时间来表示,而非本地时间。<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
,Date: Tue, 14 Apr 2020 23:40:03 GMT
Via
: 网关和代理必须使用Via
来指示中间协议和接收者。可用来追踪消息转发情况,防止循环请求
请求消息的头字段
Accept
: 请求头用来告知服务器,客户端可处理的内容类型,用 MIME 类型表示。借助内容协商机制,服务器可以从诸多备选项中选择一项进行应用,并使用Content-Type
通知客户端它的选择Accept-Charset
: 用来告知服务器,客户端可以处理的字符集类型。服务器使用Content-Type
应答。Content-Type: text/hml; charset=utf-8
Accept-Encoding
: 用来告知服务器,客户端能够理解的内容编码方式,通常是某种压缩算法。服务器使用Content-Encoding
应答 值indentity
,未经过压缩和修改Accept-Language
: 客户端可理解的自然语言Authorization
: 请求消息头含有服务器 用于验证用户代理身份的凭证,通常会在服务器返回401 Unauthorzied
状态码之后,在后续请求中发送此消息头。Authorization: <type> <credentials>
,Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
,“基本验证(Basic)”,用冒号将用户名和密码进行拼接(username:password),再用 base64 方式编码Cookie
: 其中含有先前由服务器通过Set-Cookie
首部存储到客户端的HTTP cookies
,其值是一系列的名称/值对,之间用分号和空格隔开。Cookie: PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;
Host
: 指明了服务器的域名,以及服务器监听的 TCP 端口号,默认 80.HTTP/1.1
请求缺少 Host 头字段,返回400 Bad Request
状态码If-Match
: 表示这是一个条件请求- 在 GET,HEAD 请求,服务器仅在请求的资源满足此首部的
ETag
值时才会返回资源。 - 对 PUT 请求,只有在满足条件的情况下才可以将资源上传
- 在 GET,HEAD 请求,服务器仅在请求的资源满足此首部的
If-Modified-Since
: 是一个条件式的请求首部,如果在该字段中指定的时间以来,请求的资源未被修改,则返回一个不带消息主体的304 Not Modified
响应。如果资源修改过,则返回200 Ok
.在Last-Modified
响应首部中会带有上次修改的时间。如果没有ETag
匹配,则服务器不能执行该请求方法,返回412 Precondition Failed
If-None-Match
: 是一个条件式请求。当且仅当服务器上没有任何资源的ETag
的值与此首部中列出的相匹配时,才返回200 Ok
.2 个常见应用场景- 采用 GET,HEAD 方法,来更新拥有特定的 ETag 属性值的缓存
- 采用其他方法,尤其是 PUT,将
If-None-Match
的值设置为*
,(可以代表任意资源),来检查拥有相同 ID 的资源是否存在,如果存在,则验证失败,服务器返回412 Precondition Failed(前置条件失败)
User-Agent
: 包含有关发送请求的用户代理的信息,软件类型、操作系统、开发商、版本号等。要避免进行用户代理检测,因为为不同浏览器提供不同的网页或服务通常是一个坏主意,- 功能检测,弄清楚浏览器中某种特定功能是否可用,如果不可用,找应变策略
- 渐进增强,自底向上的方法,从一个简单的层次开始,在一系列连续的层次中通过使用更多的功能来逐步提升站点的能力
- 优雅降级,自顶向下的方式,先使用所有想要的功能,然后改进使其能在更老旧的浏览器上工作,与渐进增强的方式相比,这种方法更困难,效率更低
响应消息的头字段
ETag
: 资源是特定版本的标识符。如果给定 URL 中的资源更改,则一定要生成新的 ETag 值。常见的应用场景- 避免“空中碰撞”,借助
ETag
和If-Match
头部,可以检测到“空中碰撞”的编辑冲突,POST 请求将包含有 ETag 值的If-Match
头来检查是否为最新版本,如果不匹配,则意味已经被编辑,返回412
前置条件失败错误 - 缓存未更改的资源,在请求时发送值为 ETag 的
If-None-Match
字段,服务器与其当前版本资源的 ETag 进行比较,如果两个值匹配,即资源未更改,返回304
- 避免“空中碰撞”,借助
Location
: 指定了需要将页面重定向到的地址,一般在状态码为3XX
的响应中才会有意义Retry-After
: 表示客户端需要等待多长时间后才能继续发送请求。经常同503 Service Unavailable, 当前服务不存在
响应一起使用,表示服务器下线的预期时长,可用于对于计划内宕机时间的处理Server
: 处理请求的源头服务器所用的软件相关信息Set-Cookie
: 被用来由服务器端向客户端发送 cookie,即设置此网址的 cookieSet-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
实体消息(Entity Headers)的头字段
Allow
: 资源所支持的 HTTP 方法的合集。若服务器返回状态码405 Method Not Allowed
,则该首部字段需要同时返回给客户端Content-Ecoding
: 表示消息主体进行了何种方式的内容编码(压缩)。如果源服务器不接受请求信息中的内容编码,服务器返回415 Unsupported Media Type
Content-length
: 用来指明发送给接收方的消息主体的大小Content-Type
: 消息主体的媒体类型Expires
: 响应过期是日期/时间。 0,代表过去时间,即资源已经过期。如果在Cache-Control
响应头设置了max-age
或s-max-age
指令,则Expires
会被忽略Last-Modified
: 源服务器中资源最后修改的日期/时间
HTTP-消息
HTTP 是基于客户机-服务器体系结构模型,无状态请求/响应协议,通过可靠的 TCP/IP 来交换消息。
HTTP 利用 URI 来标识给定的资源并建立连接,一旦建立了连接,HTTP 消息将以 MIME 类型传递。这些消息包含从客户机到服务器的请求和从服务器到客户机的响应。
HTTP 请求和响应使用 RFC 822 的通用消息格式来传输所需的数据,此通用消息格式由四个部分组成:起始行
,头部
,空行
,消息正文
HTTP-请求
http-请求方法
HTTP 定义了一组请求方法,以表明要对给定资源执行的操作。
GET:使用给定 URL 从服务器获取数据,且不会对数据产生其他影响
HEAD: 请求资源的头部信息, 且与 GET 方法请求时返回的一致,不包含响应正文。使用场景,在要下载一个大文件前先获取文件大小后再决定是否要下载,以节约带宽资源
POST: 发送数据给服务器,请求主体的类型由
Content-Type
首部指定
PUT 方法是幂等(idempotent,指同样的请求被执行一次或连续执行多次的效果是一样的)的,即连续调用一次或多次的效果相同(无副作用),但 POST 不是,连续调用可能会带来额外的影响,比如多次提交订单
POST 请求通常通过 HTML 表单发送,并返回服务器的修改结果,在这种情况下,content-type
是通过在<form>
元素中设置正确的enctype
属性,或在<input>
,<button>
元素中设置formenctype
属性来选择的,如application/x-www-form-urlencoded
multipart/form-data``text/plain
PUT: 使用请求中的内容创建或替换目标资源
- 如果目标资源不存在,并且 PUT 方法成功创建了一份,则服务器必须返回
201 Created
来通知客户端资源已创建 - 如果目标资源已经存在,且成功进行了更新,则服务器必须返回
200 OK
或204 No Content
来表示请求成功完成
- 如果目标资源不存在,并且 PUT 方法成功创建了一份,则服务器必须返回
PATCH:用于对资源进行部分修改,不同与 PUT 对资源进行整体覆盖。PATCH 方法是非幂等的,如何理解?
PATCH 请求中的实体保存的是修改资源的指令,该指令指导服务器来对资源做出修改,例如,对于服务器的 A 对象有个属性 b 为 1,如果要修改为 3,PUT 请求直接将改过的 b 属性的整个新对象发送给服务器查找并替换;而 PATCH 请求是在实体中包含指令:将 A 对象中的 b 属性的值+2,所有如果该请求被执行多次,b 属性就不是 3 了。DELETE: 删除指定的资源,是幂等的。如果成功执行,会有以下几种状态码:
202 Accepted
, 表示请求的操作可能会成功执行,但是尚未开始执行204 No Content
, 操作已执行,但无进一步的相关信息200 OK
,操作已执行,并且响应中提供了相关状态的描述信息
OPTIONS: 用于获取目的资源所支持的通信选项。客户端可对特性 URL 使用 OPTIONS 方法,也可对整站(RUL 设置为
*
)使用该方法检测服务器所支持的请求方法,响应报文会包含
Allow
首部字段,该字段的值表明了服务器支持的所有 HTTP 方法1
$ curl -X OPTIONS http://example.org -i
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Tue, 14 Apr 2020 03:21:01 GMT
Expires: Tue, 21 Apr 2020 03:21:01 GMT
Server: EOS (vny/0454)
Content-Length: 0
```
- 在中的预检请求,在CORS中,使用 OPTIONS 方法发起一个预检请求,以检查请求是否被服务器接收。
HTTP-响应
- 状态行:
协议版本 状态码 状态文本
,HTTP/1.1 404 Not Found
- Headers: 遵循和任何其它 header 相同的结构
- Body: 不是所需响应都有 body
HTTP-状态码
HTTP 状态码可分为 5 种类型
分类 | 描述 |
---|---|
1XX | 信息性状态码,服务器收到请求,需要请求者继续执行操作 |
2XX | 成功状态码,操作被成功接收并处理 |
3XX | 重定向,需要进一步的操作以完成请求 |
4XX | 客户端错误,请求包含语法错误 |
5XX | 服务器错误,服务器在处理请求的过程中发生了错误 |
常用状态码
200 OK
: 请求已经成功,默认情况下状态码为 200 的响应可以被缓存。201 Created
: 请求已经被成功处理,并且创建了新的资源,常作为POST
请求的返回值204 No Content
: 请求成功,但没有资源返回给客户端。常用于在PUT
请求进行资源更新时,如果创建了资源,则返回201 Created
206 Partial Content
: 对资源某一部分的请求,响应报文中包含由 Content-Range 指定范围的实体内容301 Moved Permanently
: 永久重定向,请求的资源已经被移动到由Location
头部指定的 URL 上,因为有些用户代理在进行重定向时会改变请求 method 和 body,用308 Permanent Redirect
,它不会。302 Found
,请求的资源被暂时的移动到由Location
头部指定的 URL 上。部分用户代理在重定向时无法保证请求 method 和 body 不变,推荐使用307 Temporary Redirect
.303 See Other
: 通常作为PUT
和POST
操作的返回结果,它表示重定向的链接指向的不是新上传的资源,而是另一个页面,比如信息确认页面或上传进度页面,且方法总是使用GET
304 Not Modified
: 未改变,说明无需再次传输请求的内容,可以使用缓存的内容400 Bad Request
: 表示服务器无法理解的请求,请求报文中可能存在语法错误401 Unauthorized
: 缺少目标资源要求的身份验证凭证,这个状态码会和www-Authenticate
头部一起返回,其中包含有如何进行验证的消息403 Forbidden
: 指定是服务器有能力处理请求,但是拒绝授权(没权限,未授权 IP 等)404 Not Found
: 服务器无法找到请求的资源,路径错误405 Method Not Allowed
: 表明服务器禁止使用当前的 HTTP 方法的请求500 Internal Server Error
: 服务器遇到意外的情况,并阻止其执行请求。通用的“万能”的错误响应502 Bad Gateway
: 表示最为网关或代理角色的服务器,从上游服务器中接收到的响应式无效的。503 Service Unavailable
: 表示服务器尚未处于可接受请求的状态。原因可能是停机维护或者已超载。在必要可行的情况下,应该在Retry-After
头部包含服务恢复的预期时间