10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

如何选择正确的 HTTP 状态码

  • 2015-12-10
  • 本文字数:1858 字

    阅读完需:约 6 分钟

众所周知,每一个 HTTP 响应都会带有一个状态码,不过对于很多开发者来说,平时使用最多的几个状态码无外乎就是 200、400、404、500 等。那其他众多状态码该应用在何种场景中,什么时候应该使用哪些状态码就成为一个值得我们深入思考的问题了。即便在 Facebook 这样的公司中,那些聪明的开发者所构建的 API 也可能只返回 200。为此, Michael Kropat 专门撰文分析了各个状态码的适用场景,以及我们为何要如此细致地区分不同状态码,同时还谈及了这么做的好处。

有什么是比返回一个 HTTP 状态码还要简单的事情呢?页面渲染了么?如果渲染,那就返回 200 呗。页面不存在?那就是 404。需要将用户重定向到另外一个页面?那就使用 302,也许 301 也行。

一切都是如此简单,不过当有人跟你说,你并没有以 REST 的方式做事情,你可能就要警醒了。新资源是否返回了 RFC 兼容、 Roy-Fielding 建议的状态码?只会是 200 么?也许是 204 No Content、202 Accepted,抑或是 201 Created?

问题在于官方 HTTP/1.1 指南(RFC)最初是在 1997 年发布的。那时的我们还在使用 Netscape Navigator、33.6kbps 的调试解调器网上冲浪呢。这就好比是在现代商业战略中使用孙子兵法一样。这些宝贵的建议并不会随着时间的流逝而发生变化。不过,我们需要真正理解他们。

如果有可视化的决策树就好了,它可以帮助你快速识别与你的情况相吻合的状态码,这样就能忽略掉那些不相关的了。请看下图。

上图看起来是显而易见的,不过我发现很多人都会陷入其中,并且提出诸如“这种情况应该使用 503 Service Unavailable 还是 404 Not Found 呢”?停。如果你在完全不同的响应类别中思考具体的状态码,那就表明你的做法是完全错误的。再来看看上面这张图。

在继续之前我提出几点:

  • 你不必非得听我的,请直接查看 RFC 7231 httpstatuses.com
  • 我所面向的读者是那些创建网站或是使用 REST API 的开发者
  • 我将响应码大致划分为 3 大类

最后再提一点:我其实并没有什么资格就这个主题发表自己的看法,我只不过阅读过一些 RFC 并开发过一些 APIs 而已。如果觉得我说的不对,或是没有使用你倾向于使用的状态码,那么请在文末的评论中指出来,大家一起讨论。

2XX/3XX

4XX

5XX

为何说状态码很重要

虽说 Facebook 中很多聪明的开发者在构建APIs 时只返回200,但我想说的是,状态码确实是非常重要的。现有的状态码对于现代网站/API 来说有些太宽泛了。如果响应要以应用特定的格式来包含一些细节信息,比如说哪些字段验证失败了,原因是什么,这样可以让客户端以更加有意义的方式来处理响应。既然如此,那为何不多花点时间来研究一下那些“不太常用”的HTTP 状态码呢?

在谈及为何说使用具体的状态码是非常重要的时候,人们很爱提到的一个原因就是HTTP 是个分层系统,客户端与服务器之间可能存在着代理、缓存或是其他HTTP 库,如果响应码有意义,那会让这一切都工作地更好。不过,我觉得这个解释站不住脚,比如说未来大家都使用上了HTTPS,我们也禁用掉了所有代理与缓存结点,你能说这时状态码就没用了么?

这里,我想谈谈我认为状态码依然很重要的3 点原因:

1. 客户端可以针对不同的状态码采取不同的行为(或是可以轻松扩展以应对):

  • 301 Moved Permanently 与 302 Found 对于 Google 与其他搜索引擎来说还有 SEO 的隐喻
  • 301 Moved Permanently 有缓存的含义,而 429 Too Many Requests 则没有缓存的含义,诸如此类
  • 客户端库可以通过一段时间的延迟后重试请求来处理 429 Too Many Requests
  • 客户端库可以采取类似的方式处理 503 Service Unavilable

