REST检查资源是否存在,如何在服务器端处理?

时间:2018-06-12 11:17:26

标签: rest

如何处理服务器端的资源检查? 例如,我的api看起来像:

/books/{id}

谷歌搜索后我发现,如果资源存在,我应该使用HEAD方法来检查。 https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

我知道,我可以使用GET端点并使用HEAD方法获取有关资源的信息,在这种情况下服务器不返回正文。

但是我应该在服务器端做什么? 我有两个选择。

  1. 一个标记为GET的端点。我这个端点我可以使用GET方法获取数据,HEAD来检查资源是否可用。

  2. 两个端点。一个标记为GET,第二个标记为HEAD。

  3. 为什么我在考虑第二种解决方案? 让我们假设,GET请求从数据库中获取一些数据并以某种方式处理它们,这需要一些时间,例如。 10毫秒

    但我真正需要的只是检查数据库中是否存在数据。所以我可以运行像

    这样的查询
    select count(*) from BOOK where id = :id
    

    如果查询结果等于1,则立即返回状态200.在这种情况下,我不需要处理数据,因此我的响应时间更快。

    但是...... REST中的资源是一个通过HTTP传输的对象,所以也许我应该处理数据但是当我使用HEAD方法时不返回它们?

    提前感谢您的回答!

3 个答案:

答案 0 :(得分:1)

您可以简单地将HEAD处理程序委派给现有的GET处理程序,并仅返回状态代码和标头(忽略响应有效负载)。

这就是一些框架,如Spring MVC和JAX-RS。

请参阅Spring MVC documentation中的以下引用:

  

@GetMapping - 以及@RequestMapping(method=HttpMethod.GET)隐式映射到并支持HTTP HEAD。 HTTP HEAD请求被处理,就像它是HTTP GET一样,但不是写入正文,而是计算字节数,并且“   Content-Length标题集。

     

[...]

     

@RequestMapping方法可以显式映射到HTTP HEAD和HTTP OPTIONS,但在常见情况下这不是必需的。

请参阅JAX-RS documentation中的以下引用:

  

HEADOPTIONS请求会获得额外的自动支持。收到HEAD请求后,实现必须:

     
      
  1. 调用使用HEAD的请求方法指示符注释的方法,如果不存在,则调用
  2.   
  3. 调用使用GET的请求方法指示符注释的方法,并丢弃任何返回的实体。
  4.         

    请注意,在实体创建很重要的情况下,选项2可能会导致性能下降。

注意:不要再使用旧的RFC 2616作为参考。它被一组新的RFC废弃:7230-7235。有关HTTP协议的语义,请参阅RFC 7231

答案 1 :(得分:0)

端点应该相同,服务器端脚本应根据方法决定做什么。如果method是HEAD,那么只需返回合适的HTTP代码:

  • 204如果内容存在但服务器没有返回
  • 404如果不存在
  • 其他错误
  • 4xx5xx

如果方法是GET,则处理请求并使用HTTP代码返回内容:

  • 200如果内容存在且服务器返回
  • 404如果不存在
  • 其他错误
  • 4xx5xx

重要的是URL应该是相同的,只是方法应该是不同的。如果URL不同,那么我们将讨论REST上下文中的不同资源。

答案 2 :(得分:0)

您对HTTP方法的引用已过时;你应该引用RFC 7231, section 4.3.2

  

HEAD方法与GET相同,只是服务器不能在响应中发送消息体(即响应终止于标题部分的末尾)。

     

此方法可用于获取有关所选表示的元数据,而无需传输表示数据,并且通常用于测试超文本链接的有效性,可访问性和最近的修改。

你问:

  REST中的

资源是一个通过HTTP传输的对象,所以也许我应该处理数据但是当我使用HEAD方法时不返回它们?

这是正确的 - GETHEAD之间的主要区别在于服务器是否作为响应的一部分返回消息正文。

  

但我真正需要的只是检查数据库中是否存在数据。

我的建议是使用 new 资源。 "资源"是关于使您的数据库看起来像一个网站。在REST中,许多 URI映射到使用相同谓词的查询是完全正常的。

Jim Webber这样说:

  

网络不是您的域名,它是一个文档管理系统。所有HTTP谓词都适用于文档管理域。 URI不会映射到域对象 - 这违反了封装。工作(例如:向域模型发出命令)是管理资源的副作用。换句话说,资源是反腐败层的一部分。您应该希望集成域中的资源比业务域中的业务对象多得多。