RESTful 服务中的非 CRUD 操作

将非 CRUD 操作添加到 RESTful 服务的“ RESTful”方式是什么?假设我有一个允许 CRUD 访问这样的记录的服务:

GET /api/car/123           <- Returns information for the Car object with ID 123
POST /api/car              <- Creates a new car (with properties in the request)
PUT /api/car/123           <- Updates car 123 (with properties in the request)
DELETE /api/car/123        <- Deletes car 123
POST /api/car/123/wheel/   <- Creates a wheel and associates it to car 123

如果我想改变汽车的颜色,我会简单地 POST /api/car/123和包括一个 POST 变量的新颜色。

但是,假设我想购买一辆汽车,这个操作比简单地更新“用户”记录的“拥有的汽车”属性要复杂得多。简单地执行类似 POST /api/car/123/purchase的操作是 RESTful 的吗? 在 POST /api/car/123/purchase中,“ buy”本质上是一个方法名?或者我应该使用定制的 HTTP 动词,如 PURCHASE而不是 POST

或者非 CRUD 操作完全超出了 REST 的范围?

31158 次浏览

What you're really doing is creating an order. So add another resource for order and post and put there during the order process.

Think in terms of resources rather than method calls.

To finalize the order you'd probably POST /api/order//complete or something similar.

The RESTful way as I understand it is that you don't need new HTTP verbs, there's a noun somewhere that will mean what you need to do.

Purchase a car? Well isn't that

POST /api/order

Think about purchase as a business entity or a resource in RESTful dictionary. That being said, making a purchase is actually creating a new resource. So:

POST /api/purchase

will place a new order. The details (user, car, etc.) should be referenced by id (or URI) inside the contents sent to this address.

It doesn't matter that ordering a car is not just a simple INSERT in the database. Actually, REST is not about exposing your database tables as CRUD operations. From logical point of view you are creating an order (purchase), but the server side is free to do as many processing steps as it wants.

You can even abuse HTTP protocol even further. Use Location header to return a link to newly created order, carefully choose HTTP response codes to inform users about problems (server- or client-side), etc.

I feel REST APIs help in lot more ways than just providing semantics. So cannot choose RPC style just because of some calls that seem to make more sense in RPC operation style. Example is the google maps api to find directions between two places. Looks like this: http://maps.googleapis.com/maps/api/directions/json?origin=Jakkur&destination=Hebbal

They could have called it "findDirections" (verb) and treated it as an operation. Rather they made "direction" (noun) as a resource and treated finding directions as a query on the directions resource (Though internally there could be no real resource called direction and it could be implemented by business logic to find directions based on params).