Correct RESTful verb - rest

I have a resource with conditional operations:
/foos/{id}/authorize
/foos/{id}/cancel
The idea is that authorize will change the status of the resource from saved (the default) to authorized (by a third party application). The authorize could return a error from the remote part or could be authorized. Once authorized the resource could not be authorized again so this is not an action that could be called again and again.
The cancel occurs when an authorized resource is revoked. Once cancelled the resource will stay as cancelled forever.
What's the correct verb in a RESTful world for this kind of operation considering that this operation is not safe and could not be considered idempotent as a second call will return a error like "resource already cancelled" and at the same time I'm not creating a new resource, just making a status change in a known resource?

I would use
DELETE /authorization/1234
There's a whole debate around DELETE's idempotence on previously deleted resources. See https://evertpot.com/idempotence-in-http/ and https://leedavis81.github.io/is-a-http-delete-requests-idempotent/
The bottomline here is that idempotence makes sense in a mathematical world where there's always one result, but in HTTP you get two different outcomes -- the server's response and the resource's new state. It becomes difficult identifying what is idempotent and what is not.
In such areas where the HTTP specification is not clear, I recommend pargmatism over dogmatism.
If you really want the client to know if they deleted the resource themselves or if someone else did, then I see no problem responding 404 on a previously deleted resource.
If you don't care, or think that it will never happen (either because there's not enough concurrent access or because all clients always do a GET moments before sending the DELETE), you can happily stick to 204 in all cases.

Related

HTTP Status Code when the Parent Resource is not longer live

In our Organization, the items in our inventory are called stocks. Each stock has a sortScore associated with it. An internal API is exposed to another team in the organization to update the sortScore of the stock.
PUT /api/stock/{stockid}/sortscore
This request updates the sortScore of the stock. It may happen that the stock is no more live(it is sold), but for some reason, the internal API for updating the sortScore is still hit by another team.
According to me, here the resource is sortScore and the parent resource is the stock, which isn't live anymore(It used to be live at some point of time). Even though the stock is no more live, we still keep a record of it somewhere in our Database.
Some of us are having arguement about the HTTP Status code we are sending when the stock is not live anymore. Since the resource is not available at the intended Resource Identifier(URL), we are sending NOT FOUND. But some of our colleagues are saying that since the stock used to be live at some point of time, the Status Code should be of 2xx series with the message that This stock is not live anymore.
Now I am here to know what the people from stackoverflow thinks about what the correct answer should be?
So an important thing to understand about REST is that the concepts of "parent resource" and "child resource" don't really exist.
As far as REST, and HTTP, is concerned; /a/b/c doesn't necessarily have anything to do with /a/b or /a/b/c/d. Each resource is its own thing, with its own representation(s).
So you should be thinking about
PUT /api/stock/{stockid}/sortscore
In isolation.
Since you aren't allowing the clients to change the resource, using 2xx status code is not the right idea. A 2xx status code would not only indicate that the request had been successful, but would also encourage consumers to flush their caches and so on.
404 Not Found isn't quite the right idea, since a PUT should create a resource if there isn't one present already.
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload
It sounds to me as though "it's not live any more" means that consumers are no longer allowed to modify the state of the resource. That in turn suggests that the status code you want is 405 Method Not Allowed
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource.
A common status code for this is 409 Conflict. The idea of 409 Conflict is that even though everything is fine with your request, the current state of the server prevents it from being successful.
The current state in your case is a different resource not existing anymore. This is in conflict with the PUT request you are doing.

POST/PUT response REST in a CQRS/ES system

