【问题标题】:Resource and Action URI convention for RESTREST 的资源和操作 URI 约定
【发布时间】:2018-05-28 01:20:35
【问题描述】:

我正处于开发一些 REST API 的十字路口,我发现没有关于这个主题的真正讨论,更不用说对任何一个的坚定辩护了。

据我了解,使用 REST,您的 URL 为 /<resource>/<action>

因此,要禁用用户,您将拥有:

PUT /user/disable

看起来很合理。但是,我们正在讨论更基本的方法:

应该是:

POST /user  (creates a user *implicitly*)
POST /user/create (creates a user *explicitly*)

DELETE /user/:id
DELETE /user/:id/delete

第一个似乎被认为是“标准”,第二个显然在意图上更加清晰,并且与 /user/disable 等方法一致

也许这场辩论已经在其他地方肆虐,但我还没有看到。如果你对此持“宗教信仰”,那么现在是你自尊的机会

【问题讨论】:

  • 我会说PUT /user/12 并发送disabled=1。我认为这更像是一种宗教的东西(适合论坛),而不是有一个答案的东西(适合 SO)。投票结束,认为没有建设性。
  • 我建议是明确的(例如/user/create)。这是自我记录,而不需要为用户解释或反复试验。在 DELETE 情况下,删除方法是不言自明的,因此 url 不需要包含它。如果您使用 POST,则相反,POST /user/:id/delete 将是必不可少的。

标签: http rest


【解决方案1】:

/<resource>/<action> 作为您的 URL 不是 REST。 REST 使用 HTTP 动词来确定要对给定资源或资源集合执行的操作。这意味着:

  • 创建资源是:POST /users
  • 读取资源是:GET /users/<id>
  • 更新(实际替换)资源是:PUT /users/<id>
  • 删除资源是:DELETE /users/<id>

这就是 REST。

对于所有其他方法,您可以使用其他动词,例如PATCH。禁用用户可能是:

PATCH /users/<id>/disable

这不是纯 REST,但没关系。

编辑:如果你想符合 REST,禁用用户意味着你想改变他的状态。换句话说,您想更改其属性之一,例如state 标志。您可以“修补”您的资源:

PATCH /users/<id>?state=disabled

这是 REST。您还可以按照 cmets 中的说明使用 PUT 替换资源。

【讨论】:

  • 详细说明:要制作真正的 REST,而不是在 URI 中包含操作(“禁用”),您应该发送一个 PUT 请求,将资源“禁用”字段切换为 True,1 ,或任何你用来表示的东西。在做 REST 时,您应该始终考虑“一个操作如何改变我的资源?”如果操作过于复杂而无法简单地更改资源,或者包含许多资源,那么 REST 不是最好的方法。
  • 是的。哦,你可以发送一个 PATCH 请求,其中只有“禁用”字段(false -> true)的差异,而不是使用 PUT 的完整资源。
  • @WilliamDURAND 您明确表示 /// 范式不是 REST,然后说使用 PATCH 后跟“这不是纯 REST,但没关系”。我试图了解这 2 个声明是如何融合的。我在这里没有声称自己是 REST 专家,我喜欢使用 PATCH 的想法(我读到的关于它的内容似乎表明这是一个合适的用途)。我觉得 REST+WS 仍在进行中。此外,REST 和 OO 编程语言之间存在范式冲突,它们希望将数据表示为对象并将 URL 映射到函数/操作 欣赏输入。谢谢
  • @BerislavLopac 所以,你说的是 PUT /user body: { "id":"123", "status":"disabled" } 这比 "PUT /user/123/禁用”?它在功能上是相同的,没有接受有效载荷主体的编程不便。请参阅我关于碰撞范式的评论
  • @Christian Bongorno:不,不完全是。您会看到,REST 的重点是资源,这些资源由 URI 唯一标识。因此,在这种情况下,URI 将不是 /user,而是 /user/123,并且正文将包含处于新状态的所有字段(其中之一是“状态”)。您可以使用 PATCH 而不是 PUT 来仅更新一个字段,但这还没有被 HTTP 协议正式认可。
【解决方案2】:

@Christian Bongiorno

您正在对与 REST 无关的 URI 中的操作进行编码。它是最清晰的 RPC 形式。

您需要使用在您使用的底层协议中定义的方法(即您的情况下的 HTTP)来识别资源并对这些资源执行操作。 HTTP 规范为这些方法定义了语义,因此您必须执行以下操作,而不是直接在 URI 中编码操作:

  • GET /users - 返回用户列表(每个条目/项目都有自己指向特定用户的链接)
  • GET /users/:id - 返回特定用户
  • POST /users - 在 /users 资源下创建新用户
  • POST /users/:id - 编辑用户(这里也可以使用 PATCH 方法)
  • PUT /users/:id - 替换用户
  • DELETE /users/:id - 删除用户

这就是你应该如何看待行动。但这还不够,您需要使用支持超媒体控件(如链接)的媒体格式(至少)以便能够描述这些操作,例如:

一些快速交互示例:

***Request***
GET /users HTTP/1.1
Host: service.org
Accept: application/x+json

***Response***
HTTP/1.1 200 OK
Content-Type: application/x+json
Content-Length: ...

[{
  "name": "john",
  "links": {
    "self": "/users/1",
    "edit": "/users/1"
  }
}, {
  "name": "jane",
  "links": {
    "self": "/users/2",
    "edit": "/users/2"
  }
}]

***Request***
GET /users/2 HTTP/1.1
Host: service.org
Accept: application/x+json

***Response***
HTTP/1.1 200 OK
Content-Type: application/x+json
Content-Length: ...
{
  "name": "jane",
  "links": {
    "self": "/users/2",
    "edit": "/users/2"
  }
}

***Request***
DELETE /users/2 HTTP/1.1
Host: service.org

***Response***
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: ...

Resource was destroyed...

***Request***
POST /users/2 HTTP/1.1
Host: service.org
Content-Type: application/x+json
Content-Lenght: ...

{"status": "disabled"}

***Response***
HTTP/1.1 303 See Other
Location: /users/2

【讨论】:

  • 阅读并查看了您发送的链接(其中一个 RFC 是一周前的)我确信几件事:1)如何使用 REST/HTTP 进行全机交互是 WIP 2 ) REST 描述了可能不适合或超出您的需求范围的方法和范式 3) 使用 REST 和使用流行的编程语言实现所述状态转移之间存在非常明显的范式冲突。 4) 为 m2m 和 h2m 设计 API 需要大量权衡考虑(当这是严格编译的代码时,它从来不是问题)感谢输入。谢谢
  • 好的 -------------------------------
【解决方案3】:

在您的 URL 中执行操作不是 REST。

我解决这个问题的方法是定义一个动作子资源​​。

你可以这样做:

POST /users/123/actions

请求正文为 json:

{ "type": "reset_password", "current_password": "mypassword", "new_password": "$myNewPass2#" }

【讨论】:

    猜你喜欢
    • 2019-12-29
    • 2022-07-29
    • 2016-07-21
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多