Suppose I have an endpoint that supports creating new messages. I am avoiding the creation of two times the same message in the backend, in case the user tries to push the button twice (or in case the frontend app behaves strangely).
Currently for the duplicate action my server is responding with a 303 see other pointing to the previously created resource URL. But I see I could also use a 302 found. Which one seems more appropriate ?
Note that the duplicate avoidance strategy can be more complex (eg for an appointment we would check whether the POSTed appointment is within one hour of an existing one)
I recommend using HTTP Status Code 409: Conflict.
The 3XX family of status codes are generally used when the client needs to take additional action, such as redirection, to complete the request. More generally, status codes communicate back to the client what actions they need to take or provide them with necessary information about the request.
Generally for these kind of "bad" requests (such as repeated requests failing due to duplication) you would respond with a 400 status code to indicate to the client that there was an issue with their request and it was not processed. You could use the response to communicate more precisely the issue.
Also to consider, if the request is just "fire and forget" from the client then as long as you've handled the case for duplication and no more behavior is needed from the client it might be acceptable to send a 200 response. This tells the client "the request was received and handled appropriately, nothing more you need to do." However this is a bit deceptive as it does not indicate the error to the client or allow for any modified behavior.
The JSON:API specification defines:
A server MUST return 409 Conflict when processing a POST request to create a resource with a client-generated ID that already exists.
Related
Often times I see the following for polling:
Send a request and get back a unique ID.
Poll a "Status" endpoint, which tells the client when the request has been completed.
Send a request to fetch the response.
Why steps (2) and (3) can not be combined?
If the response isn't ready yet, it'll return no response back, and some status indicating that.
If it is ready, it'll return the response.
Why are (2) and (3) often separate steps?
Is it ready is a boolean true/false and a response can be anything. In general it's easier to call "is it ready" then write logic to handle true and false than to write logic to get a response, determine if the response is not ready or is the data type you need.
In this way, the logic is all client side but if you combined them you'd need to have logic on both client and server (both to say it's not ready and to handle the actual response). You could do it but keeping it separate just keeps things neater.
This pattern is generally defined by the HTTP 202 status code, which is the HTTP protocol's mechanism of initiating asynchronous requests.
We can think of a 202 response as indicating that a job has been created. If and when that job executes, it may (or may not) produce some business entity. Presumably the client receiving a 202 is ultimately interested in that business entity, which may (or may not) exist in the future, but certainly does not exist now, hence the 202 response.
So one simple reason for returning a pointer to a job status is because the job status exists now and we prefer to identify things that exist now rather than things that may (or may not) exist in the future. The endpoint receiving the request may not even be capable of generating an ID for the (future) business entity.
Another reason is status codes. A status endpoint returns a custom job status capable of describing unlimited potential states in which a job can exist. These job states are beyond the scope of HTTP status codes. The standard codes defined by the w3 already have precise definitions; and there simply is no standard HTTP status code that means "keep polling".
The reason is that they are different resources from REST perspective.
Let's examine this a bit through an example:
If you want to place an order then first you have to submit an order request
Then there is lengthy, asynchronous process in the background which checks the payment validity, the items availability in the inventories, etc.
If everything goes fine then there will be an order aggregate with some subelements (like order items, shipping address, etc.)
From REST perspective:
There is a POST /orders endpoint to place an order
There is a GET /order_requests/{id} endpoint to retrieve order request
There is a GET /orders/{id} endpoint to retrieve order details
Whenever the order and all related sub-resources are created then the 2. endpoint usually responds with a 303 See Other status code to ask the consumer to redirect to GET /orders/{id}.
If a web application returns an HTTP 4xx response back to the client should the client assume that the communication was stateless? If this is true, should web applications return a 5xx response in the case where a client's request results in a state change but further processing fails due to an issue with the client's request (we can assume that top layer validation cannot detect this case and recovery is not possible).
Is there an ISO standard developers can refer to that discusses what is expected as far as application state is concerned when an HTTP 4xx is returned? Is this covered in RESTful architecture?
So, working backwards -- the semantics of 5xx response messages and 4xx response messages provide the same guarantees about changes to resource state.
For instance, HTTP caches will treat both 4xx and 5xx as an "error response".
HTTP standardizes the meanings (semantics) of HTTP response codes, but it doesn't constrain implementations - your server is free to return whatever message you want, so long as you describe the message you return appropriately.
If you are expecting general purpose clients to understand that there was a problem with the request itself; then you should normally choose to respond with a representation that explains the actual problem, and use the correct HTTP meta data (including the response code) so that intelligent clients can do useful things.
The fact that your server actually did some work that changed the state of the exposed resources is "just" an implementation concern. There's fundamentally no difference between the case you describe, and the case where this request had no effect, but some other request to the server made changes that this client doesn't know about (yet).
If you want the general purpose client to understand that the resource has changed (and that previously cached responses should no longer be used), then you need to return a response with a non-error status code.
At a higher level, the important idea to understand is that a REST API is a facade - it provides the illusion that our sophisticated service is "just" an HTTP compatible document store.
I work on splitting monoliths into microservices. With the monolith, I had a single source of truth and can just GET /resources/123 right after the PATCH /resources/123 and be sure that the database has the up-to-date data I need.
With microservices and CQRS in place, there is a risk that the query service has not seen yet the latest update to the record when I perform a GET request.
What is the best or standard approach to making sure that the client receives back the up-to-date value? I know that the client may compare resource versions that he receives after PATCH and after GET and retry requests, but is there a known API design to tell the server something like GET /resources/123 and wait up to 5 sec for the resource version 45 or bigger to arrive?
Since a PATCH request allows a response body, to my mind there's nothing wrong with the response including the object after patching. The requestor who sent the PATCH can use the response in lieu of a GET; for others, the eventual consistency delay for the GET isn't observable (since they don't know when the PATCH was issued).
CQRS means to not contort your write model for the sake of reads. If there's a read that is easily performed based on the write model, that read can be done against the write model.
Generally a better design might be for the PATCH request to delay its own response, if that's an option.
However, your GET request can also just 'hang' until it's ready. This generally feels like a better design than polling.
A client could indicate to the server how long it's willing to wait using a Prefer: wait= header: https://datatracker.ietf.org/doc/html/rfc7240#section-4.3
This could be used both for the GET or the PATCH request.
I don't think there's a standard HTTP way to say: this resource is not available right now, but will be in the future. However, there is a standard HTTP header to tell clients when to retry the request:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
This is mainly used for 429 and 503 errors but neither seem appropriate here.
Frankly this is one of the first thing I've heard in a while that could be a good new HTTP status code. 425 Too Early exists but its a different use-case.
I have an RESTful API that calls another remote webservice. In general I have to query this remote service for every request that comes to my specific API function, and in my code I am wrapping and/or modifying parts of the result.
However it is possible that this remote service is not answering in time or throws an error. What is the most logical response that my API should throw then? I am specifically thinking about:
HTTP 500 - however this gives the client no information what is happening
HTTP 503 with a Retry-After header - then the client clearly sees this is an error and can query again later
HTTP 200 and returning an empty result
HTTP 200 and returning an error message or something like that
...or doing something completely different?
It all depends on what you want your API to convey to your client.
500: client cannot fetch his resource and does not know whether he should just bombard your server with another request, but at least knows it MIGHT exist
503: client cannot fetch his resource, but at least knows it MIGHT exist and can retry later in X amount of time.
200 *Empty response*: client is told his resource is empty and everything is ok, so probably will not come back while the resource could be not empty and was available a second later (Kind of misleading).
200 *Error message*: client is told everything is ok, but receives in your context an error message. (This is wrong and totally contradicting itself/yourself!)
My advice:
Do the 503
I am building an API and I was wondering is it worth having a method in an API that returns the status of the API whether its alive or not?
Or is this pointless, and its the API users job to be able to just make a call to the method that they need and if it doesn't return anything due to network issues they handle it as needed?
I think it's quite useful to have a status returned. On the one hand, you can provide more statuses than 'alive' or not and make your API more poweful, and on the other hand, it's more useful for the user, since you can tell him exactly what's going on (e.g. 'maintainance').
But if your WebService isn't available at all due to network issues, then, of course, it's up to the user to catch that exception. But that's not the point, I guess, and it's not something you could control with your API.
It's useless.
The information it returns is completely out of date the moment it is returned to you because the service may fail right after the status return call is dispatched.
Also, if you are load balancing the incoming requests and your status request gets routed to a failing node, the reply (or lack thereof) would look to the client like a problem with the whole API service. In the meantime, all the other nodes could be happily servicing requests. Now your client will think that the whole API service is down but subsequent requests would work just fine (assuming your load balancer would remove the failed node or restart it).
HTTP status codes returned from your application's requests are the correct way of indicating availability. Your clients of course have to be coded to tolerate and handle them.
What is wrong with standard HTTP response status codes? 503 Service Unavailable comes to mind. HTTP clients should already be able to handle that without writing any code special to your API.
Now, if the service is likely to be unavailable frequently and it is expensive for the client to discover that but cheap for the server, then it might be appropriate to have a separate 'health check' URL that can quickly let the client know that the service is available (at the time of the GET on the health check URL).
It is not necessary most of the time. At least when it returns simple true or false. It just makes client code more complicated because it has to call one more method. Even if your client received active=true from service, next useful call may still fail. Let you client make the calls that they need during normal execution and have them handle network, timeout and HTTP errors correctly. Very useful pattern for such cases is called Circuit Breaker.
The reasons where status check may be useful:
If all the normal calls are considered to be expensive there may be an advantage in first calling lightweight status-check method (just to avoid expensive call).
Service can have different statuses and client can change its behavior depending on these statuses.
It might also be worth looking into stateful protocols like XMPP.