I'm implementing a CQRS/ES based system with a RESTful interface which is used by a webapp.
When performing certain actions e.g. creating a new profile I need to be able to check certain conditions, such as uniqueness of the profile ID, or that the person has the right to create a resource under a group. Which means I have a couple of options:
Context: POST/profiles { "email": "unique#example.com" }
From my REST API return 202 from my service with a location of the new resource where my client can poll for it. In this case, however, how do I handle errors as in effect the view will not exist or ever exist.
Create a saga on the initial request then dispatch the event. Once my service creates the view or finds the error then the result is written to the saga. When the saga has been completed return the result to the user.
From these two options - the second seems more reasonable to me, if not more complex. Is this a viable option for building RESTful request/response models on a CQRS/ES event sourced backend?
Yes, the second solution seems to better fit the business.
From what I understand from your case, from the DDD point of view, the creation of a user profile is a business process, with more than one steps (verifying the uniqueness of the profile, creating the profile and recovering from a duplicate profile situation). This process acts like an entity, it starts, runs and ends with a result (success or error). Being an entity it has an ID and it can be viewed as a REST resource. A Saga will be responsible for executing it.
So, in response to the client's request you send the URI of the process resource where the client can poll for the status. In case of error, it reads the error message. In case of success, it gets the URI of its profile.
The first solution can still be used if the use-case is simpler, if the command can be executed synchronously and the client gets the final result (error or success) as an immediate response.
From my REST API return 202 from my service with a location of the new resource where my client can poll for it. In this case, however, how do I handle errors as in effect the view will not exist or ever exist.
The usual answer here is that, as part of the 202 Accepted response, you include monitoring information
The representation sent with this response ought to describe the request's current status and point to (or embed) a status monitor that can provide the user with an estimate of when the request will be fulfilled.
In other words, a link to a resource that will change when the accepted request is finally run.
So in describing the protocol, in addition to the resource that you create, you'll also need to document the representation used when you defer the work for later, and the representation used by the monitor.
When the saga has been completed return the result to the user.
Depending on the work, that may be overkill.
Which is to say, you are raising two different questions here; one of those is whether the request should be handled synchronously (don't respond until the work is done) or asynchronously (return right away, but give the client the means to monitor progress).
The other question is how the work looks from the business layer. If you are going to need multiple transactions to make the change, and if you may need to "revert" previously committed transactions in some variants of the process, then a saga (or a process manager) makes sense.
Set Validation -- the broader term for enforcing an invariant like "uniqueness" -- is awkward. Make sure you study, and ensure that you and the business understand the impact of having a failure.

What's an appropriate HTTP status code to return by a REST API service for an expired entity?

Let's say we have an online shop and receive a valid request of updating some order.
The request is valid by itself, but let's say that the order has an expiration time, and it has already expired, so this request is unprocessable in fact.
I doubt if it is a kind of validation error or not. Because, as I stated above, the request itself is valid; and a request sender might not know that order has already expired.
What's an appropriate HTTP status code to return by a REST API service for such a situation?
Warning: Due to the general requirements for the product, it should be some of 4XX error codes!
UPD: More information: this putative "order" still exists, even being expired. It is possible to retrieve it, but it is not possible to operate it anymore. That's why the code 404 (for example) is not appropriate.
My own version:
I think that for such situation the 410 status code is most appropriate:
The 410 response is primarily intended to assist the task of web
maintenance by notifying the recipient that the resource is
intentionally unavailable and that the server owners desire that
remote links to that resource be removed. Such an event is common
for limited-time, promotional services and for resources belonging to
individuals no longer associated with the origin server's site. It
is not necessary to mark all permanently unavailable resources as
"gone" or to keep the mark for any length of time -- that is left to
the discretion of the server owner.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html:
The requested resource is no longer available at the server and no
forwarding address is known. This condition is expected to be
considered permanent. Clients with link editing capabilities SHOULD
delete references to the Request-URI after user approval. If the
server does not know, or has no facility to determine, whether or not
the condition is permanent, the status code 404 (Not Found) SHOULD be
used instead. This response is cacheable unless indicated otherwise
I'll say that 400 fits better than 410.
IMO 410 (Gone) doesn't fit because the resource is not gone. It's still there, simply in kind of a final (in this case expired) state.
400 means BadRequest. Per my interpretation, trying to UPDATE something, that is not updatable (trying to update expired item) is a BadRequest.
I believe, that 400 is not only for badly formatted requests, but also for requests that does not meet internal business logic validation (in this case, not updating an expired item, is an internal business logic).
Use 410 Gone.
The target resource is no longer available at the origin server and that this condition is likely to be permanent.
I would choose one of these:
400 - Bad request
410 - Gone
from : https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

REST: Prevent creation of duplicate resources via conditional POST?

I've been searching for best practices for preventing the accidental creation of duplicate resources when using POST to create a new resource, for the case where the resource is to be named by the server and hence PUT can't be used. The API I'm building will be used by mobile clients, and the situation I'm concerned about is when the client gets disconnected after submitting the POST request but before getting the response. I found this question, but there was no mention of using a conditional POST, hence my question.
Is doing a conditional POST to the parent resource, analogous to using a conditional PUT to modify a resource, a reasonable solution to this problem? If not, why not?
The client/server interaction would be just like with a conditional PUT:
Client GETs the parent resource, including the ETag reflecting its current state (which would include its subordinate resources),
Client does a conditional POST to the parent resource (includes the parent's ETag value in an If-Match header) to create a new resource,
Client gets disconnected before getting the server response, so doesn't know if it succeeded,
Later, when reconnected, the client resubmits the same conditional POST request,
Either the earlier request didn't reach the server, so the server creates the resource and replies with a 201, or the earlier request did reach the server, so the server replies with a 412 and the duplicate resource isn't created.
Your solution is clever, but less than ideal. Your client may never get his 201 confirmation, and will have to interpret the 412 error as success.
REST afficianados often suggest you create the resource with an empty POST, then, once the client has the id of the newly created resource, he can do an "idempotent" update to fill it. This is nice, but you will likely need to make DB columns nullable that wouldn't otherwise be, and your updates are only idempotent if no-one else is trying to update at the same time.
According to ME, HTTP is flaky. Requests timeout, browser windows get closed, connections get reset, trains go into tunnels with mobile users aboard. There's a simple, robust pattern for dealing with this. Unsafe actions should always be uniquely identified, and servers should store, and be able to repeat if necessary, the response to any unsafe request. This is not HTTP caching, where a request may be served from cache but the cache may be flushed for whatever reason. This is a guarantee by the server application that if an "action" request is seen a second time, the stored response will be repeated without anything else happening. If the action identity is to be generated by the server, then a request-response should be dedicated just to sending the id. If you implement this for one unsafe request, you might as well do it for all of them, and in so doing you will escape numerous thorny problems: successive update requests wiping out other users' changes, or hitting incompatible states ("order already submitted"), successive delete requests generating 404 errors.
I have a little google doc exploring the pattern more fully if you're interested.
I think this scheme would work. If you want to ensure POST does not result in duplicates, you need the client to send something unique in the POST. The server can then verify uniqueness.
You might as well have the client generate a GUID for each request, rather than obtaining this from the server via a GET.
Your steps then become:-
Client generates a GUID
Client does a POST to the resource, which includes the GUID
Client gets disconnected and doesn't know if it succeeded
Client connects again and does another POST with the same GUID
Server checks the GUID, and either creates the resource (if it never received the first POST) or indicates that this was a duplicate
It might be more restful to use PUT, and have the client decide the resource name. If you did not like the choosen name, you could indicate that you had created the resource but that it's canonical location was somewhere of the server's choosing.
Why not simply do duplicate detection on the server based on the actual resource, using whatever internal mechanism the server chooses to use.
It's just safer that way.
Then you return the URL to the appropriate resource (whether it was freshly created or not).
If the parents ETag is based on the state of sub resources, then it's not a reliable mechanism to check for "duplicate resources". All you know is that the parent has "changed", somehow, since last time. How do you even know it's because your old POST was processed after disconnect? Could be anything changed that ETag.
This is basically a optimistic locking scenario being played out, and it comes down to another question. If the resource is already created, what then? Is that an error? Or a feature? Do you care? Is it bad to send a creation request that's silently ignored by the server when the resource already exists?
And if it already exists, but is "different" enough (i.e. say the name matches but the address is different), is that a duplicate? is that an update? is that a error for trying to change an existing resource?
Another solution is to make two trips. One to stage the request, another to commit it. You can query the status of the request when you come back if it's interrupted. If the commit didn't got through, you can commit it again. If it did, you're happy and can move on.
Just depends on how unstable your comms are and how important this particular operation is whether you want to jump through the hoops to do it safely.

Correct HTTP status code for a not satisfiable REST request

I currently develop a task queue with a RESTful API.
In order to handle a task, a worker has to create a lease.
PUT .../leases
If the task queue has tasks available, this will succeed, a lease will be created and the server responds with status 201.
I am unsure how to handle this case when no tasks are available. It is not possible to create a lease, when no tasks are available. Which HTTP status code would be appropriate for this case?
204 No Content - The client hasn't made anything wrong, but there is no data.
400 Bad Request - This is imho not applicable, as it means "the request could not be understood by the server", which is not the case
In the meantime I thought that this approach might not be ideal. Either I use 503, as recommended of Brian and also backed by a passage of REST in practice, or I change the whole process.
I was thinking of leases which could be created tentatively. That means
PUT to /leases
Either create a lease, assign a task and respond with 201 or create a tentative lease and respond with 202
Tentative leases will stay for some time. If tasks gets available, they are assigned to the tentative leases. If there is no task for a specific period of time, the lease gets deleted and the server will respond with 410
The client should then start again with 1.
Since the resource is controlled by the server and there's nothing the client can do to influence the outcome, a 500-range code would be most appropriate.
503 - Service Unavailable sounds right to me. It implies that the server has not got enough resources available to meet the needs of the request. You should probably also return a meaningful error in the body of the response to make it explicitly clear that it failed because no leases/tasks were available, but that might not be the case sometime in the future.
404 - Not Found could be used. Wikipedia summarizes it as:
The requested resource could not be found but may be available again in the future. Subsequent requests by the client are permissible.
404 almost works, but I think of it as the resource you are dealing with and you are doing a PUT to create a resource. Of course it doesn't exist that's why you are creating it.
I would agree with your first thought on the 400 Bad Request in a narrow sense of the definition. But if you broaden the definition to include anything that could go wrong with the request then it would fit your situation and I think it's acceptable to do just that. For example we send a 400 back if the request didn't meet the schema we were expecting and if there are validation errors on the resource. For our service if we can programmatic determine that this is a bad request we send back a 400.
For your service the creation of a lease when no tasks are available constitutes a bad request, and you can send the 400 with text explaining what the problems is. I think the 400 was meant for a broader definition then what you are holding it to.
I don't think the 500's work because they are more unhandled stuff, and this is a case you can handle and provide informational responses to.
Hope this helps.
IIS sends a 405 Method Not Allowed if I try to use an unsupported method (ie PUT when it expects a GET). And it sends a 404 Not Found if the endpoint doesn't exist at all.