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"
}
}
}
现在假设我想通过 POST
ing 到 /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)。
总结一下,以下哪个选项最好?
- 直接使用id。
- 使用link,但解析出id。
- 使用link,但是访问link获取资源实例,然后获取id。
根据我的经验,最好使用最简单的请求解决方案。
生成一个新的 url 并解析它的过程对于获取资源来说似乎太过分了,而发送你想要的项目的 id 似乎要简单得多。
因此,我将以以下形式发送请求:
{
"name": "Batman",
"group": 1
}
您在这里遗漏了两件重要的事情。
- 您需要一种标准的方式来描述响应中的表单,在本例中是您的 POST 表单。
- 有关组 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 的令人信服的论据,这将击败上述内容。
假设我有一个名为 group
的资源,其表示形式如下:
{
"id": 1,
"name": "Superheroes"
"_links": {
"self": {
"href": "http://my.api.com/groups/1"
}
}
}
现在假设我想通过 POST
ing 到 /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)。
总结一下,以下哪个选项最好?
- 直接使用id。
- 使用link,但解析出id。
- 使用link,但是访问link获取资源实例,然后获取id。
根据我的经验,最好使用最简单的请求解决方案。
生成一个新的 url 并解析它的过程对于获取资源来说似乎太过分了,而发送你想要的项目的 id 似乎要简单得多。
因此,我将以以下形式发送请求:
{ "name": "Batman", "group": 1 }
您在这里遗漏了两件重要的事情。
- 您需要一种标准的方式来描述响应中的表单,在本例中是您的 POST 表单。
- 有关组 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 的令人信服的论据,这将击败上述内容。