HTTP状态码(英语:HTTP Status Code)是用以表示网页服务器超文本传输协议响应状态的3位数字代码(引自维基百科)。
这里所说的超文本传输协议自然就是位于计算机网络应用层的http协议(广义上也包括https)。而响应状态则是指,当客户端向服务端发送请求时,服务端给出了何种类型的响应。按照RFC 2616的定义,http协议对每一种响应类型都给出了唯一对应的三位数字,每个数字称为一个状态码。目前总共有五大类状态码,分别对应五大类状态,各以1-5开头,它们的大致分类如下:
分类 | 分类描述 |
---|---|
1xx | 信息响应,表示服务器已收到请求,但是需要请求者继续操作 |
2xx | 响应成功,表示服务器已接收到请求并正确处理 |
3xx | 重定向,表示服务器已接收到请求,但是没有直接处理,而是进行了重定向 |
4xx | 客户端错误,表示客户端发出的请求中存在错误,无法完成请求 |
5xx | 服务端错误,表示服务器在处理请求的过程中出现错误 |
根据http状态码,开发或者运维可以大致了解http传输的状态,从而在发生错误时快速锁定问题范围。
下面是目前规范所定义的所有状态码及其含义。
三级标题由两部分构成,分别为状态码的值,及状态文本。状态文本用于大致描述该状态码的含义。
这只是个临时的响应状态,它表示到目前为止,客户端请求的内容都没有问题。但是客户端需要继续发送请求,才能完成本次请求过程。
服务器正在切换协议。
该代码是响应客户端的 Upgrade 标头发送的,并且指示服务器也正在切换的协议。比如,我们在使用ws协议时常会见到这个状态码。
从协议本身来说,http协议和ws协议并没有什么联系。前者是一个无状态、短连接的协议,后者是一个有状态、长连接的协议。但是为了降低协议设计的复杂度,ws协议并没有定义如何直接在客户端和服务端建立一个ws连接,而是约定客户端和服务端应该先建立一个http连接,然后由客户端发送一个切换协议的请求,两者再从http协议切换到ws协议。
服务器在切换协议的时候,就会向客户端返回状态码101。
服务端已收到请求,正在处理中,但无响应可用。
简言之,服务端正在处理当前请求。
预加载提示。此状态代码主要用于与Link 链接头一起使用,以允许用户代理在服务器仍在准备响应时开始预加载资源。
下面的标签会发起一个预加载请求:
<link rel='preload' as='script' href='/js/index.js'>
由于设置了rel='preload'
,这个link标签只是提前告诉浏览器,这里描述的资源很快就会用到,请提前下载好。浏览器下载完该资源后并不会执行,而是等到需要执行时才会执行:
<link rel='preload' as='script' href='/js/index.js'>
...
<!-- 这一行才会执行index.js的代码 -->
<script src='/js/index.js'></script>
这样浏览器便可以同时渲染DOM和下载脚本,这通常可以带来页面性能的提升。
状态码103就表示当前请求的类型为预加载类型。
这是开发和运维最希望看到的一组状态码,它们的含义如下:
请求成功。
表示当前请求被正确处理和返回。对不同的http方法来说,它的含义略有差异:
请求已成功,并因此创建了一个新的资源。当请求类型为POST或PUT时,服务端可能会返回这个状态码。
请求已收到,但还未响应,因此没有结果。
不同于状态码102
,返回状态码202
意味着服务端之后不会再给出响应来表明该请求的处理结果(102表示请求未完结,服务端后续会继续给出响应)。服务器可能将这个请求交给了其他进程或服务,或者执行了批处理。
服务器已成功处理了请求,但返回的实体头部元信息不是在原始服务器上有效的确定集合,而是来自本地或者第三方的拷贝。当前的信息可能是原始版本的子集或者超集。例如,包含资源的元数据可能导致原始服务器知道元信息的超集。
使用此状态码不是必须的,而且只有在响应不使用此状态码便会返回200 OK的情况下才是合适的。
服务器已成功处理了请求,但没有返回任何实体内容,并且浏览器不需要刷新或者重定向。
举例来说,当客户端提交了一个form表单,如果服务端正确处理并返回状态码200
,那么当前页面通常会刷新或重定向。而如果服务端返回的状态码是204
的话,浏览器将不会刷新当前页面,也不会重定向,而是仅仅收到请求成功的消息。如果我们需要更新页面,可以在请求成功的回调函数中手动处理。
另外,如果a标签发送的请求返回的状态码是204
,那么页面也不会发生跳转。
使用状态码204
可以避免传输多余的数据,以及某些不必要的页面更新。
服务器已成功处理了请求,但没有返回任何实体内容,不过浏览器应该立即刷新当前页面。
该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。
服务器已经成功处理了部分 GET 请求。
这种情况常见于断点续传和大文档分段。在使用类似迅雷这样的http传输工具时,由于文档一般较大,通常无法只使用一个get请求就下载完整个文档,否则一旦传输过程中出现异常,整个文档就不得不重新下载。另外,将文档分成多个数据段,可以同时发送多个get请求,这样可以提高下载速度,并且可以支持断点续传。
要实现这个需求,客户端需要在GET请求中通过Range头信息指定要下载的内容范围,服务端每传输其中一段数据,就会发送一个206
响应。
这是由WebDAV扩展的状态码,代表之后的消息体将是一个XML消息,并且可能依照之前子请求数量的不同,包含一系列独立的响应代码。这是一个提示性的状态码。
在 DAV 里面使用: propstat 响应元素以避免重复枚举多个绑定的内部成员到同一个集合(引用自MDN,该状态码似乎不是面向http协议的,而是WebDAV)。
服务器已经完成了对资源的 GET 请求,并且响应是对当前实例应用的一个或多个实例操作结果的表示。
被请求的资源有多个可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。
即客户端的请求存在多个可用资源时,客户端需要继续选择其中一个。
被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
收到该状态码表示当前要请求的资源位置发生了变更,需要使用当前响应返回的新的资源地址进行请求。一般来说,客户端应当自动在收到301
状态码时根据返回结果自动重置资源地址,以防止下次请求资源再次返回301
。
请求的资源被临时重定向到了别的URI。但这个重定向只是临时的,下次请求当前资源时仍然应该使用当前的地址(即客户端不需要像收到状态码301
那样修改资源地址)。
这个状态码对应的响应数据一般来说不会被缓存,除非明确指定了Cache-Control或Expires。
当前请求的响应结果可以从另一个URI请求到,而且客户端应该使用GET方法进行请求。
当客户端向服务端发送POST(或PUT、DELETE)请求时,如果服务端返回状态码303
,表示服务端已经收到请求,但是不会进行处理。客户端需要向响应中携带的新的URI发送GET请求,服务端才会进行处理(图片来自网络)。
响应中的location就是客户端下次发送GET请求的地址。
未修改。
该响应码非常常见,它表示当前资源已被下载过,并且没有改变,因此客户端应该从缓存中获取该资源。比如在刷新页面时,如果某个资源的状态码是304
,通常表明它来自于浏览器缓存。
注意,304
状态码禁止携带消息体,并且只用于GET请求。
当前资源需要使用指定的代理才能访问。响应的Location域给出了代理所在的URI,客户端需要向这个代理再次单独发送一个请求才能获取指定的资源。
(MDN文档中305状态码后面的图标似乎表明该状态码已经不被推荐使用)
最新的规范中,306不再被使用。
请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
可以看到,它的含义与状态码302
是几乎一致的。实际上,302
是在http1.0中定义的,而303
和307
是在http1.1中定义的。http1.1希望用这两个更精确的状态码取代http1.0中的302
,但是由于302
已被广泛引用与生产,而另外两个状态码暂未得到很好的支持,因此目前还是以302
的使用为主(三者的关系参考文章HTTP状态码302、303和307的故事)。
被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一,并且不应该修改请求方法。
它的含义与301 Moved Permanently
是一致的,但是它有一个特殊的要求,就是在请求新的地址的时候,必须使用当前的请求方法。也就是说,如果当前发送的是POST请求,那么新的请求也要使用POST方法。
请求有误。它包含两种情况:
未授权。即当前请求需要进行用户验证。
该响应应该包含一个WWW-Authenticate信息头以询问用户信息。客户端需要在下次请求中携带合法的用户验证证书才能得到正确的响应。
如果客户端的上次请求中已经携带了用户证书,服务端仍然返回状态码401
,就表示服务端拒绝了这些证书(即证书无效)。如果浏览器再次发送该请求,且再次被拒绝时,客户端应该向用户展示响应中的实体信息,因为这里可能包含了证书被拒绝的原因。
该状态码暂未使用,将来可能用于数字支付系统。
服务器已经接受并理解了请求,但是拒绝执行。
不同于401
,这个状态并不是身份验证导致的,并且该请求不应该被再次提交(因为仍然会被拒绝)。
如果这不是一个HEAD请求,而且服务器希望提供拒绝该请求的原因,可以在响应体中描述拒绝的原因。如果服务端不希望提供拒绝的原因,也可以直接返回状态码404
。
请求的资源不存在。
当服务器无法找到客户端所要请求的资源,并且无法(或者不想)解释到哪里找到这些资源时,常常会用到这个状态码。这个状态码无法告诉客户端资源不存在是暂时的还是永久的,也不会提供跳转地址,只是笼统地告诉客户端当前请求的资源不存在。
如果服务器明确知道某些资源已经被删除,并且想要告知客户端,可以使用状态码410
。
请求方法不允许。
比如服务端设置某个资源只能用POST方法进行访问,而客户端发送的是一个GET请求,服务端就会返回状态码405
,表示当前方法不能请求到该资源。该响应必须在Allow响应头中罗列出当前资源支持的请求方法列表。
由于PUT、DELETE等方法会对服务器上的资源执行写操作,因此在服务端没有明确指定的情况下发送这类请求,都会收到状态码405
。
请求的资源的内容特性无法满足请求头中的条件,因此无法生成响应实体。
比如客户端设置返回的数据类型必须是JSON,而服务端没有配置转换JSON所依赖的包,或者所请求的资源本身就无法转化为JSON,这时服务端就无法生成符合客户端要求的响应实体,因此就会返回状态码406
。
需要在代理服务器上进行身份验证。
该状态码与401 Unauthorized
类似,但是它要求客户端必须在代理服务器上进行身份验证。代理服务器需要返回一个Proxy-Authenticate字段给客户端,客户端将这个字段的值发送给服务器进行身份验证。
请求超时。
当前请求没有在指定的时间内收到响应。客户端可以在不作任何修改的情况下,重新发送该请求。
当前请求与所请求资源的状态存在冲突,请求无法完成。
比如某个资源在特定情况下不可用,而服务器认为客户端能够解决这个冲突,就可以返回409
,并且在响应信息中描述资源冲突的原因,以帮助用户解决冲突,重新请求资源。
如果服务端认为客户端无法解决该冲突,则不应该使用该状态码。
含义类似于404
,表示请求的资源在服务器上已经不可用,并且没有可转发的地址。
一般来说,返回410
的资源应该是永久不可用的。客户端收到410
时应当删除所有指向该资源的请求,以防止继续请求这个已经不存在的资源。如果服务端无法知道资源是否永久不可用,应该使用更常规的状态码404
。
服务端拒绝没有Content-Length参数的请求。
此时客户端应该在消息头内添加描述消息体长度的参数Content-Length再重新发送请求。
先决条件验证失败。
客户端可以在请求资源时,在请求头中描述所要请求的资源需要满足的先决条件,如果服务器发现该资源不符合客户端设置的先决条件,就会返回状态码412
。这样可以避免该请求方法被用于非客户端需要的资源之上。
当前请求提交的数据量过大,服务端拒绝(或无法)处理。
此时服务端可以选择关闭连接,以避免客户端继续发送此类请求。如果这个状况是临时的,服务端可以返回一个Retry-After
响应头,以告知客户端在多久以后可以重新发送该请求。
请求的URI过长,服务端无法解释,因此拒绝该请求。
比如,一个本应通过POST提交的表单,现在被通过GET方法提交,整个表单的数据全部被作为查询参数添加到了URI中,就可能导致查询字符串过长,服务端无法处理,从而返回414
。
对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝。
即客户端提交的数据格式不被服务器支持。
如果请求头包含了Rage参数,并且其指定的数据范围与当前资源不重合,同时没有定义If-Range字段,服务器就会返回416
。
比如某个文件的大小为100kB,而当前请求要下载200kB-300kB范围内的数据,就会得到416
的报错。
此响应代码意味着服务器无法满足 Expect 请求标头字段指示的期望值。
Expect域包含了客户端对服务端的期望条件,只有满足了这个期望条件,才能继续执行请求。目前Expect字段仅支持一个值:100-Continue
,客户端通过设置Expect的值为100-Continue
,来通知服务器接下来客户端将发送一个体积很大的消息体,并询问服务端是否要继续。服务端可以给出以下两个状态码响应:
100
,表示服务器允许客户端发送这个体积很大的请求,并等待客户端的后续请求。417
,服务端拒绝接收这个体积很大的请求。我是一个茶壶,不能用来冲咖啡。
这个状态码是1998年的愚人节提交的,带有一定的幽默成分。它的原义是:当你向服务端发送一个“冲咖啡”的请求时,服务器会返回给你一个418
的状态码,告诉你“我是一个茶壶,不要用我来冲咖啡”。
实际上大部分的服务器并没有实现这个状态码,只是将其作为一个愚人节玩笑看待。比如当用户使用GET请求提交表单的时候,你就可以在服务端向客户端返回一个418
状态码。因为GET请求是用来获取资源的,而不是用来提交数据的,这就像你在拿“茶壶”冲“咖啡”一样。
该请求针对的是无法产生响应的服务器。 这可以由服务器发送,该服务器未配置为针对包含在请求 URI 中的方案和权限的组合产生响应。
换句话说,对于某些特定的URI,服务器无法作出响应。
请求格式良好,但由于语义错误而无法遵循。
在讲状态码400 Bad Request
时,我们说到,它可以表示请求的语义错误,或请求参数错误;而415 Unsupported Media Type
则用于描述请求参数的格式错误。
那么当服务端明确知道当前错误是请求的语义错误时,就可以返回状态码422
。
当前所请求的资源暂时被锁定。
由于当前请求所依赖的请求失败,所以当前请求也失败。
服务器不愿意冒风险来处理该请求,原因是处理该请求可能会被“重放”,从而造成潜在的重放攻击。
所谓的重放攻击,指的是当某个用户在认证过程中,其认证信息被第三方窃取。这个第三方可能假冒当前用户的身份向服务器重新发出身份认证的请求,从而假冒该用户的身份。服务器认为当前请求可能存在这种情况时,可以返回425
拒绝用户的请求。
服务器拒绝在当前协议下执行该请求,希望客户端切换到其他协议。
服务端需要在响应消息的Upgrade
参数中指明客户端需要升级到何种协议才可以发送请求。
服务器要求客户端的请求中必须携带某些条件,一般这意味着请求中缺少了必要的If-Match
字段。
该状态码可以防止“更新丢失”。即客户端读取服务器上的某个资源,进行修改并返回给服务器的过程中,如果存在一个第三方也在修改该资源的状态,那么先被提交的更新就会丢失。服务端要求客户端必须设置更新资源的条件,否则就返回428
。
请求频率过高。
用户在给定的时间内发送了过多的请求,服务端可以对限制数量以外的请求返回这个状态码,以防止服务器性能受到损失。
请求头过大,服务器拒绝处理该请求。
客户顿需要在减小请求头大小后重新发送该请求。
非法资源。
它表示当前资源由于法律原因不可用,如被政府审查的网页等。
服务器内部错误。
返回该状态码意味着服务器遇到了未知的错误,是一个通用的服务器错误的状态码。
请求所用方法暂未被服务器实现,因此无法处理。
只有GET和HEAD是要求服务器必须支持的,这两个方法不可能返回501
。其他的方法如果服务器暂未实现,可以向客户端返回一个501
。
网关错误。
它表示作为网关或代理角色的服务器,从上游服务器(如tomcat、php-fpm)中接收到的响应是无效的。
Gateway(网关)在计算机网络体系中可以指代不同的设备,502 错误通常不是客户端能够修复的,而是需要由途经的Web服务器或者代理服务器对其进行修复。
服务器没有准备好处理请求。
比如服务器因维护或重载而停机。这时服务端一般需要返回一个友好的提示页面,同时在响应消息中给出预计的恢复时间,以使客户端了解问题原因及处理方法。
作为网关使用的服务器,因没有及时得到响应而返回该错误代码。这里所说的响应,是其上游服务器的响应。
服务器不支持请求中所使用的的http版本。
服务器存在内部配置错误。该状态码会出现在TCN(透明内容协商,见RF2295)上下文中(参考MDN - 506 Variant Also Negotiates)。
TCN协议允许客户端取回给定资源的最佳变量/变元,具体取哪个变量/变元需要经过一个内容协商机制。而如果备选的变量/变元参与到了这个内容协商机制中,就会出现循环引用的错误,服务端将返回错误码506
。
服务器存在内部配置错误。
所选的变体资源被配置为参与透明内容协商本身,因此服务器拒绝进行存储。适用场景同上。
服务器在执行请求时检测到了无限循环,因此终止了执行。
客户端需要对请求进一步扩展,服务器才能实现它。服务器会回复客户端发出扩展请求所需的所有信息。
客户端需要进行身份认证才能获得网络访问权限。
以上是MDN列举出的所有目前在用的http状态码,对于原文档解释得不是很清楚的部分,本文结合网上的一些文章进行了进一步说明,希望对从事web开发的同学带来一些帮助。