在找不到REST资源时返回404是否正确?

car*_*ing 38 rest http-status-codes

假设我有一个简单的Jersey REST资源,如下所示:

@Path("/foos")
public class MyRestlet
        extends BaseRestlet
{

    @GET
    @Path("/{fooId}")
    @Produces(MediaType.APPLICATION_XML)
    public Response getFoo(@PathParam("fooId") final String fooId)
            throws IOException, ParseException
    {
        final Foo foo = fooService.getFoo(fooId);

        if (foo != null)
        {
            return Response.status(Response.Status.OK).entity(foo).build();
        }
        else
        {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

基于上面的代码,返回NOT_FOUNDstatus(404),或者我应该返回204,还是其他一些更合适的代码是正确的吗?

提前谢谢了!

Rob*_*Rob 55

在这种情况下,404响应是非常典型的,API用户可以轻松使用.

一个问题是客户很难判断他们是否因为未找到特定实体而得到404,或者由于URI中的结构问题.在您的示例中,/foos/5可能会返回404,因为id = 5的foo不存在.但是,/food/1即使foo id=1存在(因为foos拼写错误),也会返回404 .换句话说,404表示构造错误的URI或对不存在的资源的引用.

当您有一个引用多个资源的URI时,会出现另一个问题.通过简单的404响应,客户端不知道找不到哪个引用的资源.

通过在响应主体中返回附加信息可以部分地缓解这两个问题,以使调用者确切地知道未找到的内容.

  • @TimCastelijns我同意这是客户的错误.但是,如果客户是您的客户,那么它就成了您的问题(他们将拿起电话并打电话给某人).如果我们可以帮助客户使用API​​而不会遇到很多挫折,我们都会赢. (24认同)
  • @asiby 这个问题和答案的上下文是返回特定资源的端点,而不是集合。如果上下文是返回集合的端点,那么我同意应该返回空集合。 (4认同)
  • 我想补充说,在`/ food/1`返回404的情况下,因为该url不存在,这是一个客户端错误(他输入了错误的URL),因此不是你的问题 (3认同)
  • 如果您为客户提供了正确的API文档,那肯定是他们的错;-),但我明白了 (3认同)
  • 在某些情况下,出于某些原因,我希望使用204而不是404。对于操作人员来说,通常404会敲响警钟以进行进一步的调查,并且在许多用例中,只是资源尚未创建,因此尚无内容,因为多次成功调用DELETE,因此也多次使用(204)资源。204也清楚地指示将不返回任何正文,这对于需要考虑空响应的调用方(客户端)而言非常清楚。对于浏览器,404多次以红色显示,类似于错误,并以红色显示。 (2认同)
  • 恕我直言,当 API 端点应该返回资源集合时,您永远不应该引发 404 错误。如果未找到结果,则结果应该只是一个空列表。这是解释这种结果的最自然的方式。想象一下,如果每次您的搜索没有产生任何结果时,Google(或任何与此相关的搜索引擎)都会显示 404 错误。因此,当请求具有 URI 或类似内容的单个资源时,404 错误更合适。 (2认同)

Pau*_*tha 23

是的,对于未找到的资源,返回404是很常见的.就像一个网页,当它找不到时,你得到一个404.它不仅仅是REST,而是一个HTTP标准.

每个资源都应该有一个URL位置.URL不需要是静态的,它们可以是模板化的.因此,实际请求的URL可能没有资源.服务器有责任从模板中分解URL以查找资源.如果他们的资源不存在,那就是"找不到"

这是来自HTTP 1.1规范

404未找到

服务器未找到与Request-URI匹配的任何内容.没有说明该病症是暂时的还是永久性的.如果服务器通过一些内部可配置的机制知道旧资源永久不可用且没有转发地址,则应该使用410(Gone)状态代码.当服务器不希望确切地说明请求被拒绝的原因,或者没有其他响应适用时,通常会使用此状态代码.


这是204

204没有内容

服务器已完成请求但不需要返回实体主体,并且可能希望返回更新的元信息.响应可以包括实体标题形式的新的或更新的元信息,如果存在,应该与所请求的变体相关联.

如果客户端是用户代理,它不应该从导致请求发送的文档视图中更改它的文档视图.这种反应主要是为了允许操作发生而不引起改变到用户代理的活动文档视图的输入,尽管任何新的或更新的元信息应在用户代理的活动视图当前应用于该文档.

204响应绝不能包含消息体,因此总是在头字段之后的第一个空行终止.

通常在更新或创建表示时使用204,并且不需要发回响应主体.在POST的情况下,您可以仅发回新创建的资源的位置.就像是

@POST
@Path("/something")
@Consumes(...)
public Response createBuzz(Domain domain, @Context UriInfo uriInfo) {
    int domainId = // create domain and get created id
    UriBuilder builder = uriInfo.getAbsolutePathBuilder();
    builder.path(Integer.toString(domainId));  // concatenate the id.
    return Response.created(builder.build()).build();
}
Run Code Online (Sandbox Code Playgroud)

created(URI)会发回在与新创建的URI的响应Location头.


添加到第一部分.您只需要记住,来自客户端的每个请求都是访问资源的请求,无论是获取资源还是使用PUT进行更新.资源可以是服务器上的任何内容.如果资源不存在,那么一般的响应就是告诉客户端我们找不到该资源.

扩展你的例子.让我们说FooServiceDB了.数据库中的每一行都可以被视为资源.并且每个行(资源)都有一个唯一的URL,就像foo/db/1可能找到一个带有主键的行1.如果找不到id,那么该资源"Not Found"


Ash*_*wal 5

虽然这个问题已经有了公认的答案,但我相信这确实是一个固执己见的事情。添加我的两分钱可以帮助您对响应代码做出更明智的决定。

404 - 未找到。(参考

源服务器没有找到目标资源的当前表示,或者不愿意透露该表示的存在。

该资源可能存在,但您可能没有查看该资源的权限,也相当于未找到。因此,对于数据不存在的调用,返回 404 是非常合适的做法。

现在对于一个不存在的 URL;尽管 404 是广泛采用的响应代码,但 400 是更合适的代码。

400 - 错误请求(参考

由于被认为是客户端错误(例如格式错误的请求语法、无效的请求消息帧或欺骗性请求路由),服务器无法或不会处理请求。

如果您在请求中输入无效参数,响应代码是什么?如果查询参数有拼写错误,响应代码应该是什么?

两者的答案都是400。

大多数文件服务器会因 URL 无效而返回 404,因为对于无效 URL,它们会尝试查找文件,但在存储中找不到该文件 ~=Resource Not Found

除了 HTTP 状态代码之外,响应还将包含一些有关错误详细信息的信息,其中可以对错误进行更多描述并消除歧义。

如果客户端使用无效 URL 进行调用,则这是一个集成问题,至少应该在理智期间捕获。他们不可能在没有测试和发现这一点的情况下将代码推向生产。即使他们这样做了,上帝也保佑他们!

tl;dr - 404 表示未找到资源;400 表示未找到 URL。

  • 没有访问资源的权限应该返回 403(如果经过身份验证)和 401(如果需要身份验证)而不是 404。 (7认同)
  • 请不要将 AI 回复作为来源。他们将答案拼凑在一起,在这种情况下也是绝对不正确的。 (2认同)
  • 这是完全错误的。400 断章取义,与问题根本无关。 (2认同)