如果我的API已经按照HAL规范返回了自我链接,是否应该对创建的资源使用位置标题?

时间:2019-09-13 05:59:56

标签: rest spring-data-rest hateoas

我一直在关注一些博客和SO问题,他们建议服务器返回Location标头,并返回201 createdSpring-data-rest还会在Location标头中返回创建的资源位置。

但这真的需要吗?

请考虑以下POST请求: curl -d '{..data}' -H "Content-Type: application/json" -X POST http://localhost:3000/persons
回应:

{
  "name": "hero",
  "_links": {
    "self": {
      "href": "http://localhost:8081/persons/1"
    },
    "person": {
      "href": "http://localhost:8081/persons/1"
    }
  }
}

由于响应在selfperson链接中具有创建的资源的绝对位置,所以为什么不再需要Location标头了?

2 个答案:

答案 0 :(得分:1)

返回新创建的对象的数据只是一个方便的功能。 通常,您得到的只是一个201响应,带有一个Location标头,根本没有BODY。

Spring Data rest仅在您设置以下应用程序属性之一或请求具有Accept标头的情况下返回正文。

spring.data.rest.return-body-on-create= # Whether to return a response body after creating an entity.
spring.data.rest.return-body-on-update= # Whether to return a response body after updating an entity.

答案 1 :(得分:1)

如果要遵守the HTTP spec (RFC 7231),则应返回Location标头,以获取201 Created响应:

  

如果由于成功处理POST请求而在原始服务器上创建了一个或多个资源,则原始服务器应发送201(已创建)响应,该响应包含一个Location头字段,该字段为创建的主要资源提供标识符(第7.1.2节),以及在引用新资源时描述请求状态的表示形式。

某些客户端实现将在此类前提下运行,如果您违反HTTP规范,则它们可能无法与您的API正确交互。

此外,您必须区分某些特定于媒体类型的表示内容和某些常规的请求-响应元数据。 Location标头属于响应的元数据。不了解某种表示格式的客户端仍将知道服务器能够将内容存储在给定的URI中。

考虑到以下情况:任意客户端将数据发送到服务器,并且服务器以客户端无法理解的表示格式(允许服务器使用)存储该数据,客户端应如何确定数据的位置或将来检索数据?由于缺乏对返回的表示格式的了解,因此它无法处理响应,并且通过从标头中省略此类信息,客户端是瞎子,将无法轻松地再次请求此数据。通过引入表示中立的暗示,即每个行为良好的实现都应遵循客户端,至少可以理解这一点。它可能仍然无法正确处理响应有效负载,但它知道在相应位置有可用数据。

客户端和服务器应协商实际的媒体类型以交换消息,以增强互操作性。因此,媒体类型描述了可能出现在交换的消息中的元素的语法和语义,以及用于处理请求的规则集,即某些元素只能在某些条件下出现。仅仅交换application/json不会为客户端提供有关如何处理数据的大量信息,除了某些大括号形式的键值对中包含某些键值对之外。尽管hal+json为URI添加了语义,但是它没有指定用于返回创建的资源的密钥,因为HTTP规范已经涵盖了该密钥。

关于REST,您可以以Web为例说明如何设计客户端和服务器之间的交互流。这里的前提应该始终是服务器通过类似表单的表示格式和提供的链接来教客户下一步该做什么。 REST体系结构的最终目标是使客户端与服务器脱钩,从而使服务器将来可以自由发展而不会破坏客户端。但是,这需要仔细的设计,因为这样很容易引入意外的耦合。