Bri*_*acy 190 rest web-services http
我正在构建REST API,但我遇到了一个问题.
似乎在设计REST API时接受的做法是,如果请求的资源不存在,则返回404.
但是,对我来说,这增加了不必要的模糊性.传统上,HTTP 404与错误的URI相关联.所以实际上我们说"要么你到了正确的地方,但那个特定的记录不存在,或者互联网上没有这样的位置!我真的不确定哪一个......"
考虑以下URI:
http://mywebsite/api/user/13
Run Code Online (Sandbox Code Playgroud)
如果我得到404,那是因为用户13不存在吗?或者是因为我的网址应该是:
http://mywebsite/restapi/user/13
Run Code Online (Sandbox Code Playgroud)
过去,HTTP 200 OK如果记录不存在,我只返回带有响应代码的NULL结果.它很简单,在我看来非常干净,即使它不一定是公认的做法.但是有更好的方法吗?
Rob*_*evy 83
404只是HTTP响应代码.最重要的是,您可以提供响应正文和/或其他标题,其中包含开发人员将看到的更有意义的错误消息.
nat*_*ood 49
404如果资源不存在,请使用.不要200带空身回来.
这类似于编程中的undefinedvs空字符串(例如"").虽然非常相似,但肯定存在差异.
404表示该URI不存在任何内容(如编程中的未定义变量).200用空体返回意味着那里确实存在某些东西,而现在某些东西就是空的(就像编程中的空字符串一样).
404并不意味着它是一个"糟糕的URI".有一些特殊的HTTP代码用于URI错误(例如414 Request-URI Too Long).
jhe*_*cks 19
和大多数事情一样,"它取决于".但对我来说,你的实践并不差,并且不违反HTTP规范本身.但是,让我们清楚一些事情.
首先,URI应该是不透明的.即使它们对人不透明,它们对机器也是不透明的.换句话说,之间的差异http://mywebsite/api/user/13,http://mywebsite/restapi/user/13是相同的之间的差http://mywebsite/api/user/13和http://mywebsite/api/user/14,即不一样是不一样的周期.所以404将完全适合http://mywebsite/api/user/14(如果没有这样的用户)但不一定是唯一适当的响应.
您还可以返回空200响应或更明确地返回204(无内容)响应.这会向客户传达别的东西.这意味着所识别的资源http://mywebsite/api/user/14没有内容或基本上没有.它的意思是有是这样的资源.但是,它并不一定意味着您声称在ID为14的数据存储中存在一些用户.这是您的私人关注点,而不是发出请求的客户端的关注点.因此,如果以这种方式对资源进行建模是有意义的,那就继续吧.
为您的客户提供信息会使他们更容易猜出合法的URI,这会带来一些安全隐患.在未命中而不是404时返回200可以给客户一个至少http://mywebsite/api/user部分是正确的线索.恶意客户端可以继续尝试不同的整数.但对我来说,恶意客户端http://mywebsite/api/user无论如何都能猜到这个部分.更好的补救措施是使用UUID.即http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66好于http://mywebsite/api/user/14.这样做,你可以使用你的技术返回200,而不会给予太多.
小智 11
404 Not Found在技术上意味着uri当前未映射到资源.在您的示例中,我将请求解释为http://mywebsite/api/user/13返回404以暗示此URL 从未映射到资源.对客户来说,这应该是对话的结束.
要解决模棱两可的问题,您可以通过提供其他响应代码来增强API.例如,假设您希望允许客户端向URL发出GET请求http://mywebsite/api/user/13,您希望传达客户端应使用规范URL http://mywebsite/restapi/user/13.在这种情况下,您可能需要考虑通过返回301 Moved Permanently来发出永久重定向,并在响应的Location标头中提供规范URL .这告诉客户端,对于将来的请求,他们应该使用规范URL.
Sim*_*per 10
这是我们团队最近提出的。我们将两者404 Not found与消息正文一起使用并204 No Content基于以下原理。
如果请求 URI 指示单个资源的位置,我们使用 404 未找到。当请求查询 URI 时,我们使用 204 No Content
http://mywebsite/api/user/13当用户 13 不存在时将返回 404http://mywebsite/api/users?id=13将返回 204 无内容http://mywebsite/api/users?firstname=test将返回 204 无内容这里的想法是,“查询路由”预计能够返回 1、很多或没有内容。
无论您选择哪种模式,最重要的是保持一致- 因此请获得您团队的支持。
小智 8
所以从本质上讲,听起来答案可能取决于请求的形成方式.
如果所请求的资源根据请求形成URI的一部分http://mywebsite/restapi/user/13并且用户13不存在,那么404可能是适当且直观的,因为URI代表不存在的用户/实体/文档/等.对于使用上面的GUID http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66和api/restapi参数的更安全的技术也是如此.
但是,如果请求的资源ID包含在请求标头中[包括您自己的示例],或者实际上,在URI中作为参数,例如,http://mywebsite/restapi/user/?UID=13那么URI仍然是正确的(因为USER的概念确实退出http://mywebsite/restapi/user/); 因此,可以合理地预期响应为200(具有适当详细的消息),因为称为13的特定用户不存在但URI存在.这样我们就说URI很好,但是对数据的请求没有内容.
就个人而言,200仍然感觉不对(虽然我以前认为它确实如此).例如,当发送不正确的ID时,200响应代码(没有详细响应)可能导致不调查问题.
更好的方法是发送204 - No Content回复.这符合w3c的描述*服务器已经完成了请求但不需要返回实体主体,并且可能想要返回更新的元信息.*1在我看来,混淆是由维基百科条目引起的204 No Content - 服务器成功处理了请求,但未返回任何内容.通常用作对成功删除请求的响应.最后一句话是高度辩论的.考虑没有那句话的情况,解决方案很简单 - 如果实体不存在,只需发送204.甚至有一个参数返回204而不是404,请求已被处理,并且没有返回任何内容!请注意,204不允许回复正文中的内容
来源
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
这篇古老而优秀的文章...... http://www.infoq.com/articles/webber-rest-workflow说到这个......
404 Not Found - 服务太懒(或安全),无法给我们一个真正的原因,我们的请求失败了,但无论什么原因,我们都需要处理它.
这是一个非常古老的帖子,但我遇到了类似的问题,我想与你们分享我的经验.
我正在使用其他API构建微服务架构.我有一些休息的GET服务,它们根据请求参数从后端系统收集数据.
我遵循了其余的API设计文档,当没有与查询条件对齐的数据时(例如,选择了零记录),我向客户端发送了带有完美JSON错误消息的HTTP 404.
当没有数据发送回客户端时,我准备了一个带有内部错误代码等的完美JSON消息,以通知客户端"未找到"的原因,并通过HTTP 404将其发送回客户端.工作良好.
后来我创建了一个rest API客户端类,它是一个隐藏HTTP通信相关代码的简单帮助器,当我从代码中调用其余的API时,我一直使用这个帮助器.
但是我需要编写令人困惑的额外代码,因为HTTP 404有两个不同的功能:
重要提示:我的rest API错误处理程序捕获后端服务中出现的所有异常,这意味着如果出现任何错误,我的rest API将始终返回带有消息详细信息的完美JSON消息.
这是我的客户端帮助程序方法的第一个版本,它处理两个不同的HTTP 404响应:
public static String getSomething(final String uuid) {
String serviceUrl = getServiceUrl();
String path = "user/" + , uuid);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_UTF8)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
// HTTP 200
return response.readEntity(String.class);
} else {
// confusing code comes here just because
// I need to decide the type of HTTP 404...
// trying to parse response body
try {
String responseBody = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(responseBody, ErrorInfo.class);
// re-throw the original exception
throw new MyException(errorInfo);
} catch (IOException e) {
// this is a real HTTP 404
throw new ServiceUnavailableError(response, requestUrl, httpMethod);
}
// this exception will never be thrown
throw new Exception("UNEXPECTED ERRORS, BETTER IF YOU DO NOT SEE IT IN THE LOG");
}
Run Code Online (Sandbox Code Playgroud)
但是,因为我的Java或JavaScript客户端可以以某种方式接收两种HTTP 404,我需要在HTTP 404的情况下检查响应的主体.如果我可以解析响应主体,那么我确信我回复了有响应的地方没有数据要发送回客户端.
如果我无法解析响应,这意味着我从Web服务器(而不是其他API应用程序)获得了真正的HTTP 404.
它是如此令人困惑,客户端应用程序总是需要额外的解析来检查HTTP 404的真正原因.
老实说,我不喜欢这个解决方案.这很令人困惑,需要一直向客户添加额外的废话代码.
因此,在这两种不同的场景中我没有使用HTTP 404,而是决定我将执行以下操作:
在这种情况下,客户端代码可以更优雅:
public static String getString(final String processId, final String key) {
String serviceUrl = getServiceUrl();
String path = String.format("key/%s", key);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
log(requestUrl);
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_JSON_UTF8)
.header(CustomHttpHeader.PROCESS_ID, processId)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return response.readEntity(String.class);
} else {
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(body, ErrorInfo.class);
throw new MyException(errorInfo);
}
throw new AnyServerError(response, requestUrl, httpMethod);
}
Run Code Online (Sandbox Code Playgroud)
我认为这可以更好地处理这个问题.
如果您有更好的解决方案,请与我们分享.
| 归档时间: |
|
| 查看次数: |
182344 次 |
| 最近记录: |