I want to create or update an item in one go with the following request:
PUT /items/{id}
Should I return 201 Created if the item has been created and 204 No Content when it has been updated? Or should I return the same status for both actions?
The answer is clearly stated in RFC2616, section 9.6:
If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
TL;DR
Use 200 OK in both cases if the distinction isn't important to clients.
Use 201 Created upon creation, and 200 OK upon update, if the distinction is important.
Details
With RESTful design, there's no single, correct way of doing things, but I've often found that the original HTTP status code specification provides good guidance.
It's always fine to return 200 OK if you don't expect the client to take separate action based on the response, but you can provide more information if you think the client is going to need it. Just be aware that clients may come to expect that of your API, so once you start providing more details, you can't easily change your mind.
That said, if you want to return 201 Created, then according to the specification:
The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate.
As an example, you can put the location in the Location header, but you can also put it in the body of the response (but then you must document the structure and content-type of that body).
When it comes to 204 No Content responses, they create dead ends for link-following clients, so if you're creating a true level 3 REST API then you should avoid that response type as a courtesy to clients.
Related
I'm working on a REST API that requires multiple steps/validations to create a resource, then making a POST /transfer might not create an actual transfer resource (because it needs an extra steps), but is not failing as it will trigger the second step/validation.
In this answer the response is an incomplete or pending transaction with an id, and the resource includes endpoints to finish the transaction, like /transaction/123/commit or in my case /transaction/123/verification/432 where the client can continue, abort or finish the transaction processing.
But what are the possible response codes on that endpoints? Does /transaction/123/commit actually returns 201 because it create the transaction or the transaction is created when it reach pending state?
201 (Created)
Status code 201 (Created) indicates the creation of (at least one) new HTTP resource. The URL of the created resource is sent in the response’s Location header.
If POST /transfer creates the resource /transaction/123/commit — that is, if requests to /transaction/123/commit might now succeed where previously you’d have 404 (Not Found) — then it is correct to respond to POST /transfer with 201 and Location: /transaction/123/commit.
If POST /transfer creates several resources, then Location must be the “primary” one (in some sense).
If POST /transaction/123/commit does not create any new resource, then it is incorrect to respond with 201, even if it does create something else (like an internal database record).
If you can’t come up with a URL to send in Location, that probably means you’re not creating any new resource, in which case 201 is incorrect.
Note: Location is always relative to the request URL, not to an “API root” or any such concept you might have. For example, if POST /api/v1/foo/bar creates /api/v1/foo/bar/baz, correct values for Location would include bar/baz and /api/v1/foo/bar/baz, but not /foo/bar/baz.
200 (OK)
Status code 200 (OK) indicates general success. It can be used in most successful responses. It’s a kind of a safe fallback: it doesn’t say much, thus it’s guaranteed not to say much wrong and confuse the client.
If POST /transaction/123/commit succeeds without creating a new resource, then it is correct to respond with 200.
204 (No Content)
Except for responses to GET/HEAD, status code 204 (No Content) is mostly the same as 200. If you use 204 to say something different than 200, you’re probably making up a local convention — same as making up your own status code 275.
Other
IANA maintains a registry of standardized status codes. You can look there for a status code that is standardized to mean exactly what you want to say.
You generally don’t want to use a non-standard status code, or to use a standard status code incorrectly, because that would preclude a uniform interface, which is kind of the whole point of REST.
If you find yourself struggling all the time to uphold a uniform interface, it’s possible that you don’t need REST at all, and should be doing RPC instead.
When you use PUT endpoint to create resource in REST api, what should the endpoint return for subsequent calls after returning 201(created) for the first call? 403(cannot create since the resource already exist)? 200(updated to the same exact object?) if you change the status code after one call(201-> 200 or 403), isn't that a violation of idempotency? I looked everywhere but all I can find is you can use PUT to create but nowhere it said about status code change after resource creation.
In short my question is that PUT is an idempotent method, but when it is used in resource creation, can it still change it's return status code from the following calls?
p.s.
After first calls, it will be idempotent(constantly 403 or 200). And ideally I want to be able to tell the client that the resource is already created and you shouldn't call this again.(403)
I know using POST is an alternative but as ID is already known to client at the point of creation I wanna use PUT method but want to know the proper REST way in terms of idempotency.
===================================================================
References of Using PUT endpoints for creating resources
http://restcookbook.com/HTTP%20Methods/put-vs-post/
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations. In
contrast, the URI in a PUT request identifies the entity enclosed with
the request -- the user agent knows what URI is intended
9.6. PUT If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource
is modified, either the 200 (OK) or 204 (No Content) response codes
SHOULD be sent to indicate successful completion of the request.
http://zalando.github.io/restful-api-guidelines/http/Http.html
PUT requests are usually robust against non-existence of resources by
implicitly creating before updating
successful PUT requests will usually generate 200 or 204 (if the
resource was updated - with or without actual content returned), and
201 (if the resource was created)
Idempotency is about the server state - not about the responses. E.g. DELETE is idempotent, but after the 2nd try the resource will not be found and you may choose to respond with 404. But the state of the server is going to be the same - the resource is deleted.
Same with PUT - you can invoke it multiple times, but the state of the server will always be the same after the operation is finished.
Ideally though you could reuse PUT for updating the resources. So when the 2nd request is arrived you can use that for updating instead of returning errors. That will probably simplify implementation and the contract.
This question already has answers here:
HTTP status code for update and delete?
(10 answers)
Closed 5 years ago.
In REST, suppose the client invoked the findAll method (GET)- which would simply return the list of entities(DTOs) to the client with HTTP status code 200. Now, let's say client has invoked a DELETE method removeObject(Object object). The object in the parameter doesn't exist in the database, and typically it would return HTTP status code 400. I want the client to know this real reason of 400 in a more manageable way (less panic) . Now the need of a status code / description arises which wasn't necessary during the GET method.
I want the client to get a consistent RESPONSE for all the messages. Is there any guideline / best practices for what to return in REST based APIs?
What do you mean by REST? Let's suppose, we refer to Roy Fielding and Http 1.1 standard.
According to standard, DELETE is idempotent method. I.e. if you request DELETE more than once, side-effects would be the same. I.e. all the same record in DB would be marked as "deleted" or be absent.
First of all, to request DELETE, you request a resource. Say, http://some.url/to/resource. If it never was present - you should respond with 404.
Section "9.7 DELETE" of the standard says:
A successful response SHOULD be 200 (OK) if the response includes an
entity describing the status, 202 (Accepted) if the action has not
yet been enacted, or 204 (No Content) if the action has been enacted
but the response does not include an entity.
If you don't remove a record completely from DB and want to communicate on subsequent requests that resource had been deleted and is no longer available, then the standard, section "10.4.11 410 Gone", says:
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.
But using this response code or providing it for some time period is not necessary, and response could be also 404. So use it, if you want to differentiate, whether a resource had been deleted or had never been present.
Status code of 400 is fine but you then also return some object that the frontend can parse and comprehend (i.e. json). This way, your frontend gets more info about the error and optionally override it before presenting it to the user. Some pretty basic and barely functional pseudocode:
Backend:
return(status_code=400,
body={message: {type: "error", description: "some text here"})
Frontend:
if (status_code >= 400):
console.log(json.loads(response).message.description)
I would expect an Rest api to respond with a 200 when deleting an object. Anything else usually means something went wrong with my request.
If I requested an object after it had been deleted, I would then expect the API to return 404, or something of that nature.
Please refer to section 9.7 of RFC 2616
https://www.rfc-editor.org/rfc/rfc2616#section-9.7
I am designing a RESTful API that is managing favorites. Each favorite resource can contain details of two items that are considered as part of the favorite.
HTTP POST /favorites
{ "item1" : "ball",
"item1-ID" : "1",
"item2" : "bat",
"item2-ID" : "2"
}
Please excuse the rudimentary JSON payload. The focus is however on the semantics of the POST
The above POST method creates a new favorite resource (that contains a ball (ID 1) and a bat (ID 2))
My question is with regard to the expected behavior when the same POST request is sent twice. The first request will create a favorite (as expected). What should happen when the second request is sent?
1) Signal an error with 409
2) Signal a success with 201
1) is not idempotent (as POST is), while 2) makes POST idempotent.
Which is the correct approach?
You are thinking about this in the wrong way. If a POST creates a new resource then the resource should have a URL that identifies it (e.g., http://.../favorite/1). When the second POST with the same payload happens, is a new resource created? If so, then you have two separate resources with unique URLs. If you application does not create a new resource, then the second POST would return the same URL as the first one.
Edit
The POST section of RFC7231 does not prohibit it from being implemented in an idempotent manner. It does provide some guidance though:
If a POST creates a new resource, then it SHOULD send a 201 (Created) response containing a Location header identifying the created resource
If the result of a POST is equivalent to an existing resource, then the server MAY redirect the UA to the existing resource by returning a 303 (See Other) with the appropriate Location header
POST is not required to change the state of a resource. However, GET and HEAD are required to be idempotent. I'm not aware of any method that is required to change state on the server.
Personally, I implement resource creating POST methods as returning a 303 redirect to the canonical URL for the resource as a matter of practice. I wasn't aware of the RFC distinguishing status codes for resource creation and re-use responses. The benefit of this approach is that it removes the need to include the created resource in the POST response and the GET to the canonical URL will cache the response in any intermediate caches that may be present. It also allows for the implementation of intelligent clients that do not retrieve the response and use the canonical URL (from the Location header) instead.
In your case, I think that I would adopt the 303 approach provided that a favorite has a URL of it's own; 201 would be strange if it did not. If there is very good reason for distinguishing the creation and re-use cases in the response, then a 201 when the new resource is created and a 303 when it is reused is appropriate. What I would not do is to return a 409 unless your application requires you to deny the creation of a resource that already exists.
To me, as you pictured it, it should create a new favorite. But this feels strange for almost any application. What if:
your favorites could be defined as non-repeatable if they are exact copies
you could send an ID with the favorite (not a good idea, as it'd be client-based), and insert or update based on that
you could send some other unique field and use that to define whether it is a "create" or an "update" (ie. "favorite name" or "position in menu")
As you see, it all depends on your application.
Maybe you can get some ideas from this article I happened to write some time ago: A look into various REST APIs . Don't miss the summary at the bottom.
What should happen when the second request is sent?
It all depends on your implementation . Say if you have some logic in your controller that checks if ID 1 and ID 2 exist in the data base then update the value else create the new record.
The whole thing is not depended on POST request.
AND FYI HTTP response code for success is 200 and not 201.
Your current approach is not correct and the question is not a JAVA question
In general, it depends on you, how you want to design the underlying system. In most cases, POST creates a new resource (Yes, there are instances when you use POST and not create anything new. For example, you have a use-case where in you want to search on a very long list of the parameters and GET might not be the way!. This is completely acceptable and not a violation of REST principles.)
Commenting on your specific case,
What should happen when the second request is sent?
You should ask the following questions to yourself.
Is having a duplicate request (a request with the same payload/headers/time-stamp etc.) a "different" request for your system ? If YES - treat it normally as if it's not duplicate. I assume that the next systems to which the request is going are also understanding this as a new request, otherwise they could fail and flag error. For example, MySQL could throw Duplicate Primary Key error (Refer: Error Code: 1062. Duplicate entry 'PRIMARY')
If the answer to (1) is NO - Is the duplicate occurrence of this request an expected behaviour of the clients ? (For example, you tend to get duplicate requests from mobile if it's intermittently getting the network.) If YES - return 200 OK. Note the idempotency here.
If the answer to (2) is NO - throw 409 conflict with a custom error-code which client can handle and react accordingly. I would also investigate the unwanted behaviour of client on throwing the duplicate requests and fix it if that's doable.
Duplicate idempotent POST requests should return the previously created resource in response if the status code of the response was 200. Idempotency Enforcement Scenarios
If I am POSTing a new resource with 100 fields, and the server adds 3 fields of its own, like date created, status, etc., is it RESTful to only return a mini-representation of the resource that includes only the 3 new fields in the body of the 201 CREATED response?
Then the client can just add those 3 new fields to its local representation. I have seen exhortations that one should always send the full representation, but it seems wasteful of bandwidth to return all 103.
The 201 response entity (the body of the response itself) doesn't have to be, or is considered by any http client as, the resource you just created.
It's a representation that describes the result.
If you want people to access the resource that was just created, they can do so by issuing a request to the URI in the Location header that comes back with a 201.
If you return an entity body in your 201, it is not considered by HTTP as being the resource you just created, so you can return whatever you want.
The important thing is the media type of the entity you return. If that entity is known by the client, be it that it's a smaller or the full version of the entity, they'll know what to do with it. If you expect the clietn to "know" that the returned media type to a 201 is a minimized version, you're enforcing strong coupling to your own protocol, which is in breach of ReST principles.
There are no rules that claim you need to return the full response in the REST dissertation or the HTTP RFC. The latter (RFC 2616, HTTPbis version) has this to say about the 201 Created status code:
If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
Returning the information that has been added is a reasonable and perfectly RESTful HTTP-compliant idea.
It's entirely up to you what you respond with though it might be an idea to provide a link to more information about the resource. If you want to get really fancy you can specify a microformat