Skip to content

Commit 8f2294f

Browse files
committed
feat(状态码&数据缓存): 调整状态码分组方式,并补充数据缓存小节中遗漏的“必要的响应头”
1 parent c794868 commit 8f2294f

File tree

1 file changed

+52
-18
lines changed

1 file changed

+52
-18
lines changed

README.md

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ PS 考虑到存在[夏时制](https://en.wikipedia.org/wiki/Daylight_saving_time
147147

148148
## 请求方法
149149

150-
* [维基百科](http://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE#.E8.AF.B7.E6.B1.82.E6.96.B9.E6.B3.95)
151150
* 如果请求头中存在 `X-HTTP-Method-Override` 或参数中存在 `_method`(拥有更高权重),且值为 `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `OPTION`, `HEAD` 之一,则视作相应的请求方式进行处理
152151
* `GET`, `DELETE`, `HEAD` 方法,参数风格为标准的 `GET` 风格的参数,如 `url?a=1&b=2`
153152
* `POST`, `PUT`, `PATCH`, `OPTION` 方法
@@ -174,19 +173,19 @@ PS 考虑到存在[夏时制](https://en.wikipedia.org/wiki/Daylight_saving_time
174173
* `DELETE` 用于删除某个资源
175174
* 完成请求后返回状态码 `204 No Content`
176175

177-
## 状态码
176+
相关资料:
178177

179-
* [维基百科上的《 HTTP 状态码》词条](http://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81)
180-
* [RFC 4918](http://tools.ietf.org/html/rfc4918) - 422 状态码的来源
178+
* [RFC 7231 中对请求方法的定义](http://tools.ietf.org/html/rfc7231#section-4.3)
181179
* [RFC 5789](http://tools.ietf.org/html/rfc5789) - PATCH 方法的定义
182-
* [RFC 6585](http://tools.ietf.org/html/rfc6585) - 新增的四个 HTTP 状态码,[中文版](http://www.oschina.net/news/28660/new-http-status-codes)
183-
* [Do I need to use http redirect code 302 or 307? - Stack Overflow](http://stackoverflow.com/questions/2467664/do-i-need-to-use-http-redirect-code-302-or-307)
184-
* [400 vs 422 response to POST of data](http://stackoverflow.com/questions/16133923/400-vs-422-response-to-post-of-data)
180+
* [维基百科](http://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE#.E8.AF.B7.E6.B1.82.E6.96.B9.E6.B3.95)
181+
182+
## 状态码
185183

186184
### 请求成功
187185

188186
* 200 **OK** : 请求执行成功并返回相应数据,如 `GET` 成功
189187
* 201 **Created** : 对象创建成功并返回相应资源数据,如 `POST` 成功;创建完成后响应头中应该携带头标 `Location` ,指向新建资源的地址
188+
* 202 **Accepted** : 接受请求,但无法立即完成创建行为,比如其中涉及到一个需要花费若干小时才能完成的任务。返回的实体中应该包含当前状态的信息,以及指向处理状态监视器或状态预测的指针,以便客户端能够获取最新状态。
190189
* 204 **No Content** : 请求执行成功,不返回相应资源数据,如 `PATCH``DELETE` 成功
191190

192191
### 重定向
@@ -198,23 +197,27 @@ PS 考虑到存在[夏时制](https://en.wikipedia.org/wiki/Daylight_saving_time
198197
* 303 **See Other** : 对应当前请求的响应可以在另一个 URI 上被找到,客户端应该使用 `GET` 方法进行请求
199198
* 307 **Temporary Redirect** : 对应当前请求的响应可以在另一个 URI 上被找到,客户端应该保持原有的请求方法进行请求
200199

201-
### 客户端出错
200+
### 条件请求
201+
202+
* 304 **Not Modified** : 资源自从上次请求后没有再次发生变化,主要使用场景在于实现[数据缓存](#user-content-数据缓存)
203+
* 409 **Conflict** : 请求操作和资源的当前状态存在冲突。主要使用场景在于实现[并发控制](#user-content-并发控制)
204+
* 412 **Precondition Failed** : 服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。主要使用场景在于实现[并发控制](#user-content-并发控制)
205+
206+
### 客户端错误
202207

203208
* 400 **Bad Request** : 请求体包含语法错误
204209
* 401 **Unauthorized** : 需要验证用户身份,如果服务器就算是身份验证后也不允许客户访问资源,应该响应 `403 Forbidden`
205210
* 403 **Forbidden** : 服务器拒绝执行
206211
* 404 **Not Found** : 找不到目标资源
207212
* 405 **Method Not Allowed** : 不允许执行目标方法,响应中应该带有 `Allow` 头,内容为对该资源有效的 HTTP 方法
208-
* 406 **Not Acceptable** : 服务器不支持客户端请求的内容格式(比如客户端请求 JSON 格式的数据,但服务器只能提供 XML 格式的数据)
209-
* 409 **Conflict** : 请求操作和资源的当前状态存在冲突
210-
* 410 **Gone** : 被请求的资源已被删除
211-
* 412 **Precondition Failed** : 服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。主要使用场景在于实现[并发控制](#user-content-并发控制)
212-
* 413 **Request Entity Too Large** : `POST` 或者 `PUT` 请求的消息实体过大
213+
* 406 **Not Acceptable** : 服务器不支持客户端请求的内容格式,但响应里会包含服务端能够给出的格式的数据,并在 `Content-Type` 中声明格式名称
214+
* 410 **Gone** : 被请求的资源已被删除,只有在确定了这种情况是永久性的时候才可以使用,否则建议使用 `404 Not Found`
215+
* 413 **Payload Too Large** : `POST` 或者 `PUT` 请求的消息实体过大
213216
* 415 **Unsupported Media Type** : 服务器不支持请求中提交的数据的格式
214217
* 422 **Unprocessable Entity** : 请求格式正确,但是由于含有语义错误,无法响应
215218
* 428 **Precondition Required** : 要求先决条件,如果想要请求能成功必须满足一些预设的条件
216219

217-
### 服务端出错
220+
### 服务端错误
218221

219222
* 500 **Internal Server Error** : 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
220223
* 501 **Not Implemented** : 服务器不支持当前请求所需要的某个功能。
@@ -223,6 +226,15 @@ PS 考虑到存在[夏时制](https://en.wikipedia.org/wiki/Daylight_saving_time
223226

224227
`501``405` 的区别是:`405` 是表示服务端不允许客户端这么做,`501` 是表示客户端或许可以这么做,但服务端还没有实现这个功能
225228

229+
相关资料:
230+
231+
* [RFC 里的状态码列表](http://tools.ietf.org/html/rfc7231#page-49)
232+
* [RFC 4918](http://tools.ietf.org/html/rfc4918) - 422 状态码的定义
233+
* [RFC 6585](http://tools.ietf.org/html/rfc6585) - 新增的四个 HTTP 状态码,[中文版](http://www.oschina.net/news/28660/new-http-status-codes)
234+
* [维基百科上的《 HTTP 状态码》词条](http://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81)
235+
* [Do I need to use http redirect code 302 or 307? - Stack Overflow](http://stackoverflow.com/questions/2467664/do-i-need-to-use-http-redirect-code-302-or-307)
236+
* [400 vs 422 response to POST of data](http://stackoverflow.com/questions/16133923/400-vs-422-response-to-post-of-data)
237+
226238
## 错误处理
227239

228240
在调用接口的过程中,可能出现下列几种错误情况:
@@ -373,27 +385,49 @@ Link: <http://api.example.com/#{RESOURCE_URI}?last_cursor=&count=100>; rel="firs
373385

374386
## 数据缓存
375387

376-
大部分接口应该在响应头中携带 `Last-Modified``ETag` 信息,客户端可以在随后请求这些资源的时候,在请求头中使用 `If-Modified-Since` 或者 `If-None-Match` 两个头来确认资源是否经过修改。
388+
大部分接口应该在响应头中携带 `Last-Modified`, `ETag`, `Vary`, `Date` 信息,客户端可以在随后请求这些资源的时候,在请求头中使用 `If-Modified-Since`, `If-None-Match` 等请求头来确认资源是否经过修改。
389+
390+
如果资源没有进行过修改,那么就可以响应 `304 Not Modified` 并且不在响应实体中返回任何内容。
377391

378392
```bash
379393
$ curl -i http://api.example.com/#{RESOURCE_URI}
380394
HTTP/1.1 200 OK
381-
Cache-Control: private, max-age=60
395+
Cache-Control: public, max-age=60
396+
Date: Thu, 05 Jul 2012 15:31:30 GMT
397+
Vary: Accept, Authorization
382398
ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
383399
Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
384400

401+
Content
402+
```
403+
404+
```bash
385405
$ curl -i http://api.example.com/#{RESOURCE_URI} -H "If-Modified-Since: Thu, 05 Jul 2012 15:31:30 GMT"
386406
HTTP/1.1 304 Not Modified
387-
Cache-Control: private, max-age=60
407+
Cache-Control: public, max-age=60
408+
Date: Thu, 05 Jul 2012 15:31:45 GMT
409+
Vary: Accept, Authorization
388410
Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
411+
```
389412

413+
```bash
390414
$ curl -i http://api.example.com/#{RESOURCE_URI} -H 'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"'
391415
HTTP/1.1 304 Not Modified
392-
Cache-Control: private, max-age=60
416+
Cache-Control: public, max-age=60
417+
Date: Thu, 05 Jul 2012 15:31:55 GMT
418+
Vary: Accept, Authorization
393419
ETag: "644b5b0155e6404a9cc4bd9d8b1ae730"
394420
Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT
395421
```
396422

423+
相关资料:
424+
425+
* [RFC 7232](http://tools.ietf.org/html/rfc7232)
426+
* [HTTP 缓存 - Google Developers](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn)
427+
* [RFC 2616 中缓存过期时间的算法](http://tools.ietf.org/html/rfc2616#section-13.2.3), [MDN 版](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ), [中文版](http://blog.csdn.net/woxueliuyun/article/details/41077671)
428+
* [HTTP 协议中 Vary 的一些研究](https://www.imququ.com/post/vary-header-in-http.html)
429+
* [Cache Control 與 ETag](https://blog.othree.net/log/2012/12/22/cache-control-and-etag/)
430+
397431
## 并发控制
398432

399433
不严谨的实现,或者缺少并发控制的 `PUT``PATCH` 请求可能导致 “更新丢失”。这个时候可以使用 `Last-Modified` 和/或 `ETag` 头来实现条件请求,支持乐观并发控制。

0 commit comments

Comments
 (0)