【问题标题】:Modeling Version Control Operations in REST在 REST 中建模版本控制操作
【发布时间】:2009-10-01 05:46:52
【问题描述】:

我们最近在我们的系统中添加了版本控制功能,我们很难以 RESTful 方式对这些功能进行建模。

当系统配置为“版本控制”模式时,系统的工作方式如下,在对实体进行修改之前,必须先检查它(为该用户创建一个私有副本)。修改本地副本后,用户可以签入以提交更改或撤消签出以放弃更改。

我们正在讨论什么是建模“签入”、“签出”、“获取版本”和“撤消签出”操作的正确方法。

假设我们有一个资源(名为 my-resource)

  http://my-system/my-resources/{id}

我们想在其上添加版本控制功能,我们在以下两种方法之间争论:

  1. 以运营为导向

    签到:http://my-system/my-resources/{id}/check-in 上发帖

    结帐:http://my-system/my-resources/{id}/check-out 上发帖

    获取版本: GET http://my-system/my-resources/{id}/versions/{version-id}

    撤消签出:在http://my-system/my-resources/{id}/undo-check-out 上发布

  2. 面向资源

    签到:http://my-system/my-resources/{id}/versions 上发帖

    结帐:http://my-system/my-resources/{id}/check-out 上发帖

    获取版本: GET http://my-system/my-resources/{id}/versions/{version-id}

    撤消签出:删除http://my-system/my-resources/{id}/check-out

你怎么看? 您对如何对这些操作进行建模有什么建议吗? 您是否熟悉可供参考的类似公共 API?

【问题讨论】:

    标签: version-control rest modeling


    【解决方案1】:

    这看起来很像一个简单的RCS 风格的版本控制模型。假设与您建议的基本资源 URL 结构相同,我将在 RESTful API 中对其建模如下:

    GET http://my-system/my-resources/{id} => 返回资源“id”的当前状态,在 HTTP 扩展标头中编码签出锁定状态(例如X-checkout-status: unlocked

    POST http://my-system/my-resources/{id}/versions => 尝试签出

    • 如果成功,返回一个 HTTP 201Created 状态,并带有一个指向新的临时版本资源的 Location: 标头(请参阅下面的“版本”URL 格式)
    • 否则,返回 HTTP 409 Conflict 状态码,表示资源已签出

    GET http://my-system/my-resources/{id}/versions/{version} => 获取资源的签出版本

    PUT http://my-system/my-resources/{id}/versions/{version} => 保存对已签出资源的更改

    POST http://my-system/my-resources/{id}/versions/{version} => 提交对签出资源的更改,将它们保存到进程中的主资源(可能需要X-checkout-status: unlocked 标头确认行)

    DELETE http://my-system/my-resources/{id}/versions/{version} => 释放签出锁而不将更改保存回主资源

    DELETE http://my-system/my-resources/{id}/versions => 释放文件上的所有锁;应该需要管理权限(但对清理过时的锁很有用)

    与您的设计存在一些差异。首先,我已经明确说明了如何实际完成对已签出资源的更新。其次,我使用了X-checkout-status标头和各种HTTP代码来指示文件当前是否被锁定,以及各种版本控制操作的成功或失败。

    然而,最关键的区别在于将“版本”子 URL 空间视为显式集合,因此使用普通的 POST/DELETE/等。管理结帐的操作。

    【讨论】:

      【解决方案2】:

      您刚刚描述了两个 RPC API。如果您需要 RESTful API,请尝试以下操作:

      GET {resource url}
      200 OK
      Location: {resource url}
      <resource>
          <!-- Rest of your resource goes here -->
          <operation id="check-out" href="{check-out url}" method="post">
      </resource>
      

      使用资源表示中的 URL 和方法,您可以签出资源以创建工作副本:

      POST {check-out url}
      200 OK
      Location: {working copy url}
      <working-copy>
          <!-- Info about the working copy goes here -->
          <operation id="check-in" href="{check-in url}" method="post">
          <operation id="discard" href="{undo check-out url}" method="post">
          <!-- Additional operations, as needed, to modify the working copy -->
      </working-copy>
      

      使用工作副本中定义的操作在完成后将其重新签入:

      POST {check-in url}
      200 OK
      Location: {resource url}
      <resource>
          <!-- Modified resource data goes here -->
          <operation id="check-out" href="{check-out url}" method="post">
      </resource>
      

      或丢弃它:

      POST {undo check-out url}
      200 OK
      Location: {resource url}
      <resource>
          <!-- Original resource data goes here -->
          <operation id="check-out" href="{check-out url}" method="post">
      </resource>
      

      现在,您的每个资源都是自描述的,并且有自己的 URL 来唯一标识它们。

      【讨论】:

        【解决方案3】:

        不是 REST(尽管 Fielding 是委员会成员),但 WEBDAV 是通过 HTTP 进行版本控制的标准方式。

        另一个 Apache 项目 Sling 似乎在存储库上包含一个 REST API(尽管我无法在任何地方看到 HTTP API 的完整描述,只有一些小示例)

        可能值得关注的第三个地方是Atom Publishing Protocol,它允许简单地发布到资源。

        【讨论】:

        • 这是一个很好的建议,但是 WebDAV 资源锁定模型不同于维护显式版本的简单 RCS 样式。但是,如果域模型可以稍微改变,那么最好不要重新发明轮子,在 HTTP 上实现另一个版本控制协议。
        猜你喜欢
        • 2021-06-22
        • 2012-05-31
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        • 2013-07-20
        • 2014-08-29
        相关资源
        最近更新 更多