laravel RESTful API 错误的最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15600307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best Practice for Errors in RESTful API
提问by Nyxynyx
What are the best practices for returning HTTP status codes in RESTful API? I am using Laravel 4 for my PHP framework.
在 RESTful API 中返回 HTTP 状态代码的最佳实践是什么?我的 PHP 框架使用 Laravel 4。
In the case of an error, should I use
在出现错误的情况下,我应该使用
return Response::json('User Exists', 401);
or
或者
include flag for success
包括标志 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
使用200代替4xx,依靠success
判断是否有错误
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
PHP API 代码
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?
}
}
回答by Sven
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.
当您查看可用的 HTTP 状态代码列表时,您有时会意识到它们很多,但单独使用它们本身并不能真正解释错误。
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.
所以要回答你的问题,有两个部分。一个是:您的 API 如何传达错误原因并添加 API 用户(在大多数情况下是另一位开发人员)可以阅读和采取行动的有用信息。您应该添加尽可能多的信息,包括机器可读和人类可读。
The other part: How can HTTP status codes help in distinguish certain error (and success) states?
另一部分:HTTP 状态代码如何帮助区分某些错误(和成功)状态?
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.
后一部分实际上比一件事情更难。在明显的情况下,404 用于告诉“未找到”。对于服务器端的任何错误,500。
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.
我不会使用状态 401,除非我真的希望在存在 HTTP 身份验证凭据的情况下允许操作成功。401 通常会在浏览器中触发一个对话框,这是不好的。
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.
如果资源是唯一的并且已经存在,状态“409 冲突”似乎是合适的。如果创建用户成功,状态“201 Created”听起来也是个好主意。
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_codesto see what has been used so far, and decide whether you want to use something appropriate for your error cases.
请注意,还有更多的状态代码,其中一些与 HTTP 协议的扩展有关(如 DAV),一些完全未标准化(如 Twitter API 中的状态“420 增强您的冷静”)。查看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes以了解到目前为止使用的内容,并决定是否要使用适合您的错误情况的内容。
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.
然而,我不会仅仅因为其他人可能会抱怨而停在这里。:) 做好 RESTful 接口本身就是一项艰巨的任务,但是接口越多,积累的经验就越多。
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.
关于版本控制:将版本标记放入 URL 被认为是不好的做法,如下所示:example.com/api/v1/stuff
它会工作,但并不好。
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.
但第一件事是:您的客户如何指定他想要获得哪种表示,即他如何决定获得 JSON 或 XML?答:带Accept
标题。他可以发送Accept: application/json
JSON 和Accept: application/xml
XML。他甚至可能接受多种类型,然后由服务器决定返回什么。
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.
除非服务器被设计为用一种以上的资源表示(JSON 或 XML,客户端选择)来回答,否则客户端真的没有太多选择。但是让客户端至少发送“application/json”作为他的唯一选择,然后返回一个标头Content-type: application/json
作为响应仍然是一件好事。通过这种方式,双方都清楚他们希望对方看到的内容是什么样的。
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.
现在是版本。如果您将版本放入 URL 中,您可以有效地创建不同的资源(v1 和 v2),但实际上您只有一种资源(= URL)可以使用不同的方法来访问它。当请求的参数和/或响应中的表示与当前版本不兼容时,必须创建新版本的 API。
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
.
因此,当您创建使用 JSON 的 API 时,您无需处理通用 JSON。您处理一个具体的 JSON 结构,该结构对您的 API 来说是独一无二的。您可以并且可能应该Content-type
在服务器发送的消息中指出这一点。“供应商”扩展用于此目的:Content-type: application/vnd.IAMVENDOR.MYAPI+json
将告诉全世界基本数据结构是 application/json,但真正告诉我们期望哪种结构的是您的公司和您的 API。这正是 API 请求的版本适合的地方: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.
因此,不是将版本放在 URL 中,而是希望客户端发送一个Accept: application/vnd.IAMVENDOR.MYAPI-v1+json
标头,并且您也响应Content-type: application/vnd.IAMVENDOR.MYAPI-v1+json
。这对于第一个版本确实没有任何改变,但是让我们看看当版本 2 开始发挥作用时事情会如何发展。
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.
URL 方法将创建一组完全不相关的新资源。客户端会想知道是否example.com/api/v2/stuff
与example.com/api/v1/stuff
. 客户端可能已经使用 v1 API 创建了一些资源,并且他存储了这些东西的 URL。他应该如何将所有这些资源升级到v2?资源真的没有变,它们是一样的,唯一改变的是它们在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.
是的,服务器可能会通过向 v2 URL 发送重定向来通知客户端。但是重定向并不表示客户端也必须升级 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.
使用带有版本的接受标头时,所有版本的资源 URL 都相同。客户端决定使用版本 1 或 2 请求资源,服务器可能非常友好并且仍然使用版本 1 响应来响应版本 1 请求,但是所有版本 2 请求都使用新的和闪亮的版本 2 响应。
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.)
如果服务器无法响应版本 1 的请求,他可以通过发送 HTTP 状态“406 Not Acceptable”来告诉客户端(根据请求中发送的 Accept 标头,请求的资源只能生成不可接受的内容。)
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.
客户端可以发送包含两个版本的接受头,这使得服务器可以用他最喜欢的一个响应,即智能客户端可能实现版本 1 和 2,现在将两者都作为接受头发送,并等待服务器升级从版本 1 到 2。服务器会在每个响应中告诉它是版本 1 还是版本 2,客户端可以相应地采取行动——他不需要知道服务器版本升级的确切日期。
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.
总结一下:对于一个非常基本的 API,可能是内部的,即使有一个版本也可能是过度使用。但你永远不知道一年后这是否会成为现实。在 API 中包含版本号总是一个很好的主意。最好的地方是在您的 API 即将使用的 MIME 类型中。检查单个现有版本应该是微不足道的,但您可以选择稍后透明升级,而不会混淆现有客户端。
回答by msurguy
I wouldn't use 200 status for everything. That just would be confusing.
我不会对所有事情都使用 200 状态。那只会令人困惑。
Jquery allows you to process different response codes differently, there are built in methods for that already so take advantage of using them in your apps and when your app grows you can provide that API for others to use too.
Jquery 允许您以不同的方式处理不同的响应代码,已经有内置的方法,因此请在您的应用程序中使用它们,当您的应用程序增长时,您也可以提供该 API 供其他人使用。
Edit: Also I highly recommend watching this talk about Laravel and API development:
编辑:此外,我强烈建议您观看有关 Laravel 和 API 开发的讨论:
回答by msulhas
There are some list of HTTP Status Code at Illuminate\Http\Response
that extend to Symfony\Component\HttpFoundation\Response
. You can use that in your class.
有一些Illuminate\Http\Response
扩展到Symfony\Component\HttpFoundation\Response
. 你可以在你的课堂上使用它。
For example:
例如:
use Illuminate\Http\Response as LaravelResponse;
...
return Response::json('User Exists', LaravelResponse::HTTP_CONFLICT);
It much more readable.
它更具可读性。