2. 很多状态码所表示的情况可以通过特殊的响应进行处理。

  • 返回 404 而非 405 Method Not Allowed 的 APIs 有时会让我抓狂,“我是输错了 URL 还是使用了错误的 HTTP 方法呢”?
  • 正确区分 502 Bad Gateway 与 500 Internal Server Error 会让你省下不少的调试时间。

3. 不管信不信,目前很多流行的 APIs 建立了一些约定,比如说返回 201 Created、429 Too Many Requests,或是 503 Service Unavilable。如果遵循这些约定,那么用户在使用你的网站 /API 时就会更轻松,遇到问题时也更容易解决。

如果你在使用 HTTP 状态码时遇到了问题,还可以参考如下资源:

各位读者,相信你们中的很多人都曾经或是正在设计 API,那么在这个过程中对于状态码你做过哪些思考呢?有哪些见解呢?欢迎分享出来与 InfoQ 的其他读者一同讨论。

2015-12-10 06:565226
用户头像

发布了 88 篇内容, 共 271.1 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

电商系统微服务拆分设计

Lane

双非渣本后端,三个月逆袭字节,入职那天“泪目”了

Java架构师迁哥

手写一个简单的SpringBoot Starter

赵镇

setTimeout(〒︿〒) 请原谅我一直以来对你的忽视

编程三昧

JavaScript 大前端 定时器 基础知识

现在后端开发都在用什么数据库存储数据?

Linux服务器开发

MySQL 数据库 后端 中间件 Linux服务器开发

排序算法之冒泡排序

xcbeyond

排序算法 冒泡排序 6月日更

堆与堆排序

wzh

Java 数据结构 算法 堆排序 数据结构与算法

作为程序员,你会使用Notion吗?

Bob

程序员 Notion 笔记

网络攻防学习笔记 Day49

穿过生命散发芬芳

网络攻防 6月日更

计算机系统性能评价

若尘

性能 计算机组成原理 6月日更

🌏【架构师指南】分布式事务(XA)与一致性算法(Paxos、Raft、Zab、NWR)

码界西柚

ZAB raft协议 paxos协议 6月日更

架构实战营 模块六:课后作业

Ahu

架构实战营

架构实战营模块六作业

竹林七贤

如何应对不好回应的沟通场景?

石云升

读书笔记 沟通 6月日更

三星T5 格式化成APFS

SamGo

学习 硬件产品

【21-11】PowerShell 特殊变量

耳东@Erdong

PowerShell 6月日更

大学生如何让更好的入门计算机?

Bob

入门 话题讨论 话题 大学生

模块6课后作业

方堃

Linux之pwd命令

入门小站

Linux

新一代数仓架构-Snowflake弹性数仓

一弦思华年

大数据 数据湖 云原生 OLAP 数仓

前端 JavaScript 之『节流』的简单代码实现

编程三昧

JavaScript 大前端 js 防抖节流 代码实现

Redis入门一:简介

打工人!

数据库 nosql redis 6月日更

韩信大招:一致性哈希

悟空聊架构

分布式 一致性hash 6月日更 hash算法

Anaconda 如何安装 BeautifulSoup 环境

Qien Z.

6月日更

「SQL数据分析系列」8. 分组和聚合

Databri_AI

数据库 sql 大数据 存储 计算

冯 · 诺依曼结构原理及层次结构分析

若尘

计算机组成原理

窥见AI工业化开发黎明:华为云如何将AI进行到底

脑极体

Python——计数器(Counter)

在即

6月日更

拆分电商系统为微服务

唐江

架构实战营

模块6 学习总结

TH

【Vue2.x 源码学习】第十九篇 - 根据 vnode 创建真实节点

Brave

源码 vue2 6月日更

如何选择正确的HTTP状态码_REST_张龙_InfoQ精选文章