2013-03-06 81 views
18

我是服务器端Web开发的新手,最近我一直在阅读很多关于实现RESTful API的知识。我仍然坚持的REST API的一个方面是如何构建识别客户端可以与之交互的资源的URI层次结构。具体而言,我坚持决定如何详细地构建层次结构,以及在资源由其他资源类型组成的情况下如何处理。如何构建REST资源层次结构?

下面是一个例子,希望能够展示我的意思。想象一下,我们有一个Web服务,可以让用户从其他用户购买产品。所以在这种简单的情况下,有两个顶级资源用户产品。以下是我开始构建的URI层次,

对于用户:

/users 
     /{id} 
      /location 
      /about 
      /name 
      /seller_rating 
      /bought 
      /sold 

适合产品:

/products 
     /{id} 
       /name 
       /category 
       /description 
       /keywords 
       /buyer 
       /seller 

在这两种情况下,每个层次中的参考子对象另一个层次中的对象。例如/users/{id}/bought是某些用户已购买的产品的列表,这是/products的子集。另外,/products/{id}/seller引用销售特定产品的用户。

由于这些URI引用了其他对象或其他对象的子集,所以API应该支持这样的事情:/users/{id}/bought/id/description/products/{id}/buyer/location?因为如果支持这些类型的URI,什么可以阻止像这样的东西,或者是同样令人费解的东西?此外,在这种情况下,您将如何处理路由,因为服务器中的路由器必须解释任意长度的URI?

回答

22

目标是建立方便的资源标识符,不要试图交叉引用所有内容。您不必重复URL表示:)

链接像/product/{id}/buyer不应该存在你的数据库关系,因为已经有标识该资源:/user/{id}

虽然它的确定有/product/{id}/buyers-list因为买家列表是在其他情况下不存在的产品的属性。

+0

那么,你的意思是,系统中的每个资源都只有一个** ** URI?因为这使一切变得更简单。在上面的例子中,如果我想通过api公开一些产品的卖家(产品只有一个卖家),你会推荐什么?我应该让人们做* GET/products/{id} *这会返回一些JSON对象和卖家在里面吗? – martega 2013-03-09 00:17:41

+2

对于'/ products/{id}',JSON可能包含嵌套的用户对象,以方便用户使用,也可以为该用户提供网址,这是您的选择,并不会改变两者都存在的事实。 – Anri 2013-03-09 00:27:27

+3

顺便说一句,它有助于查看其他服务的API。例如:https://developer.foursquare.com/docs/venues/venues – Anri 2013-03-09 00:30:30

11

您应该以CRUD方式思考它,每个实体都支持Create,Read,Update和Delete(通常分别使用GET,POST,PUT和DELETE HTTP动词)。

这意味着您的端点通常只会深入一层。例如

用户

GET /users  - Return a list of all users (you may not want to make this publically available) 
GET /users/:id - Return the user with that id 
POST /users  - Create a new user. Return a 201 Status Code and the newly created id (if you want) 
PUT /users/:id - Update the user with that id 
DELETE /users/:id - Delete the user with that id 

走进更详细,如/users/:id/about可能是没有必要的。虽然它可能有效,但它可能稍微有点过分。

也许在你的情况,你可以添加在:

GET /users/:id/bought - Array of products that the user bought 
GET /users/:id/sold - Array of products that the user sold 

在那里你可以返回的ID列表(可以通过产品API来获取),或者你可以把他们回来,如果前填充的产品你希望。如果您选择填充它们,那么您可能不应该填充每个产品引用的用户。这会导致循环包含并且是错误的。

而对于产品,在您的sitation我会用:

GET /products- Return a list of all products 
GET /products/:id - Return the products with that id 
POST /products- Create a new product. Return a 201 Status Code and the newly created id (if you want) 
PUT /products/:id - Update the product with that id 
DELETE /products/:id - Delete the product with that id 

GET /products/:id/buyers  - Array of who bought the product 
GET /products/:id/sellers - Array of everyone selling the product