REST API设计:如何处理也可以是子资源的资源 [英] REST API design: how to handle resources that can also be sub-resources

查看:53
本文介绍了REST API设计:如何处理也可以是子资源的资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在现有产品数据库的顶部放置一个(只读)REST服务.最简单的部分是拥有顶级产品资源,例如:

I have to put a (read-only) REST service atop of an existing product database. The easy part is having a top level product resource, like:

/api/products/

现在,实际上,此服务的调用者将需要根据商店的ID和特定过程(例如零售")的ID获取其相关产品.在幕后,这两个值的组合产生了已配置的产品子集.这对于调用者而言必须是透明的,它不需要了解这些产品组合".

Now, actually callers of this service will rather need to get their relevant products based on the ID of a store and of a specific process (like "retail"). Behind the scenes, the combination of those two values results in a configured subset of products. This must be transparent for the caller, it should not need to know about these "product portfolios".

所以我考虑过这样设计URI,其中1234是StoreID,零售是流程:

So I thought about designing the URI like this, where 1234 is the StoreID and retail is the process:

/api/stores/1234/retail/products

这里出现的第一个问题是,如果我应该将完整的产品或URI返回到/api/products/上它们各自的资源中,...专业人士显然会发现调用者不需要从中检索每个单独的产品/api/products,其缺点是,这会导致/api/stores/1234/retail/products URI出现缓存问题.

The first question that comes up here is if I should return full products here or URIs to their individual resources on /api/products/ ... the pro would be clearly that the caller does not need to retrieve each individual product from /api/products, the con would be that this would cause a caching headache on the /api/stores/1234/retail/products URI.

为了使事情复杂化,这些产品当然也要有价格.同样在这里,产品没有一个价格,而是多个价格,除了其他因素外,该价格还取决于StoreID和流程.实际上,价格是产品的直接子代,因此:

To complicate things, those products of course also have prices. Also here, a product does not have one price, but multiple ones that is also dependent of the StoreID and the Process, besides other factors. In reality, prices are direct children of products, so:

/api/products/ABCD/prices

将是显而易见的选择,但同样,由于StoreID和Process与预过滤价格有关,因此类似URI:

would be the obvious choice, but again, as StoreID and Process are relevant to pre-filter the prices, an URI like:

/api/stores/1234/retail/products/ABCD/prices

会更合适.

同时,在此URI下还有其他产品的子资源(如产品详细信息)没有意义.这些显然仅在/api/products/ABCD/details下直接有意义,因为它们不依赖于商店或过程.

At the same time, there are other subresources of products that will not make sense to have under this URI, like product details. Those would clearly only make sense directly under /api/products/ABCD/details as they are not dependant on the store or process.

但这对我来说似乎有些混乱.但是同时,仅通过使用queryparam过滤器直接在产品资源上解决该问题就解决了这一问题,而且并没有强制调用者同时提供StoreId和process:

But this looks somehow messy to me. But at the same time, solving this by only having queryparam filters to solve it directly on the product resource, is not much nicer and does not enforce the caller to provide both, StoreId and process:

/api/products?store=1234&process=retail
/api/products/ABCD/prices?store=1234&process=retail

更重要的是,process或storeid与产品没有任何关系,因此直接在产品上进行查询似乎很奇怪.对于价格来说,这是有道理的.

Even more, process or storeid does not have anything to do with the product, so querying for it directly on product seems odd. For prices, it would make sense, though.

所以我的问题是:有没有解决我看不到的好方法?并且:当它们是子资源时,您是否建议返回完整的产品-这样做时您如何看待(HTTP)缓存?

So my question is: is there a good way to solve this that i don't see? And: would you recommend returning full products when they are a subresource - and what do you think about handling (HTTP) caching when doing that?

推荐答案

这里出现的第一个问题是我是否应该全额退还此处的产品或/api/products/上其各自资源的URI[...]缺点是会导致/api/stores/1234/retail/products上的缓存头痛URI.

The first question that comes up here is if I should return full products here or URIs to their individual resources on /api/products/ [...] the con would be that this would cause a caching headache on the /api/stores/1234/retail/products URI.

我肯定会退还全部产品-想象一下,如果客户只想显示产品名称列表,客户将要做的金额.理想情况下,该端点应该是分页的(例如,查询字符串可以包含& pageSize = 10& pageNumber = 2 之类的内容).

I would definitely return the full products - imagine the amount the client would have to do if it would simply want to display a list of product names. Ideally this endpoint would be paginated (query string can include something like &pageSize=10&pageNumber=2, for example).

与此相关的还有各种缓存解决方案-例如,您可以将所有产品缓存在Redis等数据结构服务中.

Also there are various caching solutions around this - for example you can cache all the products in a data structure service like Redis.

复杂的是,这些产品当然也要有价格[...]和详细信息子资源.

To complicate things, those products of course also have prices [...] and details subresource.

查看 Richardson成熟度模型级别3 ,这是链接进入的地方播放,您可能会在产品资源下看到以下内容:

Looking at the Richardson Maturity Model level 3, this would be where links come into play, and you could have something like this under a product resource:

<link rel = "/linkrels/products/ABCD/prices" 
      uri = "/products/ABCD/prices?store=1234&process=retail"/>

和产品详细信息资源的另一个类似链接.

and another similar link for the product details resource.

@Roman是正确的,REST是可以发现的,客户端应该简单地跟随链接(可能有很长/很丑陋的uri),而不必记住它们(例如,在SOAP中).

@Roman is right, REST is meant to be discoverable, clients should simply follow links (that can have long/ugly uris), instead of having to memorize them (like in SOAP, for example).

这篇关于REST API设计:如何处理也可以是子资源的资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