Rest uri design for changing the status for resource

15,573

Solution 1

The first option is clearly not REST; you have 'actions' in the URI and are using POST, which is to create a new resource, which you clearly not attempting to do.

Looking at just the URI format for now. Option two is getting better, but query strings of that nature are more for reading data. Nothing really stops you doing it in this way. Option three has the best URI format, it is only referencing what resource you want to refer to in your request.

If we now consider the method of the request. In my book, this is rather simple, I presume that the status is only one field of this resource, and so if you are only doing a partial update, you are patching the resource, and thus PATCH is the method to use. On the off chance the 'status' is the only property, then changing the status is completely changing the resource and thus PUT would be acceptable; but I doubt that really is the case.

As it stands, the URIs of the third option, combined with use of PATCH is probably the best option.

PATCH /resources/{resource_identifier}

{ "status" :"close" }

Of course, you could also combine this with the concept of exposing specific attributes via their own URI as if they were a resource in their own right. Frankly, I don't like this, as it feels rather odd and only works for one attribute at a time. Still, if this is what you wanted to use, you could have something like:

PUT /resources/{resource_identifier}/status

close

Keep in mind, there is no "right" way of doing REST, just "not bad" ways. It's a style, not a rule set.

I also suggest you consider that being able to take many formats is a desirable feature, generally speaking. As such, the first option tends to be easier to work with. You could take JSON, as the example has, or swap it to XML <status>close</ status>, or a simple key value pair status=closed etc.

Solution 2

Why not have 'status' as resource. You can manage it. Also assume that there should be already a 'status' created as part of the {resource_identifier} resource creation and there is already a default value for the status.

Then the business logic need is just to 'update' the status via the rest call and therefore 'PUT' should be used.

updated Moving status to the Put-Body

PUT:    /resources/{resource_identifier}/status/

Body: {void | open | close }

Solution 3

Your second option looks better because you're maintaining the RESTful url structure and not appending RPC-style methods to the end of it.

Why not just do this:

PUT to /resources/:id and send the data transition=void with the request.

It behaves in the same way it would if you were receiving a POST request, just grab the data out of the request body.

Solution 4

There are many cases that state changes have a lot of business logic. While the answers are based on the "Rest standards", I think there are cases that are not simply changing a state field.

For example, if a system has to cancel an order. This is not simply to change a state, since the order has many states and each change represents a lot of logic (notifications, verifications, etc.)

In the cases of using:

PATCH /order/1
{ "status" :"cancelled" }

I can assure you that the logic will be scattered by the client and the server, it will be difficult to maintain, and it will not have an elegant code (especially on the server side, which will verify the previous, subsequent state, if the change is consistent, and it will be mixed with the update responsibility).

I see it simpler to have a cancel method and do its job. I think in many cases it is more elegant to do:

PATCH: /order/1/cancel 

//you could use the body with some cancellation data.

The following link can help you: https://phauer.com/2015/restful-api-design-best-practices/#keep-business-logic-on-the-server-side

Share:
15,573

Related videos on Youtube

Suresh
Author by

Suresh

Updated on September 16, 2022

