针对非 CRUD 操作的 REST API 设计,例如保存、部署、执行代码

问题描述 投票:0回答:3
我的 REST API 上下文中的资源是用某种编程语言编写的应用程序代码。可以轻松映射到 HTTP 动词的 CRUD 操作是保存/编辑/删除代码。难以映射到 HTTP 方法的非 CRUD 操作是在服务器上部署代码、执行代码和取消部署。

我在 SO 中遇到的常见建议是:

重构操作,使其看起来像资源的字段,例如如果您的操作是启动引擎,请设计 URI:

PATCH engines/123
    ,正文:
  1. {"status":"active"}
    
    
    将操作视为子资源,例如
    PUT engines/123/active
  2. 没有身体
  3. 使用查询参数,例如
    PUT engines/123?activate=true
  4. 务实一点,选择非 RESTful、RPC 风格的 URL,例如
    PUT engines/activate?id=123
  5. 
    
    我绝对无法按照 #1 和 #2 中的建议将
  6. deploy
/

undeploy

/
execute
 代码操作适合资源。您能否分享您的意见,我们如何才能最好地为这些操作设计 API?
	

rest
3个回答
15
投票

创建/更新/删除

信息资源
,其副作用是在 API 后面进行工作。

所以思考文档。

一个非常好的例子:在

RESTful Casuistry

中,Tim Bray 询问了一个用于关闭机器的 api。

Seth Ladd 的回应,尤其值得阅读 从根本上来说,REST 是一个通过文书工作解决问题的官僚机构。 如果您想完成任何事情,请提交正确的表格;这将成为描述您想要做什么的信息资源。

PUT /deploymentRequests/abcde Please find the artifacts from build 12345 and deploy that artifact to machine 67890 201 Created

请求只是一个文档,就像办公桌上要求您解决某些任务的便签也是一个文档一样。
就 REST 而言,URI 的拼写绝对不重要;但从人类可读的命名约定的角度来看,从资源就是文档这一事实开始——而不是您希望文档具有的副作用。

因此,例如,描述事物当前状态的文档和描述您想要对事物进行更改的文档是具有不同标识符的

不同文档

,这是完全正常且符合 REST 的。

我认为您正在寻找控制器,根据

12
投票

控制器资源对程序概念进行建模。 控制器资源就像可执行函数,有参数和返回值;输入和输出。 与传统 Web 应用程序使用 HTML 表单一样,REST API 依赖控制器资源来执行特定于应用程序的操作,这些操作无法在逻辑上映射到标准方法之一(创建、检索、更新和删除,也称为 CRUD)。 控制器名称通常显示为 URI 路径中的最后一段,在层次结构中没有子资源跟随它们。 下面的示例显示了允许客户端向用户重新发送警报的控制器资源:

POST /alerts/245743/resend

还有:

POST should be used to create a new resource within a collection and execute controllers.



0
投票

我认为你误解了整个概念。您可以将操作映射到 HTTP 方法和 URI,而不仅仅是 HTTP 方法。对于 CRUD 来说,这一点很明显。在“非 CRUD”的情况下,您需要添加具有不同 URI 的新资源,而不是尝试将新的 HTTP 方法添加到列表中。

PATCH 用于更新资源,就像 PUT 一样,但在 PATCH 的情况下,您发送更新指令而不是表示。当然可以使用,也可以使用POST。如果您不在正文中发送新资源状态的表示,那么使用 PUT 并不是一个好主意。

所以这些都可以是好的:

PATCH engines/123 "activate" PUT engines/123/state "active" POST engines/123/activation null

您可以使用“部署/取消部署/执行”执行相同操作:
PATCH engines/123 "deploy"
PUT engines/123/state "before-deploy"
POST engines/123/execution null

这只是一个建议。你可以根据HTTP标准选择动词,我认为最好避免在URI中使用动词,我只使用名词,因为这样才有意义。虽然 URI 并不是那么重要,它就像网页上漂亮的 URI,看起来不错,但没有人真正关心,除非他们必须把它写下来。需要明确的是,除非您在回复中发送这些超链接,否则这仍然不是 REST。
{
    id: "engines/123",
    type: "docs/engine",
    operations: [
        {
            operation: "docs/engine/activation", 
            id: "engines/123",
            method: "PATCH",
            body: "activate"
        }
    ]
}

使用 RDF 和本体可以更进一步。
    

© www.soinside.com 2019 - 2024. All rights reserved.