1

我正在尝试通过 HTTP 设计一个 REST API。我对此完全陌生,所以请告诉我我的任何假设或想法是否完全错误。

该域是简约的。我有一个产品数据库,每个产品都有一个关联的图像。正如我所看到的,我可以通过以下两种方式之一来设计我的 API:

  1. 我可以将每个图像与其产品捆绑在一起,并将它们表示为一个资源。此 api 的缺点是每次 PUT 或 GET 产品时,您都必须通过网络发送图像,即使您不需要特别读取或更改图像。据我了解,不 PUT 或 GET 资源的完整表示不是 RESTful。此外,在这种情况下,图像的客户端缓存将毫无用处。

  2. 我可以将产品和图像建模为两种不同的资源。当您获取产品时,它将包含一个可用于获取图像的 image_id。该模型需要两个 HTTP 请求。一个获取产品,一个获取其对应的图像。也许还不错,但是如果我想显示所有产品的列表以及它们的图像怎么办?然后我突然有一堆HTTP请求。在使用 SSL 时,我想这可能会产生性能问题。不过,好消息是我的 API 的使用者可以选择在客户端缓存图像。

那么,如何将我的 API 建模为既 RESTful 又高效?

4

3 回答 3

5

您正在考虑数据模型,这很好。
与此相关的是,REST 没有指定或暗示数据模型必须完全去规范化。

通常,在获取资源时,您会收到一个信息包,其中还包括对其他相关资源的 URL 引用,例如产品图像。它还可以包括对产品类别、产品制造商等的引用。每个都可能是 URL,或者您可以从中派生 URL 的 ID。像这样的消息:

{
   "id": 123456,
   "description" : "Your basic paperweight",
   "category" : { id: 17717,  "name" : "Home furnishings" },
   "manufacturer": { id : 78783, "name" : "Boeing" },
   "price" : 1.99,
   "imageId" : 109101
}

...可能暗示这样的 URL:

http://api.mycompany.com/product/123456   
http://api.mycompany.com/category/17717   
http://api.mycompany.com/manufacturer/78783   
http://api.mycompany.com/image/109101    

...并注意链接到资源的完整表示,如类别、制造商等,不会与原始资源一起传输。这是一个部分去规范化的数据模型。

关于您对 PUT 的评论:

  1. 这是一个见仁见智的问题,但是……对于许多开发人员 来说,允许通过 PUT 进行部分更新是完全可以接受的。因此,您可以在不指定所有内容的情况下更新资源;现有字段将保持不变。如果您选择此行为,则在处理边缘情况时可能会使您的(服务器端)代码复杂化。例如,客户如何指示他要擦除或删除字段?(传递 null 可能有效,但对于某些数据, null 是一个有意义的值。)

  2. 为什么要担心 PUT?如果您想要部分更新,很容易使用 POST,在查询参数中带有动词(例如,“partialUpdate”)。实际上,这就是 Roy Fielding 所倡导的,对我来说很有意义。

部分更新将是这样的:

POST /products/123456?action=partialUpdate 
*headers*

{ 
  "description" : "A fabulous paperweight designed in Sweden, now at a new low price." },
  "price" : 1.78 
}
于 2012-11-24T23:14:00.960 回答
1

我会使用选项 2,但不是 image_id,而是存储图像 URL。此外,不要害怕使用自定义脚本来返回您需要的内容(例如,显示所有产品和图像)。REST 是设计目标,不一定是实现真理。你的设计仍然是 RESTful。

于 2012-11-24T22:40:16.057 回答
0

我同意其他 2 个答案,我认为您应该选择选项 2。但是您还询问了有关获取产品列表的问题,因此这是我的回答。

考虑使用只能与 GET 一起使用的另一个资源,该资源将返回产品列表。通过这种方式,将只有一个 HTTP 请求来使用该列表。如果列表可能非常大,则需要实现某种分页机制。

例如,假设您需要退回 2500 件产品,但您决定退回的产品不超过 1000 件。第一个 GET 请求将返回前 1000 个项目,并且还将在答案中包含使用下一个“页面”的 URL,在这种情况下是下一个 1000 个产品,然后在第二个请求中,您将返回产品 1001-2000 和一个 URL到下一个“页面”,在这种情况下是最后 500 个产品。

然后,如果需要,消费者也可以获取图像。您也可以对图像使用此列表选项,但每个“页面”中的图像束应该明显更小。我不建议选择列表机制来消费图像。

于 2012-11-26T07:00:19.227 回答