【问题标题】:REST API design for non-CRUD actions, e.g. save, deploy, execute code用于非 CRUD 操作的 REST API 设计,例如保存、部署、执行代码
【发布时间】:2017-06-04 05:15:30
【问题描述】:

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

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

  1. 重组动作,使其看起来像资源的一个字段,例如如果您的操作是激活引擎,请设计 URI:PATCH engines/123,正文:{"status":"active"}
  2. 将操作视为子资源,例如PUT engines/123/active 没有身体
  3. 使用查询参数,例如PUT engines/123?activate=true
  4. 务实并选择非 RESTful 的 RPC 样式 URL,例如PUT engines/activate?id=123

我绝对无法按照 #1 和 #2 中的建议将 deploy/undeploy/execute 代码操作安装到资源中。您能否分享您的意见,我们如何才能最好地为这些操作设计 API?

【问题讨论】:

标签: rest


【解决方案1】:

您能否分享您的意见,我们如何才能最好地为这些操作设计 API?

创建/更新/删除信息资源,并作为其副作用,在 API 后面工作。

所以想想文件。

一个很好的例子:在RESTful Causistry 中,Tim Bray 询问了一个用于关闭机器的 api。 Seth Ladd's response 尤其值得阅读

从根本上说,REST 是一种解决文书工作问题的官僚机构。如果您想完成任何事情,请提交正确的表格;它成为描述你想要做什么的信息资源。

PUT /deploymentRequests/abcde

Please find the artifacts from build 12345 and deploy that artifact
to machine 67890

201 Created

请求只是一份文件,就像你办公桌上要求你完成某项任务的便签一样,也是一份文件。

就 REST 而言,URI 的拼写完全无关紧要;但从人类可读的命名约定的角度来看,从资源是文档这一事实开始,而不是您希望文档具有的副作用。

因此,例如,描述事物当前状态的文档和描述您想要对事物进行更改的文档是不同的文档,这是完全正常且符合 REST 的不同的标识符。

【讨论】:

  • 太棒了,虽然我认为您打算 POST 到 /deploymentRequests ,而不是 PUT。
  • 我不打算 POST。
【解决方案2】:

我认为您正在寻找控制器,根据REST API design RuleBook

控制器资源对程序概念进行建模。 控制器资源就像可执行函数,有参数和返回值;输入和输出。 与传统的 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.

【讨论】:

    【解决方案3】:

    可以轻松映射到 HTTP 动词的 CRUD 操作是 保存/编辑/删除代码。难以映射的非 CRUD 操作 HTTP 方法是在服务器上部署代码,执行代码,然后 取消部署。

    我认为您误解了整个概念。您将操作映射到 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 和本体可以更进一步。

    【讨论】:

      猜你喜欢
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 2014-03-14
      • 2014-10-19
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多