HTTP 状态返回码
HTTP 状态返回码用来表示 HTTP 请求是否成功完成。响应被分为 5 种类型:
- 消息型响应 (1xx)
- 成功响应 (2xx)
- 重定向 (3xx)
- 客户端错误 (4xx)
- 服务器错误 (5xx)
HTTP 首部字段 (Headers)
HTTP 消息首部被用来描述资源信息,或者用于描述客户端和服务器的行为。HTTP 消息头允许客户端和服务器通过 request 和 response 传递附加信息。一个请求头由名称(不区分大小写)后跟一个冒号 :,冒号后跟具体的值(不带换行符)组成。该值前面的引导空白会被忽略。
原始定义在 RFC 4229,也可以在 IANA registry 找到。IANA 同时也维护着一份 registry of proposed new HTTP message headers。自定义的专有首部可以加上 X-
前缀。
根据不同上下文分类
根据不同上下文,可将消息头分为:
- 一般头: 同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。
- 请求头: 包含更多有关要获取的资源或客户端本身信息的消息头。
- 响应头: 包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。
- 实体头: 包含有关实体主体的更多信息,比如主体长度( Content-Length ) 或其 MIME类型。
根据代理对其的处理方式分类
端到端消息头
这类消息头必须被传输到最终的消息接收者,也即,请求的服务器或响应的客户端。中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
逐跳消息头
这类消息头仅对单次传输连接有意义,不能通过代理或缓存进行重新转发。这些消息头包括 Connection
, Keep-Alive
, Proxy-Authenticate
, Proxy-Authorization
, TE
, Trailer
, Transfer-Encoding
及 Upgrade
。注意,只能使用 Connection
来设置逐跳一般头。
常用
- 缓存相关
a.ETag
是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。
如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。
ETag
属性之间的比较采用的是弱比较算法,即两个文件除了每个比特都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。
b.If-None-Match
是一个条件式请求首部。对于 GET 和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的相匹配的时候,服务器端会才返回所请求的资源,响应码为 200 。
对于其他方法来说,当且仅当最终确认没有已存在的资源的 ETag 属性值与这个首部中所列出的相匹配的时候,才会对请求进行相应的处理。
c.If-Modified-Since
是一个条件式请求首部,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 响应,而在 Last-Modified
首部中会带有上次修改时间。
不同于If-Unmodified-Since
, If-Modified-Since
只可以用在 GET 或 HEAD 请求中。当与 If-None-Match
一同出现时,它(If-Modified-Since)会被忽略掉,除非服务器不支持 If-None-Match
。
最常见的应用场景是来更新没有特定 ETag 标签的缓存实体。
d.Cache-Control
通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。
e.Pragma
在 HTTP/1.0 中规定的通用首部,这个首部的效果依赖于不同的实现,所以在“请求-响应”链中可能会有不同的效果。它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器,那时候 HTTP/1.1 协议中的 Cache-Control 还没有出来。
f.Last-Modified
是一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。
由于精确度比 ETag 要低,所以这是一个备用机制。
包含有 If-Modified-Since
或 If-Unmodified-Since
首部的条件请求会使用这个字段。
f.Expires
包含日期/时间, 即在此时候之后,响应过期。
无效的日期,比如 0, 代表着过去的日期,即该资源已经过期。
如果在Cache-Control
响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires
头会被忽略。
2.安全相关
a.Strict-Transport-Security
HSTS是一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP。
b.Content-Security-Policy
内容安全策略(CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。
c.Authorization
验证用户代理身份的凭证,通常会在服务器返回401 Unauthorized
状态码以及WWW-Authenticate
消息头之后在后续请求中发送此消息头。
3.资源相关
a.Content-Type
用于指示资源的MIME
类型media type
。
ⅰ. text/plain ⅱ. application/json {"a":1} ⅲ. application/x-www-form-urlencoded a=1&b=2 ⅳ. multipart/form-data POST /foo HTTP/1.1 Content-Length: 68137 Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575 ---------------------------974767299852498929531610575 Content-Disposition: form-data; name="description" some text ---------------------------974767299852498929531610575 Content-Disposition: form-data; name="myFile"; filename="foo.txt" Content-Type: text/plain (content of the uploaded file foo.txt) ---------------------------974767299852498929531610575
HTTP 首部字段详解
Cache-Control
控制缓存的行为,多个指令之间通过逗号分隔,如Cache-Control: private, max-age=0, no-cache
。
请求指令:
no-cache
,防止接收过期的资源,指示代理服务器(缓存服务器)每次都向源服务器确认资源的有效期。
no-store
, 不缓存该请求的任一部分,暗示请求中包含机密信息。
max-age=[秒]
, 参数值必须,如果缓存资源的时长比该值小则接收缓存的资源,http/1.1
版本的服务器会优先处理max-age
而忽略Expires
,http/1.0 版本服务器则相反。
max-stale(=[秒])
,即使缓存资源已过期,只要在指定时间内则接收响应资源,不指定参数值的话表示不论过了多久都接收响应。
min-fresh=[秒]
,参数值必须,指定服务器返回还未过指定时间的缓存资源。
no-transform
,缓存不能改变主体的媒体类型,防止代理压缩图片等操作。
only-if-cached
, 只请求缓存服务器上的缓存资源,不对缓存资源有效期确认,如果缓存服务器的本地缓存无响应则返回状态码504 Gateway Timeout
。
响应指令:
private
, 指示代理服务器(缓存服务器)只对特定用户提供资源缓存服务。
public
, 所有用户都可以使用缓存。
no-cache(=[value])
, 参数值可选,当指定参数值后指示缓存服务器不再对资源进行缓存,如Cache-Control: no-cache=Location
。
no-store
, 不缓存该响应的任一部分,暗示响应中包含机密信息。
no-transform
, 缓存不能改变主体的媒体类型,防止代理压缩图片等操作。
must-revalidate
, 指示代理服务器在返回响应的缓存资源前向源服务器验证该缓存目前是否有效,如果代理无法连接源服务器的话会返回504 Gateway Timeout
状态码,使用该指令会忽略请求的max-stale
指令。
proxy-revalidate
,指示代理服务器对缓存资源的有效性进行确认。
max-age=[秒]
, 参数值必须,指示缓存服务器在该时间内不必再向源服务器确认缓存资源的有效性。
s-maxage=[秒]
, 参数值必须,与max-age
功能相同,不同的是该指令只适用于供多位用户使用的公共缓存服务器,使用该指令后会忽略对Expires
首部字段及max-age
指令的处理。
另外,可以使用自定义的指令,但这种扩展的指令仅对能理解它的代理服务器有意义。如下的community
指令,Cache-Control
本身没有这个指令,如果缓存服务器不能理解这个指令,则会忽略它:Cache-Control: private, community="UCI"
Connection
管理持久连接和控制不再转发的首部字段。如当服务器想明确断开连接的时候发送 Connection: close
,在http/1.1之前版本协议上使用持久连接的话客户端发送 Connection: Keep-Alive
(服务端会返回包含Connection和Keep-Alive首部字段的响应)。Connection: Upgrade
则是指示不再转发Upgrade首部。
Date
表明创建 http 报文的日期时间,如 date: Tue, 27 Aug 2019 07:25:02 GMT
。
Pragma
http/1.1
之前版本的遗留字段,只用在客户端发送的请求中,要求所有的中间服务器不返回缓存的资源:Pragma: no-cache
。
如果所有的中间服务器都使用 http/1.1 版本的话则应直接使用 Cache-Control: no-cache
。
Trailer
指示在报文主体之后记录了那些首部字段,Trailer 用在 http/1.1 响应首部中允许发送方在分块发送的消息后面添加额外的元信息,如:
Transfer-Encoding
设置传输报文主体时的编码方式为分块编码传输:Transfer-Encoding: chunked
。
默认情况下,HTTP 的响应消息体是作为整包发送到客户端的,用头Content-Length
来表示消息体的长度, 这个长度对客户端非常重要,因为对于持久连接TCP并不会在请求完立马结束,而是可以发送多次请求/响应,客户端需要知道哪个位置才是响应消息的结束,以及后续响应的开始,因此Content-Length显得尤为重要,服务端必须精确地告诉客户端消息体的长度是多少。
如果Content-Length
比实际返回的长度短,那么就会造成内容截断。
如果比实体内容长,客户端就一直处于pendding
状态,直到所有的消息体都返回了请求才结束。
分块编码传输是另一种解决方案:它把数据分解成一系列数据块,并以多个块发送给客户端,服务器发送数据时不再需要预先告诉客户端发送内容的总大小,只需在响应头里面添加Transfer-Encoding: chunked
,以此来告诉浏览器使用的是分块传输编码,这样就不需要Content-Length
。
这就是分块传输编码Transfer-Encoding
的作用。
HTTP 1.1引入分块传输编码提供了以下几点好处:
- HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久连接。通常,持久链接需要服务器在开始发送消息体前发送
Content-Length
消息头字段,但是对于动态生成的内容来说,在内容创建完之前是不可知的。(动态内容,content-length无法预知)
- 分块传输编码允许服务器在最后发送消息头字段。对于那些头字段值在内容被生成之前无法知道的情形非常重要,例如消息的内容要使用散列进行签名,散列的结果通过HTTP消息头字段进行传输。没有分块传输编码时,服务器必须缓冲内容直到完成后计算头字段的值并在发送内容前发送这些头字段的值。
- HTTP服务器有时使用压缩 (gzip或deflate)以缩短传输花费的时间。分块传输编码可以用来分隔压缩对象的多个部分。在这种情况下,块不是分别压缩的,而是整个负载进行压缩,压缩的输出使用本文描述的方案进行分块传输。在压缩的情形中,分块编码有利于一边进行压缩一边发送数据,而不是先完成压缩过程以得知压缩后数据的大小。(gzip压缩,压缩与传输同时进行)
Upgrade
检测能否使用更高版本的协议进行通信,因为Upgrade
仅限于客户端和邻接服务器之间,所以还需要额外指定Connection: Upgrade
WebSocket
是建立在Http
基础上的协议,因此,连接的发送方仍是客户端,确立WebSocket
通信连接后服务端可以不必等待请求而直接向客户端推送数据,而且WebSocket
是一直保持连接状态,首部信息量比Http
要小。
为了实现WebSocket
通信,需要在HTTP连接建立后完成一次握手步骤:
- 通过使用HTTP的Upgrade首部字段,
Upgrade
用来告诉服务器通信协议发生改变,Sec-WebSocket-Key
字段内记录着握手过程中必不可少的键值,Sec-WebSocket-Protocol
字段内记录使用的子协议。
- 对于客户端的握手请求,服务器返回状态码
101 Switching Protocols
响应,Sec-WebSocket-Accept
字段值是由握手请求中的Sec-WebSocket-Key
的字段值生成的。
- 成功握手确立
WebSocket
连接之后,通信不再使用Http
的数据帧,而采用WebSocket
的数据帧。JavaScript
可以调用"The WebSocket API
"(W3C标准制定)内提供的WebSocket
程序接口,以实现WebSocket
下的全双工通信。
Via
报文在经过代理或网关时,会在首部字段Via中附加该服务器的信息(使用的http版本等),Via首部是为了追踪传输路径,其经常和TRACE方法一起使用,比如代理服务器收到由TRACE方法发送过来的请求,当Max-Forwards: 0时代理服务器不再转发该请求,这时代理服务器将自身信息写入Via首部后返回该请求的响应。
Warning
该首部通常告知用户一些与代理缓存相关的问题的警告,Warning首部的格式及警告码内容如下:
语法:Warning: <warn-code> <warn-agent> <warn-text> [<warn-date>]
示例:Warning: 110 - "Response is stale"
- <warn-code>
三位数字警告码。第一位数字表示 Warning 信息在验证之后是否需要从已存储的响应中删除。
1xx 警告码描述了关于当前响应的新鲜度或者验证状态的警告信息,并且将会在验证之后被缓存服务器删除。
2xx 警告码描述了验证之后不会被修复的某些展现内容方面的警告信息,并且在验证之后不会被缓存服务器删除。
码值 | 文字描述 | 详细说明 |
110 | Response is Stale | 由缓存服务器提供的响应已过期(设置的失效时间已过)。 |
111 | Revalidation Failed | 由于无法访问服务器,响应验证失败。 |
112 | Disconnected Operation | 缓存服务器断开连接。 |
113 | Heuristic Expiration | 如果缓存服务器采用启发式方法,将缓存的有效时间设定为24小时,而在该响应的年龄超过24小时时发送。 |
199 | Miscellaneous Warning | 任意的、未明确指定的警告信息。 |
214 | Transformation Applied | 由代理服务器添加,如果它对返回的展现内容进行了任何转换,比如改变了内容编码、媒体类型等。 |
299 | Miscellaneous Warning | 与199类似,只不过指代的是持久化警告。 |
- <warn-agent>
添加到 Warning 首部的服务器或者软件的名称或者伪名称(当代理不可知的时候可以用 "-" 代替)。
- <warn-text>
用来描述错误信息的警告文本。
- <warn-date>
可选。假如多个 Warning 被发送,那么需包含一个与 Date 首部相对应的日期字段。
Content-Security-Policy
告诉用户代理在一个页面上可以加载使用的资源。
内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。
除此之外,html文件中设置 <meta>
标签也可以配置该策略, 如<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Accept
用户期望的 MIME类型。告诉服务器,用户能处理的媒体类型及其优先级。
如text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
。其中q用来指示优先级,使用分号;与媒体类型隔开,q的值从0.0到1.0,默认为1.0:
Accept-Charset
用户支持的字符集。告诉服务器,用户支持的字符集及字符集的优先级。
如Accept-Charset: iso-8859-5, unicode-1-1;q=0.8。
Accept-Encoding
用户支持的压缩方法。告诉服务器,用户支持的内容编码及编码的优先级。
如Accept-Encoding: gzip, deflate, br
。
常见的内容编码有 gzip
、compress
、deflate
、identity
(不执行压缩的默认编码格式),另外除了可以使用q来指定优先级外也可以使用通配符*来指定任意的编码格式。
Accept-Language
用户期望的自然语言。告诉服务器,用户支持的自然语言集及其优先级。
如Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,und;q=0.7
。
Accept-Ranges
范围请求可不可以被处理,Accept-Ranges: none
表示不能处理范围请求,Accept-Ranges: bytes
表示可以处理范围请求。
Authorization
用户凭证。告诉服务器,用户代理的认证信息(证书值)。
HTTP协议中的 Authorization
请求消息头含有服务器用于验证用户代理身份的凭证,通常会在服务器返回 401 Unauthorized
状态码以及WWW-Authenticate
消息头之后在后续请求中发送此消息头。
Expect
客户端发送Expect:100-Continue
握手的目的,是为了在客户端在发送请求内容之前,判断源服务器是否愿意接受请求(基于请求头部)。 xpect:100-Continue
握手需谨慎使用,因为遇到不支持HTTP/1.1协议的服务器或者代理时会引起问题。
From
告知服务器使用用户代理的用户的电子邮箱地址。
Host
虚拟主机运行在同一个IP上,使用Host
加以区分,如Host: www.lilnong.top
。Host
首部字段是HTTP/1.1
中唯一一个必须包含在请求内的首部字段,如果服务器未设定主机名则Host
值为空即可。
If-Match
只有当If-Match
的字段值跟请求资源的ETag值匹配时服务器才接受请求(这时的服务器无法使用弱ETag值),否则返回状态码412 Precondition Failed
响应:
If-None-Match
, 只有当If-Match的字段值跟请求资源的ETag值不匹配时服务器才接受请求,利用它可以获取最新的资源。
If-Modified-Since
,请求的资源在指定日期后发生了更新服务器才接受请求,否则返回304 Not Modified
(首部字段Last-Modified
可以获取资源的更新日期),其作用与If-Match类似。
If-Unmodified-Since
, 请求的资源在指定日期后未发生更新服务器才接受请求,否则返回412 Precondition Failed
响应。
If-Range、Range
, 请求的资源指定的ETag
值或时间匹配时则可作为范围请求处理,否则返回全部资源。
Max-Forwards
通过TRACE
或OPTIONS
方法发送包含首部字段Max-Forwards
的请求时,可以指定经过的服务器最大数目,当服务器收到收到值为0的请求时不再进行转发,直接返回响应,对此我们可以确定那台终点服务器的通信状态
Proxy-Authorization
接收到从代理服务器发来的认证质询时,客户端会发送包含该首部字段的请求,以告知认证所需要的信息,客户端与服务器之间的认证则使用首部字段Authorization。
Referer
告知服务器请求的原始资源的URI,告诉服务器我是从哪个页面链接过来的,服务器藉此可以获得一些信息用于处理,比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Refere
r中统计出每天有多少用户点击我主页上的链接访问他的网站。
TE
告知服务器客户端能够处理响应的传输编码方式及相对优先级,与Accept-Encoding
相像,但是用于传输编码。
User-Agent
传达浏览器或代理服务器的种类或名称,由网络爬虫发起请求时,有可能在该字段内添加爬虫作者的电子邮件地址。
Age
告知客户端资源缓存的时间,如Age: 600表示资源距上次请求已经过了600秒,代理创建响应时必须加上该首部字段。
ETag
告知客户端实体标识,ETag值是服务器给每个资源分配的唯一性标识,如ETag: "82e323200c392ff89323acd12"
,当资源更新后其ETag值也会变化,如下。
强ETag值是指实体发生细微变化就会改变ETag值。
弱ETag值只有当资源发生根本改变产生差异时才会更新,弱ETag值会在字段值前加一个"W/"
,如ETag: W/usagi-1234
。
Location
提示浏览器重定向到另一个URI位置,该字段一般会配合3xx: Redirection的响应
Proxy-Authenticate
将代理服务器所要求的认证信息发送给客户端,如Proxy-Authenticate: Basic realm="Usagidesign Auth"
。服务器与客户端之间进行认证时,首部字段WWW-Authorization
有着相同的作用。
Retry-After
告诉客户端在指定的秒数后或指定的时间(GMT格式)再次发起请求,主要配合状态码503 Service Unavailable
响应或3xx Redirect
响应使用。
Server
告知客户端http服务器信息,如Server: Apache/2.2.6
。
Vary
对缓存进行控制,源服务器会向代理服务器传达关于本地缓存使用方法的命令。
WWW-Authorization
通知客户端适用于请求URI所指定资源的认证方案(Basic或Digest)和带参数提示的质询,状态码401 Unauthorized
响应中肯定带有该首部字段,如WWW-Authorization: Basic realm="Usagidesign Auth"
。
Allow
当服务器收到不支持的方法请求时,会返回405 Method Not Found
,并将其支持的方法写入到Allow首部字段中,如Allow: GET, HEAD
。
Content
Content-Encoding
告知客户端服务器对实体主体部分选用的内容编码方式,如Content-Encoding: gzip
。
Content-Language
, 告知客户端实体主体使用的语言,如Content-Language: zh-CN
。
Content-Length
, 实体主体部分的大小(字节),对实体主体进行内容编码传输时,不能使用该首部字段。
Content-Location
, 指定报文主体返回资源对应的URI,比如,当返回的内容页面与实际请求的对象不同时,在该首部字段内写入URI。
Content-MD5
,报文主体的MD5值,使用Base64编码。
Content-Range
, 针对范围请求,告知客户端返回的实体的范围及整个实体的大小,如:Content-Range: bytes 5001-10000/10000
。
Content-Type
。
用于描述服务器文档的 MIME类型。帮助用户代理(浏览器)去处理接收到的数据。
实体主体内对象的媒体类型,和首部字段 Accept
一样采用type/subtype
形式,如 Content-Type: text/html; charset=UTF-8
。
Expires
告知客户端或缓存服务器资源失效时间,超出该时间后缓存服务器应该从源服务器获取该资源,如Expires: Wed, 23 May 2012 09:59:55 GMT
。源服务器不希望缓存服务器缓存的时候可以将该字段写入与Date相同的时间值。
Last-Modified
指明资源最终修改的时间,如Last-Modified: Wed, 23 May 2012 09:59:55 GMT
。
Cookie、Set-Cookie
Cookie
是由服务器端生成,发送给浏览器,将Cookie
的key/value
保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie
给服务器。
Set-Cookie
属于响应首部字段,包含了状态管理所使用的Cookie
信息。
Cookie
属于请求首部字段,用来通知服务端当前页面的域生效中的cookie
。
Set-Cookie
字段的属性必须包含赋予cookie
的名称和值,其它属性有:
expires
,cookie的有效期,不指定的话则默认为浏览器关闭为止,如果设置一个过去的时间,浏览器会立即删除该cookie。
path
,将服务器上指定文件目录作为cookie的适用对象,若不指定则默认为文档所在的文件目录。
domain
,作为cookie适用对象的域名(结尾匹配,比如指定lilnong.top后,除lilnong.top外,www.lilnong.top和www2.lilnong.top都可以发送Cookie),若不指定则默认为创建cookie的服务器的域名。
secure
,仅在https通信下才会发送cookie,指定secure属性的方式如:Set-Cookie: name=value, secure
。
HttpOnly
,使JavaScript脚本无法获得cookie,其主要目的是为防止跨站脚本攻击(XSS)对cookie信息的窃取。
Content-Dispositison
用来指示如何显示附加的文件,即设置Content-Disposition
告诉浏览器下载文件的名称和是否在浏览器中内嵌显示,如:
Content-disposition: inline; filename=1502849449726.jpg
表示浏览器内嵌显示一个文件。
Content-disposition: attachment; filename=1502849449726.xlsx
表示弹出下载提示对话框来下载文件。
X-Frame-Options
属于http响应首部,用来控制网站内容在其它web网站的Frame标签内的显示,其主要目的是为了防止点击劫持(clickjacking)攻击,如将其设为字段值DENY的话就是拒绝,页面不能被嵌入到任何iframe或frame中,SAMEORIGIN则为页面只能被本站页面嵌入到iframe或者frame中(比如当指定http://hackr.jp/sample.html
页面为SAMEORIGIN
时,hackr.jp上所有页面的frame都被允许可加载该页面,其它域名的页面就不行),ALLOW-FROM:页面允许frame或frame加载。