RESTful服务中的自定义更新操作

时间:2019-03-20 15:43:05

标签: node.js rest

我的API需要许多不同类型的更新,这些更新可以由不同类型的角色执行。票证可以更新其数据,票证可以被批准(包括一些信息),票证可以被拒绝,票证可以被存档(导致票证无法更新的状态)等。

我最近开始以后端开发人员的身份工作,我真的不知道哪种方法最适合这种情况,但是我有两个想法:

  • 单个更新终结点(例如/api/tickets/:id)接受具有要对该文件执行的更新类型的操作字段;
  • 多个自定义操作端点(例如/api/tickets/:id/validate/api/tickets/:id/accept等)

在涉及REST体系结构时,哪种方法是解决这种情况的最佳方法?如果在REST方面都不正确,那么最正确的方法是什么?我在SO上找不到任何可以回答我问题的帖子,因此我决定创建自己的帖子。谢谢!

4 个答案:

答案 0 :(得分:1)

尝试之一

  • 处理单个对象-> api/v1/tickets/1
  • 处理对象列表-> api/v1/tickets/

然后尝试将所有操作捕获为CRUD操作。

  • 创建对象-> HTTP POST
  • 回溯对象-> HTTP GET
  • 更新对象-> HTTP PATCH
  • 删除对象-> HTTP DELETE

还有:

  • 完全保存对象-> HTTP PUT

更改状态时,这些只是故障单上的属性。例如,我将发送一个PATCH请求。如果我需要将票证#1的雕像更改为“已拒绝”,我将发送诸如PATCH api/v1/tickets/1之类的有效载荷,如:

{
    "status": "rejected"
}

REST有很多最佳实践,但并非所有事情都是一成不变的。也许本教程:https://restfulapi.net能为您提供帮助吗?

答案 1 :(得分:1)

REST都是关于资源的。在客户端和服务器之间的无状态通信的顶部,应该使用表示形式(例如JSON,XML,您为其命名)来操纵资源的状态。

一旦URI用于标识资源,就应该在URI中使用名词代替动词。并且在通过HTTP协议设计REST API时,应使用HTTP方法来指示打算对资源执行的操作。

执行部分更新

您可以使用PATCH HTTP动词对资源进行部分更新。 PATCH请求有效负载必须包含要应用于资源的一组更改。

有两种格式可用于描述要应用于资源的一组更改:

JSON合并补丁

它在RFC 7396中定义,可以按如下所述应用:

  

如果提供的合并修补程序包含目标中未出现的成员,则会添加这些成员。如果目标确实包含该成员,则将替换该值。合并补丁中的Null值具有特殊含义,表示已删除目标中的现有值。

因此,修改票证status的请求可能类似于:

PATCH /api/tickets/1 HTTP/1.1
Host: example.org
Content-Type: application/merge-patch+json

{
  "status": "valid"
}

JSON补丁

它是在RFC 6902中定义的,表示要应用于目标JSON文档的一系列操作。修改票证status的请求可能类似于:

PATCH /api/tickets/1 HTTP/1.1
Host: example.org
Content-Type: application/json-patch+json

[
  {
    "op": "replace",
    "path": "/status",
    "value": "valid"
  }
]

path是JSON指针值,如RFC 6901中所述。

答案 2 :(得分:1)

REST代表代表状态转移,这意味着客户端和服务器通过交换资源的代表来影响彼此的状态。

客户可能GET表示票证,如下所示:

GET /api/tickets/123 HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": 123, 
    "state": "new",
    "archived": false,
    "comments": []
}

现在,客户可以PUT进行新的表示(批量替换)或PATCH现有的特定部分:

PATCH /api/tickets/123 HTTP/1.1
Content-Type: application/json-patch+json

[
    {"op": "replace", "path": "/state", "value": "approved"},
    {"op": "add", "path": "/comments", "value": {
        "text": "Looks good to me!"
    }}
]


HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": 123,
    "state": "approved",
    "archived": false,
    "comments": [
        {"author": "Thomas", "text": "Looks good to me!"}
    ]
}

请注意,如何使用标准JSON Patch格式以要在JSON表示形式中更改的内容来表示更新。客户端可以使用相同的方法来更新JSON中表示的任何资源。这有助于uniform interface,将客户端与特定服务器分离。

当然,服务器不需要支持任意更新:

PATCH /api/tickets/123 HTTP/1.1
Content-Type: application/json-patch+json

[
    {"op": "replace", "path": "/id", "value": 456}
]


HTTP/1.1 422 Unprocessable Entity
Content-Type: text/plain

Cannot replace /id.

不过,与“批准”,“拒绝”等专用操作相比,这可能在服务器上需要更多的复杂性。您可能想使用a library来实现JSON补丁。如果您发现需要许多难以表达的自定义操作,那么RPC体系结构可能比REST更适合您。

答案 3 :(得分:1)

真的,这全都取决于口味。在行业中,通常会在URL中使用静态参数(例如:/tickets/update/users/add/admin/accounts)和可变参数在查询中(例如ID,消息,名称)。它允许具有固定数量的端点。

我看到您正在使用NodeJS,因此您可能正在使用Express,在Express中,获取url参数和body参数同样容易:

// supposing you're using a JSON-based API with body-parser for JSON parsing
app.get('/some/path/:someParam', (req, res) => {
    console.log(req.params.someParam);
    console.log(req.body.someOtherParam);
    res.send();
}