4

I've seen tons of examples on how to structure URL's for basic CRUD operations but seen very little when talking about more Command-like operations, or application service calls.

For example, let's say in my application service I have a call like RemoveOldOrders(int customerId) that would remove any order from the system that is over 2 years old for a customer with id "customerId". What would the URL look like on my restful service? What would the payload of the call look like? What HTTP method (POST?) would I use?

My thought is it would be something like this:

/Customer/1/RemoveOldOrders as a POST, with an empty body (as the customerID would come from the url).

Are there good guidelines on something like this?

Update: I feel like I need to clarify my question a bit in lieu of the comment about a possible duplicate post (yes, that post is asking essentially the same thing but I don't really feel the question was answered well).

What if I want to perform an operation against a resource but that operation doesn't fit into the standard HTTP verbs?

Another example: my application is hooked into an ESB and there needs to be a way to force a projection of my resource onto the ESB for processing? In my current SOAP-based web service I'd have a method like:

ExportCustomer(int customerId)

Now, in the case of a RESTful service, how could I represent this action in a uri? Option 1 from Brian Kelly's answer seems like the most logical, something like:

POST http://someapp/api/customer/1/export

or would:

POST http://someapi/api/customer/export/1

be better?

Matthew Bonig
  • 2,001
  • 2
  • 20
  • 40
  • probable duplicate question: http://stackoverflow.com/questions/6850187/non-crud-operations-in-a-restful-service – smcg Mar 28 '12 at 17:30

3 Answers3

2

Anytime you want to model verbs like "remove", you should think of DELETE. Similarly, for "create" think POST (and/or maybe PUT), for "read" think GET and for "update" think PUT (or maybe PATCH).

So for your example of "remove old orders", you should definitely use DELETE. Now your only remaining challenge is how to identify the orders that should be removed. Once you figure that out, the URI scheme will fall into place with it.

Here are some options:

  1. DELETE http://your-api.com/old-orders

    Here, the meaning and range of old-orders will be determined by the server receiving this request. This frees the client from having to do so, but removes their ability to change that range.

  2. GET http://your-api.com/order-query?days-older-than=730

    This returns a Location URI of http://your-api.com/order-query-result/{some ID} that represents the set of old appointments. Then you can simply issue a DELETE on that URI to purge the old records in one fell swoop.

  3. Instead of forcing the client to remember to issue deletion commands of this type, offer some kind of configuration resource that can be manipulated via your API to set some field like purgeRecordsOlderThanDays=730, and just let the server do it automatically for you in a cron-like fashion. That would be my preferred approach.

Brian Kelly
  • 19,067
  • 4
  • 53
  • 55
  • Ok, but what if the "verb" does not fall into "delete", "create", "update" or one of the common HTTP actions? I used a poor example. I see the similar post mentioned as a comment to my OP describes considering it a "resource" but that wouldn't be the case for many situations. What if my resource is still a Customer but the operation is something very obtuse like "Export to ESB"? – Matthew Bonig Mar 28 '12 at 19:11
  • 2
    Then you should consider creating a noun out of the verb that's causing you trouble, and act on that instead. For example, to model "Export to ESB", you could have an `ESBExporter` resource which you could then `POST` to in order to do the actual export. – Brian Kelly Apr 09 '12 at 01:58
0

For exporting, then you need to remove the "export" verb and replace it with an ESB representation of the resource: -

  • GET http://someapp/customer/{id}
  • The response includes a link to export: GET http://someapp/customer/{id}/ESB
  • Getting on the export link returns the ESB representation (with appropriate content type)
David Kerr
  • 375
  • 2
  • 12
0

For example, let's say in my application service I have a call like RemoveOldOrders(int customerId) that would remove any order from the system that is over 2 years old for a customer with id "customerId". What would the URL look like on my restful service? What would the payload of the call look like? What HTTP method (POST?) would I use?

RemoveOldOrders(int customerId)
DELETE /oldOrders {customerId: id}
DELETE /customer/{id}/orders?old=true
etc...

You should read more about uniform interface / resource identifiers and the HTTP method specification.

The URL does not really matters. What matters that you should have resource with resource identifiers (URLs) and you have to manipulate them by using an uniform (standard) interface, like the call of HTTP methods.

inf3rno
  • 24,976
  • 11
  • 115
  • 197