10

I'm trying to convert a set of SOAP-based services to a RESTful API.

I started by identifying resources by analyzing operation names and I got the resource Subscription.

When I need to update the state of the subscription, I cannot simply send a POST request to the server, because I don't have direct access to the resources, but I need to call some RPC-style operations to update their properties. Additionally, only and only if I'm changing the state of the subscription to "active", an additional call to an external service is required.

In these cases, what is the best practice to handle underlying operations?

The solution I came up with is to use query parameters, so that if I need to call activation service, I can use something like:

POST /subscriptions/{subscriptionid}/?activate=true

Considering that I cannot directly update my Subscription object fields, is there any best practice to handle this kind of conversion?

Update 1:

I can put in the body of my POST request some values, for instance "state":"active"

and check inside my service the proper operations to be triggered.

  • REST's mapping of commands to HTTP verbs fails with complex operations. You are better off just doing a RPC style call POST activateSubscription/{id} no-one will be confused by it – Ewan Jun 28 '16 at 9:30
  • @Ewan I'm not sure this complies with the RESTful model, but I came up with another solution: in my code I can call the proper RPC-style operation according to the input payload (I can pass state=active in the body of my post request, the code will call the activation code) – Vektor88 Jun 28 '16 at 9:52
  • 1
    An update to an existing resource like this should be a PATCH, and the body of the query is then a partial model of what you are changing. A POST is supposed to be a request that creates a resource. This distinction, apart from being clearer to the user, will make it easier for your code to know when this operation is happening rather than a resource post. – Mr Cochese Jun 28 '16 at 10:42
  • 1
    @Vektor88 Typically, but those are idempotent operations where you need to pass in the entire resource state representation. This use case seems far more like a partial update, which fits a PATCH really well. – Mr Cochese Jun 28 '16 at 10:56
  • 1
    @MrCochese POST is not idempotent. – JimmyJames Jun 28 '16 at 14:55
7

You need to watch this talk by Jim Webber.

When I need to update the state of the subscription, I cannot simply send a POST request to the server, because I don't have direct access to the resources, but I need to call some RPC-style operations to update their properties. Additionally, only and only if I'm changing the state of the subscription to "active", an additional call to an external service is required.

Think "messaging"; send a message to your domain, describing what you want to have happen. The side effect of the message is that your domain model actually changes its state. The "resource" is the message queue.

POST /subscriptions/{subscriptionid}/?activate=true

The spelling of the resource name doesn't matter to the machines; but people tend to get fussy when the identifiers you use break from the convention that resources are "nouns".

Also, we're talking about a resource that is subordinate to /subscriptions/{subscriptionid} , so convention (see RFC 3986) calls for expressing that relationship with a path segment, rather than using the query part.

So these spellings might be reasonable

POST /subscriptions/{subscriptionid}/messages
POST /subscriptions/{subscriptionid}/activations
0

If its a boolean flag to activate/deactivate stuff, i'd say the default is to use JSON:

POST /subscriptions/{subscriptionid}/
{
    format: 0,
    subscription: 
    {
        active: false
    }
}

This is easily extended if you want to support more properties. Another approach is giving it its own endpoint:

POST /subscriptions/{subscriptionid}/active/
DELETE /subscriptions/{subscriptionid}/active/

Personally, i would only use this if the active state of this event needs/has properties that you then can pass/get in JSON, like an user ID or setting.

If its not a boolean value but just an action that you need to trigger but dont need/have any status feedback for (except an immediate 200 OK), i'd use an endpoint like this to trigger it much like a RPC:

POST /subscriptions/{subscriptionid}/activate/

When in doubt, read this: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful (see "What about actions that don't fit into the world of CRUD operations?")

0

REST is non-functional. Activate is a verb and can not be a state, Active is a state.

Because RESTful is non-functional you can not tell a RESTful service what to do, but you can add work for the queue of a service.

See this:

PUT /subscriptionQueue
subscriptionId={subscriptionId}
active=true

This request is RESTful and supports all benefits of RESTful (like performance, acid...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.