Comments

  • Suresh
    Suresh over 1 year

    I have a resource that can be reach at the URI /resources/{resource_identifier} and it has a 'status' property that I want be accessible. I've thought of a few options for this, which would be the 'best' or 'most RESTfull'?

    Option One Append actions onto the URI and have the client POST to these URIs

    /resources/{resource_identifier}/void    
    /resources/{resource_identifier}/open    
    /resources/{resource_identifier}/close
    

    This looks clumsy though.


    Option Two Use a query param in the URI and have the client PATCH to these

    /resources/{resource_identifier}?transition=void
    /resources/{resource_identifier}?transition=open
    /resources/{resource_identifier}?transition=close
    

    Option Three Use the payload of the request and have the client PUT

    /resources/{resource_identifier}
    

    payload options:

    { ..., "status" :"void" }
    { ..., "status" :"open" }
    { ..., "status" :"close" }
    

    Or maybe something else altogether?

  • Suresh
    Suresh over 10 years
    Thanks... But we are doing resource creation and actions in POST request.... For update only we use PUT request... Once again Thanks..
  • Dan Rowlands
    Dan Rowlands over 10 years
    I think PUTing to the /status/ resource makes sense. Although wouldn't you put the actual status: void, open, close in the body of the PUT rather than as part of the URI?
  • adnan
    adnan over 7 years
    What about if you want to use hypermedia? Option one might be more suitable then right? So that these resources are only shown if applicable ( stackoverflow.com/questions/39457627/hateoas-and-links-actio‌​ns/… ). What do you think?
  • thecoshman
    thecoshman over 7 years
    To be honest, I don't really understand what it is you are trying to ask. This question is about ReSTfull design, in which case, using an action as part of the URL is clearly against what was advised by Fielding, and if you are not basing you design on decisions on what Fielding advised in his paper, then you are not on about ReST and thus all is moot.
  • adnan
    adnan over 7 years
    Why not, by makeing a list of different appropriate actions you are guiding the user to which changes of states are available (HATEOAS right?). Why is this not ReSTfull?
  • thecoshman
    thecoshman over 7 years
    ... it's not ReSTfull because you have the actions in the URL. It's a simple as that.
  • Moses Schwartz
    Moses Schwartz about 4 years
    Keep in mind, there is no "right" way of doing REST, just "not bad" ways. It's a style, not a rule set.
  • thecoshman
    thecoshman about 4 years
    @MosesSchwartz yes and no; there is an original description of how REST should be done, but yeah, really, just do what makes sense. You're going to have to document it anyway.
  • Moses Schwartz
    Moses Schwartz about 4 years
    @thecoshman I just quoted you, I thought it’s the greatest description of REST
  • Siim Nelis
    Siim Nelis almost 4 years
    Since the standard behaviors of PUT, GET, and DELETE map roughly to the CRUD paradigm, some believe that Resource APIs should only be used for CRUD use cases. This, however, is an incorrect assessment because POST can be used to execute behaviors that don’t map well to CRUD. Post is meant exactly for that. Make 3 post methods.
  • thecoshman
    thecoshman almost 4 years
    @SiimNelis erm, GET and DELETE do cleanly map to Read and Delete. PUT has the confusion of being more of a complete Update (not partial, such as changing a field, unless you expose that field as it's own resource), but it can also be used to Create. POST is best used for Create. Using POST to trigger three actions is basically using POST for RPC and that's something REST is meant to be avoiding.
  • Siim Nelis
    Siim Nelis almost 4 years
    @thecoshman you are right on the REST verbs part. What I'm saying REST gives you standard for CRUD operations but complex domains have behaviour which manipulates data on the server side, that doesn't come from the client but is a outcome of a computation. You have standard POST for you resource to create and you can have additional POST endpoints with a VERB that REST standard doesn't support.
  • thecoshman
    thecoshman almost 4 years
    @SiimNelis I would be careful to not use 'standard' when it comes to REST, there is no standard, only conventions. Even the notion there is a set list of http verbs available is wrong. It's also not quite right to say that POST is the verb for creating a resource, PUT can also be used. If you wanted to, in theory, you can use any verb (even one you make), for a REST call, such as DISPATCH /order/123. Downside here is that ad-hoc verbs whilst technically valid are often treated as invalid and dropped. My example would be 'more REST' than doing something like POST /order/123/dispatch.
  • Siim Nelis
    Siim Nelis almost 4 years
    @thecoshman post isnt idempotent and put is and you problably know this and what it means. Use the standard if there is one. But if there isnt why create a new http verb instead of a new uri for post. KISS
  • alejo4373
    alejo4373 over 3 years
    The GitHub REST API offer us some examples that relate to this discussion. See how they handle locking an issue for example: they PUT .../issues/{issue_number}/lock and DELETE .../issues/{issue_number}/lock. It's interesting that this resembles real life putting on(PUT) an actually lock and removing(DELETE) from something.