HTTP Overview

作为 HTTP 系列文章的开篇,我们先快速回顾一下 HTTP 的发展史:

  • HTTP/0.9: 只支持 GET 请求,并且没有 Headers 的概念,并且只能返回 HTML
  • HTTP/1.0: 增添了 POST 以及 HEAD 请求,增添了状态码以及 Headers 的概念,依托于 Headers,可以返回除 HTML 文件之外的内容。HTTP 相关的基础内容在这个版本基本添加完毕,但是还存在无法连接复用以及请求只能排队发送的问题。
  • HTTP/1.1: 增添了 PUT,DELETE,TRACE,OPTIONS,PATCH,CONNECT 请求,增加了缓存的相关的 headers,增加了 headerConnection:keep-alive解决了连接复用问题,同时请求可以同时发送,并且增加了断点续传功能。这个版本增加了缓存以及连接复用等优化点,是目前很多网站最常使用的版本。但是还是不能解决队头堵塞的问题(虽然请求可以同时发送了,但是响应还是按照请求发送的顺序依次返回)
  • HTTP/2: 将原先的文本传输改为二进制格式传输(二进制分帧),同时共用一个 TCP 连接,并且请求和响应没有顺序的概念(多路复用)。并且将请求头部压缩,同时服务端可以主动推动消息给客户端。总的来说HTTP/2做了很多传输方面的优化。
  • HTTP/3: 弃用 TCP 协议,改为基于 UDP 协议的 QUIC 协议,主要解决队头堵塞的问题,目前还处于草案阶段。

HTTP Messages

作为 HTTP 最基础的内容,我们来熟悉一下 HTTP Messages,后续会针对不同内容进行细节补充。HTTP Messages 由 HTTP Requests 和 HTTP Responses 组成。

HTTP Requests 组成内容如下:

1
2
3
4
<method> <request-url> <version>
<headers>
//empty line
<entity-body>

HTTP Responses 组成内容如下:

1
2
3
4
<version> <status> <reason-phrase>
<headers>
//empty line
<entity-body>

下面做出解释:

  • method: 请求方式,常见的如 GET,POST 等
  • request-URL: 请求地址
  • version: 协议版本,常见的有 HTTP/1.1,HTTP/2
  • headers: 请求/响应 headers
  • entity-body: 请求/响应 body,body 可以是常见的 json 类型,也可以是二进制文件等类型
  • status: 状态码,常见如 200,404 等
  • reason-phrase: 原因短语,常见的如状态码 200 对应的 OK

Request Methods

Request Methods 常见的有 GET 和 POST 请求,但是HTTP/1.1整体上定义了 GET,POST,HEAD,PUT,DELETE,TRACE,OPTIONS,PATCH,CONNECT 九个请求方式,下面会逐一介绍相关请求方式的用途和注意项。在介绍各种请求方式之前,我们需要了解一个重要的概念:幂等(Idempotence)

Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

也就是说对于相同条件下的一次或多次请求,最终产生的副作用都是一致的,那么就可以说这个 Request Methods 是幂等的。

GET

GET 请求作为常见的请求,常用于获取资源,不应该对服务器资源有修改,所以是幂等的。作为最早出现的请求方式,有如下的特点和限制:

  • GET 请求可以被缓存,好处是我们可以利用缓存来减少相关静态资源的网络请求,坏处是在较早的 IE 浏览器中甚至是某些 GET 请求的接口都有缓存。
  • GET 请求会被保留到浏览记录中,同时也可以方便的添加为浏览器书签
  • GET 请求本身在规范中没有长度限制,但是不同浏览器对 GET 请求的长度有限制,例如 Chrome 的长度限制为 8KB

HEAD 请求和 GET 请求的区别是 HEAD 请求不返回 HTTP Response entity-body。正是因为这个特性,可以用于不获取资源的情况下,查看资源的一些信息如是否存在和修改等。
HEAD 请求是幂等且可缓存的。

POST

POST 请求也是最常见的请求,对服务器资源做新增或者修改操作,但是多次提交的副作用可能不一致,所以不是幂等的。
POST 请求没有长度限制,也不能缓存和被保存到浏览记录中。

PUT

PUT 请求虽然也可以对服务器资源做新增或者修改操作,但是和 POST 的区别是多次提交的副作用都是一致的,所以是幂等的。典型的场景如创建编号为 1234 的文章,PUT 操作如果没有则新建一个,如果有的话则不作改动。

DELETE

DELETE 请求表示对服务器的资源做删除操作,一次删除和多次删除的副作用是一致的,所以 DELETE 是幂等的。

TRACE

TRACE 请求发送的内容和收到的结果如果链路中没有修改则应该保持一致,利用这种特性可以验证 HTTP 请求在整个链路中是否被修改。TRACE 请求是幂等的。

