透视HTTP协议-请求码&状态码

730 阅读8分钟

标准请求方法

请求方法的实际含义就是客户端发出了一个”动作指令“,要求服务器端对URI定位的资源执行这个动作。

目前HTTP/1.1规定了八种方法,单词都必须是大写的形式:

  1. GET:获取资源,可以理解为读取或者下载数据;
  2. HEAD:获取资源的元信息(服务器不会返回请求的实体数据,只会传回响应头);
  3. POST:向资源提交数据,相当于写入或上传数据;
  4. PUT:类似POST,但与POST存在微妙的不同,通常 POST 表示的是“新建”“create”的含义,而 PUT 则是“修改”“update”的含义;
  5. DELETE:删除资源;
  6. CONNECT:建立特殊的连接隧道;
  7. OPTIONS:列出可对资源实行的方法;
  8. TRACE:追踪请求-响应的传输路径。

安全与幂等

在HTTP协议里,所谓的”安全“是指请求方法不会破幻服务器上的资源,即不会对服务器上的资源造成实质的修改。按照这个定义,只有GET和HEAD方法是”安全“的。

幂等意思是多次执行相同的操作,结果也是相同的。很显然,GET和HEAD既是安全的也是幂等的,DELETE可以多次删除同一个资源,效果都是”资源不存在“,所以也是幂等的。

正确的网址

用什么来标记服务器上的资源呢?怎么区分这个资源和那个资源呢?

用的就是URI,即统一资源标识符。

URI的格式

URI本质上是一个字符串,这个字符串的作用是唯一地标记资源的位置或者名字。下面的这张图显示了 URI 最常用的形式,由 scheme、host:port、path 和 query 四个部分组成,但有的部分可以视情况省略。

  1. 第一个组成部分叫scheme,即”方案名“或者”协议名“,表示资源应该使用哪种协议来访问。在scheme之后,必须是三个特定的字符"://"
  2. 在"://"之后,是被称为”authority“的部分,表示资源所在的主机名,通常的形式是”host:post“
  3. 第三部分是标记资源所在位置的path。URI的path部分必须以”/“开始,也就是必须包含“/”
  4. 第四部分是附加参数“query”部分,它在 path 之后,用一个“?”开始,但不包含“?”,表示对资源附加的额外要求。查询参数 query 有一套自己的格式,是多个“key=value”的字符串,这些 KV 值用字符“&”连接,浏览器和服务器都可以按照这个格式把长串的查询参数解析成可理解的字典或关联数组形式。

响应状态码

RFC 标准把状态码分成了五类,用数字的第一位表示分类,而 099 不用,这样状态码的实际可用范围就大大缩小了,由 000999 变成了 100~599。

这五类的具体含义是:

  • 1××:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;
  • 2××:成功,报文已经收到并被正确处理;
  • 3××:重定向,资源位置发生变动,需要客户端重新发送请求;
  • 4××:客户端错误,请求报文有误,服务器无法处理;
  • 5××:服务器错误,服务器在处理请求时内部发生了错误。

常用状态码

状态码含义
200 OK成功状态码,表示一切正常,如果是非HEAD请求,通常在响应头后都会有boby数据
204 No Content成功状态码,响应头后没有body数据
206 Partial Content成功状态码,但body里的数据不是资源的全部,而是其中的一部分
301 Moved Permanently永久重定向,含义是此次请求的资源已经不存在了,需要改用新的URI再次访问
302 Found临时重定向,含义是此次请求的资源还在,但需要暂时用另一个URI访问
304 Not Modified表示资源未修改,用于缓存控制。它不具有通常的跳转含义,但可以理解成“重定向已到缓存的文件”(即“缓存重定向”)
400 Bad Request通用错误码,表示请求报文有错误,但未说明具体错误
403 Forbidden表示服务器禁止访问资源
404 Not Found表示资源在本服务器上未找到,所以无法提供给客户端
500 Internal Server Error通用错误码
501 Not Implemented表示客户端请求的功能还不支持
502 Bad Gateway通常是服务器作为网关或者代理时返回的错误码,表示服务器自身工作正常,访问后端服务器时发生了错误,但具体的错误原因也是不知道的
503 Service Unavailable表示服务器当前很忙,暂时无法响应服务

HTTP的特点

灵活可扩展

首先,HTTP协议是一个”灵活可扩展“的传输协议。

因为报文里的各个组成部分都没有做严格的语法语义限制,可以由开发者任意定制。

可靠传输

第二个特点,HTTP协议是一个”可靠“的传输协议。

这个特点显而易见,因为 HTTP 协议是基于 TCP/IP 的,而 TCP 本身是一个“可靠”的传输协议,所以 HTTP 自然也就继承了这个特性,能够在请求方和应答方之间“可靠”地传输数据。

应用层协议

第三个特点,HTTP是一个应用层的协议

请求-应答

第四个特点,HTTP协议使用的是请求-应答通信模式。

这个请求 - 应答模式是 HTTP 协议最根本的通信模型,通俗来讲就是“一发一收”“有来有去”,就像是写代码时的函数调用,只要填好请求头里的字段,“调用”后就会收到答复。请求 - 应答模式也明确了 HTTP 协议里通信双方的定位,永远是请求方先发起连接和请求,是主动的,而应答方只有在收到请求后才能答复,是被动的,如果没有请求时不会有任何动作。

无状态

第五个特点,HTTP协议是无状态的。

“无状态”形象地来说就是“没有记忆能力”。

其他特点

除了以上的五大特点,其实 HTTP 协议还可以列出非常多的特点,例如传输的实体数据可缓存可压缩、可分段获取数据、支持身份认证、支持国际化语言等。但这些并不能算是 HTTP 的基本特点,因为这都是由第一个“灵活可扩展”的特点所衍生出来的。

Q&A

Q:你能把 GET/POST 等请求方法对应到数据库的“增删改查”操作吗?请求头应该如何设计呢?

A:GET:查;POST:增;DELETE:删;PUT:改。请求头:请求方法+URI+HTTP版本号

Q:你觉得 TRACE/OPTIONS/CONNECT 方法能够用 GET 或 POST 间接实现吗?A:能

Q:HTTP 协议允许在在请求行里使用完整的 URI,但为什么浏览器没有这么做呢?

A:因为在请求头的字段里有URI,没有必要重复

Q:URI 的查询参数和头字段很相似,都是 key-value 形式,都可以任意自定义,那么它们在使用时该如何区别呢?

A:因为查询参数是与URI关联在一起的,所以它针对的就是资源(URI),是长期、稳定的。而头字段是与一次 HTTP 请求关联的,针对的是本次请求报文,所以是短期、临时的。简单来说,就是两者的作用域和时效性是不同的。比如,要获取一个JS文件,而它会有多个版本,这个“版本”就是资源的一种属性,应该用查询参数来描述。而如果要压缩传输、或者控制缓存的时间,这些操作并不是资源本身固有的特性,所以用头字段来描述更好。

Q:你在开发 HTTP 客户端,收到了一个非标准的状态码,比如 4××、5××,应当如何应对呢?

A:4xx错误时,要尽量详细清晰,告知客户端请求错在那。如果预定义不够,就自己扩展。 5xx,不用太详细,为了安全,只告诉那部分出错,方便定位。

Q: 你在开发 HTTP 服务器,处理请求时发现报文里缺了一个必需的 query 参数,应该如何告知客户端错误原因呢?

A:可以返回一个4xx错误,然后在body里用json等格式说明具体的错误原因。