【问题标题】:REST - dealing with sub-resource accessREST - 处理子资源访问
【发布时间】:2014-01-06 19:57:51
【问题描述】:

我正在评估一种可能的 REST API 设计,并希望就处理嵌套资源的方式寻求反馈或最佳实践。

考虑以下(JSON 表示的)数据模型,它是一个人为的图书库,类似于我正在查看的数据。请忽略没有图书馆等书籍可以存在的事实。

{ "library-name" : "foobar",
  "rows" : 
[
  {"row-id":"1", 
   "shelves": 
      [
        {"shelf-id":"1", 
            "books": 
              [
                {
                  "book":
                    {"book-name":"abc", "author":"someone"}
                }
              ]
         }
       ]
    }
 ]
}

然后假设可能的 REST API 设计是:

/library (the root API URI)
/library/{library-name}/
/library/{library-name}/{row-id}
/library/{library-name}/{row-id}/{shelf-id}
/library/{library-name}/{row-id}/{shelf-id}/{book-name}

对于 POST 操作,服务器将实现以下功能以允许:

  • 添加新书,方法是直接对 /library/{library-name} 执行 POST,将书的所有详细信息编码到嵌套数据结构内的书架、行等(如图所示)。
  • GET 操作将允许在每个追索级别。 GET 将返回完全嵌套的数据(例如,作为 JSON 数据返回给定图书馆的所有行/书架和书籍等)。

上面有一些权衡:

  • 可以通过多个 URI 访问给定的图书资源。例如,对 /library/{library-name} 的 POST 可以创建一本书,对 /library/{library-name}/{row-id}/{shelf-id} 的 POST 也可以。在这种间接 POST 情况下,数据而不是 URI 标识了实际的目标子资源。这是 RESTfuL 吗?
  • 允许在 POST/PUT 操作中通过其父资源处理资源在批量操作中很有用;节省往返次数。这种好处是以客户端和服务器必须处理的更复杂的数据结构和处理程序代码为代价的。

评论?我在这里缺少什么(我没有找到很多上面的例子,这让我觉得这不是一种常见的设计模式)?

【问题讨论】:

标签: rest design-patterns restful-url


【解决方案1】:

根据您的描述,您打算将“行”和“架子”作为 URL 的组成部分公开,如果这是您的设计意图,这很好。这就是您的问题所在,因为如果“行”和“架子”是资源 URL 的组成部分,那么您不应该执行“所谓的”批量 POST/PUT/DELETE 操作,但使用 GET 就可以了只要书名是唯一的。

我可以看到你有以下业务操作

A) - 在特定位置创建一本书

HTTP POST /library/{lib-name}/{row-id}/{shelf-id}/{book-name}
Body: {json info for the book}

B) - 获取所有书籍

//in all library        
HTTP GET /library/

//in a specific library         
HTTP GET /library/{lib-name}/ 

//in a specific row         
HTTP GET /library/{lib-name}/{row-id}/

//in a specific row & shelf         
HTTP GET /library/{lib-name}/{row-id}/{shelf-id}/

C) - 获取特定书籍

HTTP GET /library/{lib-name}/{row-id}/{shelf-id}/{book-name}

//If the book-name or ID is unique, you can access it from the toplevel
HTTP GET /library/books/{ book-name}

如果行和架子不是 URL 的重要部分,您将拥有

A) - 创作一本书

HTTP POST /library/{lib-name}/{book-name}
Body: {json info for the book including row & shelf}

B) - 获取所有书籍

//-in all library       
HTTP GET /library/

//-in a specific library        
HTTP GET /library/{lib-name}/ 

C) - 获取特定书籍

//If the book-name or ID is unique, you can access it from the toplevel
HTTP GET /library/books/{ book-name}

更新

这里的决定是从应用程序的角度来看,{row}/{shelf} 在 URL 中公开给客户端作为管理 REST 资源 的一种方式是至关重要的,或者它们是只是一本书的属性

如果 {row} 和 {shelf} 也是 REST 资源 供客户端管理或用于识别资源的唯一路径(在本例中为 book),则拥有它们是有意义的作为 URL 的一部分,它们应该受到 REST/HATEOAS 的约束。换句话说,您不应该使用复杂的主体来包含您的 POST 中的所有“子资源”。

GET 更微妙。

在 URL 上 GET 很简单

/library/{lib-name}/{row-id}/{shelf-id}/{book-name}

GET 可以应用于 '/library/{lib-name}/'。在这种情况下,正文应该包含某种形式的结构化链接,指向下面的资源,例如

[
{/library/{lib-name}/{row-id}/{shelf-id}/{book-name}}, 
{/library/{lib-name}/{row-id}/{shelf-id}/{book-name}},
 ...]

但如果它们只是属性,那么它们可能是复杂体的一部分,因为从可寻址性或链接和连接性的角度来看,它们没有增加任何价值。

REST 关注以下内容(复制自 RESTful Web Services

  • 可寻址性
  • 无国籍状态
  • 陈述
  • 链接和连通性
  • 统一界面

两本关于 REST 的好书,并就您感兴趣的主题进行了一些讨论。

【讨论】:

  • 谢谢!那么您对实现的 REST API 有何看法:HTTP POST /library/{lib-name}/{row-id}/{shelf-id}/{book-name} 带有复杂的主体。本质上,在从 POST 操作中的数据派生目标子资源或在 GET 中将子资源数据返回给父级时,即使这些子资源具有 URI,是否存在非 RESTful 的东西?我在想至少这个设计不遵循 HATEOAS 风格。
  • 更新后,如果行和架子是 REST 资源或识别资源的“可寻址性”的一部分,那么它们不应隐藏在正文中。
  • 再次感谢!我对这些子资源还有一个疑问。我想知道如何处理以下情况:当为 /library/{lib-name}/{row-id}/{shelf-id}/{book-name} 尝试“新书”POST 时,一个想要检查/修改货架容量。这里显然存在资源依赖(图书资源依赖于书架资源,两者都被管理)。在实施方面,人们将如何解决这个问题?例如。 {book} 处理程序是否应该调用 {shelf} 处理程序,并对书架资源进行检查/更改?同样,我想知道这种间接的资源修改是否是 RESTful 的。
  • 这与REST无关,是后端处理。但是如何向客户汇报,需要从容处理。就像即将创建书籍一样,后端会在创建书籍之前验证书架甚至有关书籍的信息是否有效。如果有任何失败,后端将返回 HTTP 错误代码,例如“400/412”和错误更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 2016-12-23
相关资源
最近更新 更多