RESTful 在请求体中引用其他资源的方式

RESTful way of referencing other resources in the request body

假设我有一个名为 group 的资源,其表示形式如下:

{
    "id": 1,
    "name": "Superheroes"
    "_links": {
        "self": {
            "href": "http://my.api.com/groups/1"
        }
    }
}

现在假设我想通过 POSTing 到 /persons/1 创建一个新的 person 实例。我应该使用以下哪项作为请求正文:

使用 ID

{
    "name": "Batman",
    "groupId": 1
}

使用link

{
    "name": "Batman",
    "group": "http://my.api.com/groups/1"
}

使用第一种方法,当我保留 person 实例时,我直接访问 id 以查找相关资源或最终将 id 存储在数据库中。但是使用另一种方法,我要么必须从 URI 中提取 id,要么按照 link 加载相关资源,然后找出它的 id。我真的不想在数据库中存储 URI。

对于后一种选择,看到服务器控制着 URI 的结构,我可以从 link 中解析出 id 吗?跟随 link 回到服务器本身似乎很奇怪,看到此时我们已经可以直接访问信息(我们只需要 id)。

总结一下,以下哪个选项最好?

根据我的经验,最好使用最简单的请求解决方案。

生成一个新的 url 并解析它的过程对于获取资源来说似乎太过分了,而发送你想要的项目的 id 似乎要简单得多。

因此,我将以以下形式发送请求:

{ "name": "Batman", "group": 1 }

您在这里遗漏了两件重要的事情。

  1. 您需要一种标准的方式来描述响应中的表单,在本例中是您的 POST 表单。
  2. 有关组 ids/uris 的信息,或如何获取它们,必须以标准方式在表单中描述。

例如,带有 SELECT 输入的 HTML 表单将是 RESTful。我们在 json 中最接近做同样事情的是 json-ld 和 hydra。但如果你对 hal 很着迷,那么使用 hyperagent forms 或类似的东西。它永远不会成为标准,但如果兼容性不是问题,那就足够了。

要回答你的问题,你应该使用id,因为服务器知道如何解释它。客户端需要资源标识符,服务器只需要在请求的 uri 部分,而不是正文。

TL;DR:使用简单的 ID。

更详细的解释:

一种直接的方法是通过 POSTing 到 /groups/1/persons 和负载 {"name": "Batman"}.

创建一个人

然而,虽然这种方法适用于简单的情况,但如果需要引用 2 个资源,情况就会变得复杂。假设一个人也需要属于一家公司:

GET /persons/1
{
   "name": "Batman",
   "group": 1,    // Superheros, available at /groups/1
   "company": 5  // Wayne Enterprises, available at /companies/5
}

由于公司和团体之间没有关系,因此通过 POSTing 到 /groups/1/companies/5/persons/companies/5/groups/1/persons 创建一个人在语义上是不正确的。

因此,假设您想创建一个具有如下请求的人员:

POST /persons
{
    "name": "Batman"
    "group": ???,     // <--- What to put here?
    "company": ???    // <--- What to put here?
}

这让我们得到了您问题的答案:

易于使用。您的 API 应该主要设计为易于使用。如果您设计 public API,则尤其如此。因此,选项 2(使用 link,但解析出 id)已被淘汰,因为它为您的 API.

的客户增加了额外的工作量

构造搜索查询。如果您希望能够查询属于公司 10 和组 42 的人员,简单的 ids 引导提高可读性和不易出错的 urls。您认为以下哪项更具可读性?

  • URL 带有一个简单的 id:

    GET /groups/42?company=10

  • 或 URL 与 url-encoded link:

    GET /groups/42?company=http%3A%2F%2Fmy.api.com%2Fcompanies%2F10

我不会低估可读性的重要性。您需要在各种 curls、日志、邮递员等中调试您的 API 多少次

开发链接需要在后台解析,简单的ids可以直接使用。这与性能无关,而与您必须投入的额外 work/tests 有关。

端点维护。想象一下,您的 API 端点在进化。您决定有一天切换到 https 或在 url 中包含版本控制。这可能会破坏 API 客户端,如果它们出于某种原因依赖于 link 的结构。此外,您可能需要检查后端的 link 解析是否正确完成。

argumentum ab auctoritate 我知道这不是一个合适的论点,但如果你检查 APIs 大玩家,例如Twitter、Github 或 Stripe,它们都使用简单的 ID。

HATEOAS。 支持 link 的一个常见论据是它与 HATEOAS 对齐。但是,据我所知,这与 API 响应中的附加 link 相关,而不是在 POST 请求的有效负载中使用 link。

总而言之,我会选择简单的 ID,因为我还没有听到支持 links 的令人信服的论据,这将击败上述内容。