当你看list of available HTTP status codes,你会在某个时刻认识到,有很多人,但单独使用本身也不能真正解释错误。
所以要回答你的问题,有两个部分。一个是:你的API如何传达错误的原因,并添加API的用户(大多数情况下是另一个开发人员)可以阅读和采取行动的有用信息。您应该尽可能多地添加机器可读和人类可读的信息。
另一部分:HTTP状态代码如何帮助区分某些错误(和成功)状态?
这后一部分实际上比一件事情更难。有404个明显的情况用于告诉“未找到”。而500是服务器端的任何错误。
我不会使用状态401,除非我真的想让操作在存在HTTP身份验证凭证的情况下成功。 401通常会在浏览器中触发一个对话框,这很糟糕。
如果资源是唯一且已存在的,状态“409 Conflict”似乎是合适的。如果创建用户成功,状态“201 Created”听起来也是一个好主意。
请注意,还有更多的状态代码,其中一些与HTTP协议的扩展(如DAV)有关,一些完全没有标准化(例如状态“420让你的冷静”从Twitter API中获益)。看看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes看看到目前为止使用了什么,然后决定是否要使用适合您的错误情况的东西。
根据我的经验,简单地选择一个状态码并使用它是很容易的,但很难一致地按照现有标准进行操作。
我不会因为别人会抱怨而停下来。 :)正确的做RESTful接口本身就是一项艰巨的任务,但接口越多,获得的经验就越多。
编辑:
关于版本的:它被认为是不好的做法,把一个版本标记到URL,像这样:example.com/api/v1/stuff
它会工作,但它是不是很好。
但首先是:您的客户如何指定他想要获得哪种表示形式,即他如何决定要么获取JSON或XML?答案:Accept
标题。他可以为JSON发送Accept: application/json
,为XML发送Accept: application/xml
。他甚至可能接受多种类型,并且服务器决定返回什么。
除非服务器被设计为回答多个资源表示(JSON或XML,客户端选择),否则客户端的确没有多少选择。但让客户至少发送“application/json”作为他的唯一选择,然后返回标题Content-type: application/json
作为回应,这仍然是件好事。这样,双方都明确表示他们希望对方看到内容。
现在的版本。如果将版本放入URL中,则可以有效地创建不同的资源(v1和v2),但实际上,只有一个资源(= URL)使用不同的方法来访问它。当请求的参数和/或与当前版本不兼容的响应中的表示发生突变时,必须创建API的新版本。
因此,当您创建使用JSON的API时,您不会处理泛型JSON。你处理一个具体的JSON结构,它对你的API来说是独一无二的。您可以也可能应该在服务器发送的Content-type
中指出这一点。 “供应商”的扩展是这样的:Content-type: application/vnd.IAMVENDOR.MYAPI+json
会告诉世界,基本的数据结构是application/json,但它是你的公司和你的API,真正地告诉哪个结构期望。而这正是API请求的版本适合的地方:application/vnd.IAMVENDOR.MYAPI-v1+json
。
因此,不要将版本放入URL中,而是期望客户端发送Accept: application/vnd.IAMVENDOR.MYAPI-v1+json
标题,并且您也以Content-type: application/vnd.IAMVENDOR.MYAPI-v1+json
作为响应。这对第一个版本确实没有什么影响,但让我们看看版本2发挥作用时的情况。
URL方法将创建一组完全不相关的新资源。客户端会怀疑example.com/api/v2/stuff
与example.com/api/v1/stuff
的资源是否相同。客户端可能已经使用v1 API创建了一些资源,并且存储了这些东西的URL。他应该如何将所有这些资源升级到v2?资源真的没有改变,它们是一样的,唯一改变的是它们在v2中看起来不同。
是的,服务器可能会通过发送重定向到v2 URL来通知客户端。但重定向并不表示客户端还必须升级API的客户端部分。
对版本使用accept标头时,资源的URL对于所有版本都是相同的。客户端决定使用版本1或2请求资源,服务器可能如此友善,仍然可以回答版本1请求的版本1响应,但所有版本2的请求都带有新的闪亮的版本2响应。
如果服务器无法应对版本1请求,他可以通过发送HTTP状态“406不可接受”来告诉客户端(请求的资源只能根据发送的接受头文件生成不可接受的内容请求。)
客户端可以发送包含两个版本的accept头,这使得服务器可以使用他最喜欢的版本进行响应,即智能客户端可以实现版本1和版本2,并且现在将两者都作为accept头发送,并等待以便服务器从版本1升级到2.服务器会在每个响应中告诉它是版本1还是版本2,并且客户端可以采取相应措施 - 他不需要知道服务器版本升级的确切日期。
总结一下:对于一个非常基本的API,即使有一个版本也许是有限的,可能是内部的,但是使用起来可能会过度。但是你永远不知道这一年是否会成为现实。将版本号包含到API中始终是一个非常好的主意。最好的地方在于您的API即将使用的mime类型。检查单个现有版本应该是微不足道的,但您可以选择稍后进行透明升级,而不会混淆现有客户端。
restful api只是为我自己的网站的ajax/backbonejs/jquery使用。在这种情况下,我应该坚持相同的错误代码(比如400)吗?或者为每个AJAX响应返回200,并检查'success'变量以查看是否发生错误 – Nyxynyx 2013-03-24 15:50:03
不,通过错误代码指示基本的“成功/错误”事实是一个非常好的主意。错误响应由HTTP客户端处理,例如,它们不应该被缓存等。在数据有效载荷内指示相同也是一件好事。我自己的API在成功时有“数据”,或者在失败时有“错误”。这与“成功=真/假”基本相同,并且适用于我。但是确实知道状态“400错误请求”不是您认为的通用客户端错误状态。没有这样的事情,你必须指定错误状态。 – Sven 2013-03-24 16:28:24
很好的答案,斯文! 但是,您会说:>关于版本控制:将版本 >标记放入我不同意的网址中被认为是不好的做法。这是Apigee的一个[指南](http://apigee.com/about/api-best-practices/restful-api-design-second-edition),他得出结论认为* *确实是最佳的使用版本号的做法网址。他们还澄清了返回状态代码。 – unicopter 2013-04-10 19:27:14