首页 > 解决方案 > 如果我的 API 已经按照 HAL 规范返回自链接,我应该为创建的资源使用位置标头吗?

问题描述

我正在关注一些博客和 SO 问题,他们建议Location服务器返回一个带有201 created响应的标头。Spring-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不再需要标头?

标签: restspring-data-resthateoas

解决方案


如果您想符合HTTP 规范 (RFC 7231),您应该返回一个响应Location头:201 Created

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

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

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

想一想任意客户端向服务器发送数据并且服务器以客户端不理解的表示格式(允许服务器)存储该数据的场景,客户端应该如何确定数据的位置或检索未来的数据?由于缺乏关于返回的表示格式的知识,并且通过从标头中省略此类信息,客户端是盲目的并且无法轻松地再次请求此数据,因此它无法处理响应。通过引入一个表示中立的提示,即每个表现良好的实现都应该遵循客户端,至少可以理解这一点。它可能仍然无法正确处理响应负载,但它知道数据在相应位置可用。

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

关于 REST,你可以以 Web 为例,介绍如何设计客户端和服务器之间的交互流程。这里的前提应该始终是服务器通过类似表单的表示格式和提供的链接来指导客户端下一步可以做什么。REST 架构的最终目标是将客户端与服务器解耦,从而允许后者在未来自由发展而不会破坏客户端。然而,这需要仔细设计,因为它很容易引入意外的耦合。


推荐阅读