OPTIONS

OPTIONS 请求可以获取目标资源所支持的 methods,并在 HTTP Responses headers 中的Allow进行标识。OPTIONS 请求是幂等的。
日常开发中在我们涉及到 CORS 跨域的情况下,复杂请求需要进行预检请求,用到的请求就是 OPTIONS

PATCH

PATCH 请求用于对资源进行局部更新,和 PUT 请求的区别是 PUT 请求需要提供全部详细信息,而 PATCH 请求则只需要提供部分信息。而且 PATCH 不是幂等的。

CONNECT

CONNECT 请求可以开启一个客户端与所请求资源之间的双向沟通的通道。它可以用来创建隧道。CONNECT 不是幂等的。

Summary

  • GET,HEAD,PUT, DELETE,OPTIONS,TRACE 请求都是幂等的,POST,PATCH,CONNECT 请求则不是幂等的
  • 常见的可缓存的请求是 GET 和 HEAD

Status & Reason Phrase

一般来说 status 都有约定俗成的 reason-phrase 一一对应,大部分情况下服务器不会自行修改 reason-phrase,所有我们重点关注 status 就可以。

总的来说:

  • 1xx: informational response
  • 2xx: success
  • 3xx: redirect
  • 4xx: client error
  • 5xx: server error

常见的状态码:
| status | reason-phrase |
|——–|———————–|
| 200 | Successful |
| 201 | Created |
| 301 | Moved Permanently |
| 302 | Found |
| 303 | See Other |
| 304 | Not Modified |
| 307 | Temporary Redirect |
| 308 | Permanent Redirect |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 405 | Method Not Allowed |
| 500 | Internal Server Error |
| 502 | Bad Gateway |
| 503 | Service Unavailable |
| 504 | Gateway Timeout |

这篇文章主要聊一下 3xx,4xx,5xx 状态码。

3xx Redirect

重定向相关的状态码,在一些诸如域名更换的情况下比较常用。但是不是所有的 3xx 状态码都与重定向有关,下面会讲到。

302 Found & 303 See Other & 307 Temporary Redirect

这三个状态码都可以引发临时性重定向,但是302 Found因为部分浏览器对标准支持的原因,会导致 POST 请求重定向到 GET 请求;303 See Other则只支持任意请求重定向到 GET 请求,是实际标准里的应该用到的临时性重定向且改变为 GET 请求的状态码;307 Temporary Redirect才是标准的临时性重定向,且不允许浏览器将 POST 请求重定向到 GET 请求。

301 Moved Permanently & 308 Permanent Redirect

这两个状态码都引发永久性重定向,区别是308 Permanent Redirect状态码不允许浏览器将 POST 请求重定向为 GET 请求,而301 Move Permanently则因为浏览器的标准支持原因,可能会导致 POST 请求重定向为 GET 请求。

由于临时性重定向会造成搜索引擎降权的问题(简单来说就是生成多个域名同时临时性重定向到目标域名,搜索引擎就会认为目标域名干扰判断,从而降权),因此我们平常在更换域名或者空间服务器时,建议使用永久性重定向。

304 Not Modified

虽然 304 在 3xx 区间内,但是这个状态码和重定向无关,与协商缓存相关,表示可以继续使用协商缓存的内容。

4xx Client Error

客户端错误相关的状态码,比如说使用了错误的请求方法,或者请求参数或路径不正确,都属于客户端请求错误,而服务器无法处理。

  • 400 Bad Request: 客户端请求语法错误
  • 401 Unauthorized: 需要认证相关的信息
  • 403 Forbidden: 资源不可用,通常是服务器相关权限设置问题导致。在 nginx 配置错误的情况下访问相关静态资源,会出现这个错误。
  • 404 Not Found: 服务器找不到相关资源,或者服务器拒绝请求又不想说明原因。是最为常见的错误码之一。
  • 405 Method Not Allowed: 服务器禁止使用相关请求方式,服务器应当在 Response Header 中的Allow中返回可用的请求方式

5xx Server Error

服务器在处理请求时出现错误或者异常。

  • 500 Internal Server Error: 一般来说是服务器源代码逻辑出现错误。
  • 502 Bad Gateway & 504 Gateway Timeout: 都是服务器作为代理或者网关时请求上游服务器,502 代表上游服务器有响应,但是响应异常;504 则代表上游服务器响应超时。
  • 503 Service Unavailable: 服务器临时维护或者过载暂时无法处理请求,如果服务器能够预计延迟时间,则应当在 Response Header 中的Retry-After中返回延迟时间。

下一篇我们对HTTP Headers展开介绍。

References

Comments