RESTful服务中的非CRUD操作

Mik*_*att 98 rest web-services

将非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
Run Code Online (Sandbox Code Playgroud)

如果我想改变汽车的颜色,我会简单地POST /api/car/123为新颜色添加一个POST变量.

但是,假设我想购买一辆汽车,而且这种操作比简单地更新"用户"记录的"拥有汽车"属性更复杂.简单地做一些类似于POST /api/car/123/purchase"购买"本质上是方法名称的东西是RESTful 吗?或者我应该使用自定义HTTP动词,PURCHASE而不是POST

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

Tom*_*icz 60

考虑将购买作为业务实体或RESTful字典中的资源.话虽这么说,进行购买实际上是在创造一种新的资源.所以:

POST /api/purchase
Run Code Online (Sandbox Code Playgroud)

将下新订单.应该通过发送到此地址的内容中的id(或URI)引用详细信息(用户,汽车等).

订购汽车不仅仅是数据库中的简单INSERT并不重要.实际上,REST不是将数据库表暴露为CRUD操作.从逻辑的角度来看,您正在创建订单(购买),但服务器端可以自由地执行所需的处理步骤.

您甚至可以进一步滥用HTTP协议.使用Locationheader返回新创建的订单的链接,仔细选择HTTP响应代码以通知用户有关问题(服务器端或客户端)等.

  • "作为资源购买"设计看起来很整洁.如果资源是"啤酒"怎么办......我希望服务器喝它..(它对我来说,我肯定会得到它;))..我们应该把"喝酒行动"视为一种资源?!或者"正在喝啤酒",这是一项艰苦的商业运作?!更严重的是,RESTful设计是关于将行动视为资源吗?!.. (22认同)
  • REST就是要操纵资源状态,每个业务操作都必须映射到状态CRUD操作.如果您需要*hard*业务操作语义,则必须采用SOAP方式(SOAP实际上是消息传递,但通常在请求 - 响应操作中组织). (3认同)
  • 您将如何通过REST服务公开"批准采购订单"?我认为@TomaszNurkiewicz是正确的,因为任何无法以CRUD方式完成的东西都需要SOAP提供的操作语义.除非"采购订单批准"是其自身的模型/实体.例如POST/po-approval(请求中包含PO详细信息). (2认同)
  • 从REST客户端的角度来看,"批准采购订单"应该是订单的另一个更新.例如,将"已批准"更改为"true"并将更新发送到服务器.服务器可能需要做一堆检查,可能需要更新/创建一堆其他资源.但这是服务器问题,不应该对客户端可见. (2认同)
  • @antinome:"假设客户端知道其中的一些",如果是这样你就不做REST(它可能仍然是有效的,合理的软件!).REST旨在能够创建不知道那种东西的客户端,以创建在服务器行为发生变化时仍能正常工作的客户端.您要做的是经典RPC,您需要检查您的方法以使其适合REST,或者接受您正在执行RPC并使用针对RPC的协议(如SOAP).REST非常努力地不成为RPC,所以当你想要/需要RPC时,它永远不会是一个很好的选择. (2认同)

djn*_*jna 14

我理解的RESTful方式是你不需要新的HTTP动词,在某个地方有一个名词意味着你需要做什么.

买车?好吧不是那样的

POST /api/order
Run Code Online (Sandbox Code Playgroud)

  • PUT是否用于*更新*资源,因为它是幂等的?这意味着您可以根据需要多次调用它,但只有第一个/最后一个呼叫很重要.另一方面,POST用于*创建*资源,并且调用它两次应该实际创建两个. (2认同)

小智 5

你真正在做的是创建一个订单.因此,为订单添加另一个资源并在订单处理期间发布并放置.

考虑资源而不是方法调用.

要完成订单,您可能会POST/api/order //完成或类似的东西.