设计有效的rest API

时间:2012-11-24 22:36:03

标签: api rest

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

该域名极简主义。我有一个产品数据库,每个产品都有一个相关的图像。在我看来,我可以用两种方式之一设计我的API:

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

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

  3. 那么,我如何将我的API建模为RESTful和高效?

3 个答案:

答案 0 :(得分: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
}

...可能意味着这样的网址:

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”)。实际上this is what Roy Fielding advocates,这对我来说很有意义。

  3. 部分更新将是这样的:

    POST /products/123456?action=partialUpdate 
    *headers*
    
    { 
      "description" : "A fabulous paperweight designed in Sweden, now at a new low price." },
      "price" : 1.78 
    }
    

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我同意其他2个答案,我认为你应该选择2号选项。但你也问过要获得产品清单,所以这是我的答案。

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

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

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