在基于REST的API错误最佳实践 [英] Best Practice for Errors in RESTful API

查看:220
本文介绍了在基于REST的API错误最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是REST风格的API返回的HTTP状态codeS的最佳实践?我使用Laravel 4我的PHP框架。

在一个错误的情况下,我应该用

 返回响应:: JSON(用户存在',401);

包括标志成功

 返回响应:: JSON([
    '成功'=>假,
    '数据'=> 用户存在'],
    401
);

用200代替4XX,依靠成功,以确定是否有错误

 返回响应:: JSON([
    '成功'=>假,
    '数据'=> 用户存在'],
    200
);

和在成功的情况下,也没有必要返回任何数据,你还回什么?

PHP API code

 公共职能getCheckUniqueEmail(){
    //检查电子邮件表中已经存在的'用户'
    $ uniqueEmail = checkIfEmailExists();    //返回JSON响应
    如果($ uniqueEmail){
        //验证失败(用户存在)
        返回响应:: JSON(用户存在',401);
    }其他{
        //验证成功
        // - 什么回报?
    }
}


解决方案

当你看的列表提供HTTP状态codeS ,你会在某个时刻认识到,有很多人,但单独使用本身也不能真正解释错误。

因此​​,要回答你的问题,有两个部分。其中之一是:如何可以将您的API为传达一个错误的原因,并添加有用信息的API(在大多数情况下是另一开发商)的用户可以读取并呼吁采取行动。您应该添加尽可能多的信息越好,这两个机器可读和人类可读的。

另一部分:如何能HTTP状态codeS帮助中区分一定的误差(和成功)状态

这后一部分实际上比人们的事情更难。有404的地方是用来告知没有发现明显的情况下。而500是服务器端的任何错误。

我不会用状态401,除非我真的很想让操作才能成功,如果有HTTP认证证书present。 401通常会触发在浏览器中,这是坏的对话框。

在一个的ressource的情况下,是唯一与已经存在的,状态为409冲突似乎是适当的。如果创建一个用户成功,状态为201创建听起来是个不错的主意。

请注意,有很多更多的状态codeS,他们中的一些相关的HTTP协议(如DAV)的扩展,一些完全非标准化(如状态420增强你的平静,从Twitter的API)。看一看<一个href=\"http://en.wikipedia.org/wiki/List_of_HTTP_status_$c$cs\">http://en.wikipedia.org/wiki/List_of_HTTP_status_$c$cs看什么一直使用至今,并决定是否要使用合适的东西为你的错误情况。

从我的经验,很容易只需选择一个状态code和使用它,但它是很难做到一致并符合现行标准。

我就不会停下不过这里只是因为别人可能会抱怨。 :)做的RESTful接口权本身就是一项艰巨的任务,但更多的接口存在,更多的经验已经收集。

编辑:

关于版本:它被认为是不好的做法,把一个版本标记到URL,如下所示: example.com/api/v1/stuff 它将工作,但它是不是很好。

但是,第一件事情就是:请问你的客户指定他希望得到哪种类型的再presentation的,即他怎么决定是得到JSON或XML?答:随着接受头。他可以发送接受:应用/ JSON 对JSON和接受:应用程序/ XML 的XML。他甚至可以接受多种类型,它是服务器来决定什么,然后返回。

除非服务器的设计与资源的多个重presentation回答(JSON或XML,客户选择),确实没有客户端太多的选择。但它仍然是有客户端发送至少是应用/ JSON作为他唯一的选择,然后返回一个头内容类型一件好事:响应应用程序/ JSON 。这样一来,双方都让自己清楚他们希望对方看到喜欢的内容是什么。

现在的版本。如果你把版本到URL,您可以有效地创建不同的资源(v1和v2),但在现实中你只有一个资源(= URL)用不同的方法来访问它。当在请求和/或在响应中重新presentation这与当前版本不兼容的参数的断裂改变创建的API的新版本必须发生

所以,当你创建使用JSON的API,你不处理的通用JSON。您处理一个具体的JSON结构是某种独特的API。你可以,而且也应该在内容类型服务器发送表明这一点。 「卖方」推广是有这样的:内容类型:应用程序/ vnd.IAMVENDOR.MYAPI + JSON 将告诉世界,基本的数据结构是application / JSON,但它是你的公司和你的API,真正告诉期待哪种结构。而这正是该版本的API请求的用武之地:应用程序/ vnd.IAMVENDOR.MYAPI-V1 + JSON

因此​​,而不是把版本中的网址,您期望的客户端发送一个接受:应用/ vnd.IAMVENDOR.MYAPI-V1 + JSON 标题,你应用程序/ vnd.IAMVENDOR.MYAPI-V1 + JSON 还有:以内容类型响应。这确实改变不了什么了第一个版本,但让我们看看事情如何发展,当第2版的用武之地。

该URL的方式将创建一个完全不相关的一系列新资源。客户端将不知道是否 example.com/api/v2/stuff 是相同的资源 example.com/api/v1/stuff 。该客户端可能提供了一些资源与V1 API和他保存这些东西的URL。他应该如何升级所有这些资源至V2?资源一点也没有变,他们是一样的,那更改的唯一事情是,他们看在V2不同。

是的,服务器可以通过发送重定向到URL V2通知客户端。但重定向并不表示该客户机还具有对API的客户端部分进行升级。

在使用接受的版本标题,资源的URL是所有版本相同。客户决定使用版本1或2请求资源,服务器可能会这么好心,仍然回答版本1请求,版本1的反应,但是所有版本2请求与新版本闪亮2响应。

如果服务器无法回答到版本1的要求,他可以通过发送HTTP状态告诉客户端406不可接受(请求的资源只能生成内容不能接受根据发送的接受报头请求。)

客户端可以发送接受两个版本头在内,这使服务器与一个他最喜欢的,即智能客户端可以实现1版和第2响应,现在发送既作为接受头,并等待要升级服务器从版本1到2服务器将在每一个响应说无论是版本1或2,客户端可以采取相应的行动 - 他并不需要知道服务器版本升级的确切日期

要总结一下:对于具有有限的,也许内部,使用甚至有一个版本可能会矫枉过正一个非常基本的API。但你永远不知道这是否会成为一个真正的一年从现在开始。它始终是一个很好的主意,包括版本号为一个API。而对于这一点的最好的地方是,你的API是要使用MIME类型里面。检查单现有的版本应该是微不足道的,但你以后升级透明的选择,没有混淆现有的客户。

What are the best practices for returning HTTP status codes in RESTful API? I am using Laravel 4 for my PHP framework.

In the case of an error, should I use

return Response::json('User Exists', 401);

or

include flag for success

return Response::json([
    'success' => false,
    'data' => 'User Exists'],
    401
);

or

use 200 instead of 4xx, relying on success to determine if there is an error

return Response::json([
    'success' => false,
    'data' => 'User Exists'],
    200
);

And in the case of success and there is no need to return any data, do you still return anything?

PHP API Code

public function getCheckUniqueEmail() {
    // Check if Email already exist in table 'users'
    $uniqueEmail = checkIfEmailExists();

    // Return JSON Response
    if($uniqueEmail) {
        // Validation fail (user exists)
        return Response::json('User Exists', 401);
    } else {
        // Validation success
        // - Return anything?
    }
}

解决方案

When you look at the list of available HTTP status codes, you will at some point realize that there are plenty of them, but used alone they cannot really explain an error by itself.

So to answer your question, there are two parts. One is: How can your API communicate the reasons for an error and add useful information that the user of the API (which in most cases is another developer) can read and act upon. You should add as much information as possible, both machine readable and human readable.

The other part: How can HTTP status codes help in distinguish certain error (and success) states?

This latter part is actually harder than one might thing. There are the obvious cases where 404 is used to tell "not found". And 500 for any errors that are server-side.

I wouldn't use status 401, unless I really want to allow the operation to succeed if there are HTTP authentication credentials present. 401 usually triggers a dialog box in the browser, which is bad.

In case of a ressource being unique and already existing, status "409 Conflict" seems appropriate. And if creating a user succeeds, status "201 Created" sounds like a good idea, too.

Note that there are a lot more status codes, some of them related to extensions of the HTTP protocol (like DAV), some completely unstandardized (like status "420 Enhance your calm" from the Twitter API). Have a look at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes to see what has been used so far, and decide whether you want to use something appropriate for your error cases.

From my experience, it is easy to simply pick a status code and use it, but it is hard to do so consistently and in accordance with existing standards.

I wouldn't however stop here just because others might complain. :) Doing RESTful interfaces right is a hard task in itself, but the more interfaces exists, the more experience has been gathered.

Edit:

Regarding versioning: It is considered bad practice to put a version tag into the URL, like so: example.com/api/v1/stuff It will work, but it isn't nice.

But the first thing is: How does your client specify which kind of representation he wants to get, i.e. how can he decide to either get JSON or XML? Answer: With the Accept header. He could send Accept: application/json for JSON and Accept: application/xml for XML. He might even accept multiple types, and it is for the server to decide then what to return.

Unless the server is designed to answer with more than one representation of the resource (JSON or XML, client-selected), there really isn't much choice for the client. But it still is a good thing to have the client send at least "application/json" as his only choice and then return a header Content-type: application/json in response. This way, both sides make themselves clear about what they do expect the other side to see the content like.

Now for the versions. If you put the version into the URL, you effectively create different resources (v1 and v2), but in reality you have only one resource (= URL) with different methods to access it. Creating a new version of an API must take place when there is a breaking change in the parameters of a request and/or the representation in the response which is incompatible with the current version.

So when you create an API that uses JSON, you do not deal with generic JSON. You deal with a concrete JSON structure that is somehow unique to your API. You can and probably should indicate this in the Content-type sent by the server. The "vendor" extension is there for this: Content-type: application/vnd.IAMVENDOR.MYAPI+json will tell the world that the basic data structure is application/json, but it is your company and your API that really tells which structure to expect. And that's exactly where the version for the API request fits in: application/vnd.IAMVENDOR.MYAPI-v1+json.

So instead of putting the version in the URL, you expect the client to send an Accept: application/vnd.IAMVENDOR.MYAPI-v1+json header, and you respond with Content-type: application/vnd.IAMVENDOR.MYAPI-v1+json as well. This really changes nothing for the first version, but let's see how things develop when version 2 comes into play.

The URL approach will create a completely unrelated set of new resources. The client will wonder if example.com/api/v2/stuff is the same resource as example.com/api/v1/stuff. The client might have created some resources with the v1 API and he stored the URLs for this stuff. How is he supposed to upgrade all these resources to v2? The resources really have not changed, they are the same, the only thing that changed is that they look different in v2.

Yes, the server might notify the client by sending a redirect to the v2 URL. But a redirect does not signal that the client also has to upgrade the client part of the API.

When using an accept header with the version, the URL of the resource is the same for all versions. The client decides to request the resource with either version 1 or 2, and the server might be so kind and still answers version 1 requests with version 1 responses, but all version 2 requests with the new and shiny version 2 responses.

If the server is unable to answer to a version 1 request, he can tell the client by sending HTTP status "406 Not Acceptable" (The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.)

The client can send the accept header with both versions included, which enabled the server to respond with the one he likes most, i.e. a smart client might implement versions 1 and 2 and now sends both as accept header, and waits for the server to upgrade from version 1 to 2. The server will tell in every response whether it is version 1 or 2, and the client can act accordingly - he does not need to know the exact date of the server version upgrade.

To sum it up: For a very basic API with limited, maybe internal, usage even having a version might be overkill. But you never know if this will be true a year from now. It is always a very good idea to include a version number into an API. And the best spot for this is inside the mime type that your API is about to use. Checking for the single existing version should be trivial, but you have the option of transparently upgrading later, without confusing existing clients.

这篇关于在基于REST的API错误最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