REST:如何创建依赖于三个或更多不同类型资源的资源?

标签 rest

一个 RESTful,hypertext-driven系统需要使客户端能够创建依赖于三个或更多不同类型资源的新资源。公开此功能的最佳方法是什么?

例如,假设我经营一家在线商店。服务器知道四种资源:

  • 订单:要运送的产品组。 [有一件货]
  • 目的地:运送到的位置。 【有很多货】
  • 发货:将产品发送给客户的行为。 [属于目的地、订单和包装商]
  • 包装工:实际准备发货订单的员工。 【有很多货】

  • 当订单发货时,客户端需要通过在服务器上创建一个新的发货来记录此事件。货件将需要提及目的地、订单和包装商。

    实现新Shipments的创建,我可以想到三种方法,我不喜欢它们中的任何一种:
  • 使用 Shipment 媒体类型 POST 到/shipments。 Shipment 媒体类型有三个字段:“order_uri”; "packer_uri";和“destination_uri”。每个 URI 分别用作货件中涉及的 Order、Packer 和 Destination 的唯一标识符。
  • 使用 Shipment 媒体类型发布到/orders/{order_id}/packers/{packer_id}/destinations/{destination_id}/shipments。
  • 向系统添加一个名为“ShipmentBuilder”的新资源。使用包含在 ShipmentBuilder 媒体类型中的“packer_uri”、“destination_uri”和“order_uri”POST 到/shipment_builders。

  • 我不喜欢选项 1,因为 Shipment 媒体类型另外定义了到 Order、Packer 和 Destination 的链接。这里,“链接”是一个 JSON 散列,由一个人类可读的名称、一个 URI 和一个媒体类型组成。向媒体类型添加“order_uri”、“packer_uri”和“destination_uri”似乎不是很枯燥,因为它复制了关联资源的 URI。

    选项 2 使用深度嵌套的 URI,它看起来既不易于维护,也无法捕获任何有意义的分层信息。

    选项 3 在客户端和 Shipments 的创建之间放置了另一个抽象级别,这使得系统更难学习。

    如果 Shipment 仅依赖于一种其他资源,则选项 2 会更有意义,但在这种情况下并非如此。就目前而言,我赞成选项 3,但更喜欢更好的选择。

    在此示例中,创建新 Shipment 的 URI 和媒体类型的最佳组合是什么?还应该考虑哪些其他方法?

    更新:以下是 Shipment 资源的 JSON 示例表示,显示订单、包装商和目的地的链接。选项 1 所需的 URI 重复出现在“装运”哈希中:
    {
      "shipment":{
        "created_at": "Wed Sep 09 18:38:31 -0700 2009",
        "order_uri":"http://example.com/orders/815",
        "packer_uri":"http://example.com/packers/42",
        "destination_uri":"http://example.com/destinations/666"
      },
      "order":{
        "name":"the order to which this shipment belongs",
        "uri":"http://example.com/orders/815",
        "media_type":"application/vnd.com.example.store.Order+json"
      },
      "packer":{
        "name":"the person who packed this shipment",
        "uri":"http://example.com/packers/42",
        "media_type":"application/vnd.com.example.store.Packer+json"
      },
      "destination":{
        "name":"the destination of this shipment",
        "uri":"http://example.com/destinations/666",
        "media_type":"application/vnd.com.example.store.Destination+json"
      }
    }
    

    “shipment”散列的内容(减去“created_at”字段)将被发布。使用 GET 时,将发送上面的完整 Shipment 表示。

    最佳答案

    REST“层次结构”没有任何意义。它们便于导航以路径的形式显示关系。本身不是层次结构,而是路径。因此,如果您放弃“层次结构”概念并认识到有许多通往同一最终位置的替代路径,则选项 2 实际上是明智的。

    您的选项 2 是 orders->packers->destination 路径。理论上,orders->destinations->packers和packers->orders->destinations,packers->destinations->orders,以及其他几个都在同一个地方。是的,支持他们所有人是一种痛苦。然而,这证明它们都是等价的,并且没有等级。

    “我不喜欢选项 1,因为 [它] 看起来不是很干燥。”

    所以?去掉重复的东西。为什么 cargo 还必须包含订单和包装商信息的完整重复? URI 引用足以允许查找和检索 Order 和 Packer。为什么要发送 Order 和 Packer?

    “选项 3 使系统更难学习。”为了谁?开发商?您是围绕开发人员而不是用户及其用例设计系统吗?耻辱。

    REST 的要点是(通常)一个 URI 是一个绝对的、最终的和永恒的东西。哪种替代方案为您提供了绝对最佳的 URI 结构?认识到 URI 不是层次结构而是路径——并且对象可以存在于多个替代路径的末尾。

    您正在创建货件。发布到 /shipment .简单、清晰的 URI 才是最重要的。

    关于REST:如何创建依赖于三个或更多不同类型资源的资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1402721/

    相关文章:

    python - 在存储标签上删除请求

    android - 使用 oAuth 的 RESTful Web 服务用于移动应用程序

    java - 多个JAX RS路径触发了错误的方法

    java - REST 服务器返回由 Jetty 提供支持的 HTTP 404 错误,如何查找服务器日志条目?

    python - FK选择的显示选项-Django Rest Framework

    api - REST GET 请求、动词和 apikey

    php - 使用 Codeigniter 框架缓存 REST api

    php - Paypal 付款 REST API - REQUIRED_SCOPE_MISSING

    java - REST 请求响应和内部服务器错误

    http - 超长 URI 的 REST 最佳实践