Status code when using PUT endpoint to create resource in REST api - rest

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.

Related

Should HTTP PUT create a resource if it does not exist?

Lets suppose that someone performs a PUT request on my endoint:
/resources/{id}
However there is not resource with the given id stored in my PostgreSQL database.
According to the RFC 2616, I should create the resource if I am capable to:
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
Would be okay to create the resource with the provided id? As manually assigning ids on database insert is not the best practice.
Should I return a 404 error if the creation of the resource is not possible?
First of all, you are using an obsolete document: The RFC 2616 is no longer relevant nowadays and anyone using such document as reference should stop right away.
Quoting Mark Nottingham who, at the time of writing, co-chairs the IETF HTTP and QUIC Working Groups:
Don’t use RFC2616. Delete it from your hard drives, bookmarks, and burn (or responsibly recycle) any copies that are printed out.
The old RFC 2616 has been supplanted by the following documents that, together, define the HTTP/1.1 protocol:
RFC 7230: Message Syntax and Routing
RFC 7231: Semantics and Content
RFC 7232: Conditional Requests
RFC 7233: Range Requests
RFC 7234: Caching
RFC 7235: Authentication
If you are looking for methods, status codes and headers definitions, then the RFC 7231 is the document you should refer to.
Having said that, let's go back to your question.
Should HTTP PUT create a resource if it does not exist?
It depends.
But, if your application generates resource identifiers on behalf of the client, as you mentioned in your question, then you should use POST instead of PUT for creating resources.
Some parts of the PUT method definition are quoted below. The last sentence seems to be the most relevant to you (highlight is mine), supporting what I've just mentioned above:
4.3.4. PUT
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. [...]
If the target resource does not have a current representation and the PUT successfully creates one, then the origin server MUST inform the user agent by sending a 201 (Created) response. If the target resource does have a current representation and that representation is successfully modified in accordance with the state of the enclosed representation, then the origin server MUST send either a 200 (OK) or a 204 (No Content) response to indicate successful completion of the request. [...]
Proper interpretation of a PUT request presumes that the user agent knows which target resource is desired. A service that selects a proper URI on behalf of the client, after receiving a state-changing request, SHOULD be implemented using the POST method rather than PUT. [...]
Should I return a 404 error if the creation of the resource is not possible?
That's seems to be an accurate status code to be returned, as no representation has been found for the requested resource:
6.5.4. 404 Not Found
The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. [...]
Now, for the sake of completeness, find below some relevant quotes on the POST method definition, which should be used to create resources in the scenario described in your question:
4.3.3. POST
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others):
[...]
Creating a new resource that has yet to be identified by the origin server;
[...]
If one or more resources has been created on the origin server as a result of successfully processing a POST request, the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created and a representation that describes the status of the request while referring to the new resource(s).
While the 201 status code indicates that a new resource has been created, the Location header indicate where the newly created resource is located. If no Location header is provided, then the client should assume that the resource is identified by the effective request URI:
6.3.2. 201 Created
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created. The primary resource created by the request is identified by either a Location header field in the response or, if no Location field is received, by the effective request URI. [...]
In short, it depends wheter the payload you want to store violates any constraint the server has for resources or not.
In general I'd say it should attempt it as the client explicitly expresses his intent to store that particular representation at the target URI. The server should though perform constraint checks before! Usually, in a real REST scenario though, the client should use URI that are provided by the server and not just chose any URI on its own. Thereby, a server should be in control of its namespace, as such using PUT to create resources is not recommended here by default.
With that being said, as PUT is idempotent while POST being not, some clients might want to benefit from this property. Here a POST-PUT creation pattern has evolved, where a client is attempting to create a new resource via POST until it receives a confirmation via a Location header in the response and afterwards attempts the update of that resource's state via PUT. This way the client can be sure that in case of transmission problems the representation was only created once. Depending on the stance, some people might consider the actual update of the resource as the actual resource creation, though as the client beforehand received the respective link, this is not quite the case.
Note that a server also has the right to transform the representation to something different if i.e. the server is configured to provide specific representations for certain URI endpoints. Think of uploading an image via PUT to a URI and the server embedds the image into a HTML page
There's two questions embedded here: 1) should PUT try to create the resource and 2) what happens if it cant.
1)
The RFC linked by #cass says https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4:
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. A successful PUT of a given
representation would suggest that a subsequent GET on that same
target resource will result in an equivalent representation being
sent in a 200 (OK) response.
Further, Mozilla's text https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
The HTTP PUT request method creates a new resource or replaces a representation of the target resource with the request payload.
Further, from the original RFC (that was replaced with the above test) https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
This is a bit anecdotal, but the Kubernetes API also carefully makes this distinction and informs it's users of PATCH if they really meant update: https://kubernetes.io/docs/reference/using-api/api-concepts/#api-verbs
For PUT requests, Kubernetes internally classifies these as either create or update based on the state of the existing object. An update is different from a patch; the HTTP verb for a patch is PATCH.
2
In terms of "what happens if it fails" I think the code depends on what went wrong:
400: it couldnt be created due to a bad payload
409: it couldnt be created due to a conflict - for example some field in the input JSON has some global uniqueness check on it
502/3 - it couldnt be created because it tried to call the database and it was dead
I'm not sure if 404 is the best code, becuase it doesnt tell the user anything about why.

Rest Api: When to use Post, PUT, PATCH and Delete

I am working on a restful api and I need to update a resource (i.e. a customer detail record with 10 fields).
On Add request, I send a Post request with complete record.
On update request, I send a PUT request with complete record of 10 fields.
On Verify request, I send a PUT request with just two fields i.e. recordId and versionNo.
On Delete request, I send a DELETE request with two fields in HttpOptions.
I have few questions that:
Although, it a restful api but specific application which would be used by an angular application, So should I return data in response of POST/PUT requests.
Should I use PATCH in case of Verify (or anyother action where just recordId and versionNo send to server to change some fields) or it is OK to use PUT.
To make uniformity, should I send data in body of delete request as I need recordId and versionNo to delete a record.
Should I use PATCH in case of Verify (or anyother action where just
recordId and versionNo send to server to change some fields) or it is
OK to use PUT.
In RESTful API designs, PUT requests are generally used to add or replace an entire resource, whereas a PATCH should be just used to update an existing resource. A PUT request is called "idempotent" - no matter how many times you send a PUT response, you should get the same result. A PATCH is not idempotent.
example:
PATCH /Cars/vauxhall-astra/engine --> This request would be used to only update the engine of my already existing vauxhall astra
PUT /Cars/renault-clio --> This request would create a new Renault Clio or, if it already exists, replace the entire Clio using the data specified in my request. A Clio would then be guaranteed to exist after my request is successful, regardless of whether it existed or not before.
Although, it a restful api but specific application which would be used by an angular application, So should I return data in response of POST/PUT requests.
Totally up to you, returning data from a POST/PUT is fine - especially if it saves you having to make extra GET api requests. Just always make sure you are only ever returning the data you need from a response.
To make uniformity, should I send data in body of delete request as I need recordId and versionNo to delete a record.
Again it's totally up to you. Whether you use query parameters (e.g. DELETE cars?id=123) or a request body is just your preference, there's nothing in REST that has rules for this.
REST Response
A RESTful API MUST always answer with HTTP codes to client requests:
Success and error responses are a vital part to define how an API is used correctly.
Refer to this guide to solve all your RESTful related questions.
PATCH/PUT
From Wikipedia:
The main difference between the PUT and PATCH method is that the PUT method uses the request URI to supply a modified version of the requested resource which replaces the original version of the resource whereas the PATCH method supplies a set of instructions to modify the resource. If the PATCH document is larger than the size of the new version of the resource sent by the PUT method then the PUT method is preferred.
Also:
Using the PUT method consumes more bandwidth as compared to the PATCH method when only a few changes need to be applied to a resource. But when the PATCH method is used, it usually involves fetching the resource from the server, comparing the original and new files, creating and sending a diff file. On the server side, the server has to read the diff file and make the modifications. This involves a lot of overhead compared to the PUT method.[11] On the other hand, the PUT method requires a GET to be performed before the PUT and it is difficult to ensure that the resource is not modified between the GET and PUT requests.
So I will use PATCH for verifying a resource.
DELETE
Normaly, for DELETE requests, the client specifies the id of the resource and pass it ass a Path Variable on the URL:
curl -X DELETE http://example.com/resource/{id}
But you can pass a body on the request also. This possibility is stated by MDN Mozilla Web DOCS:
Request has body - May
Successful response has body - May
Even though others have answered the question in details before me but still I'm posting this just to provide a handy short difference between all of these HTTP methods
1.HTTP Post:It is used to create an item
2.HTTP Put:It is used to update an item
3.HTTP Patch:It is used to partially update an item
4.HTTP Delete:It is used to delete an item

What response code should I use on a REST API with multiple steps?

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.

Is it good to use the Http DELETE verb to define a REST API that delete a single specific object?

I am implementing some REST APIs and I have a doubt about what HTTP verb should I use to implement an API that remove a single record from my DB
I thought that I should use the DELETE method but reading here:
http://www.restapitutorial.com/lessons/httpmethods.html
Reading the DELETE verb defintion I can read:
405 (Method Not Allowed), unless you want to delete the whole
collection—not often desirable.
So it seems to me that I have to use DELETE when I delete the whole collection and not a single element. Or it fit also the use case in which I am deleting a specific object (passing the ID of this object into my URL)?
Looks like you have misunderstood the content of the link you posted.
The DELETE HTTP method can be used to remove a single resource or a collection of resources.
However, in most of situations, you don't want to allow the client to remove the entire collection, so you return a 405 status code indicating that the DELETE method is not allowed in the collection URL.
In more practical terms, consider that you have a collection of customers mapped to /customers.
A GET request to such URL will return a representation of this collection. A DELETE request to such URL will delete all customers from your application. It's very likely you don't want that, so you return 405 to indicate that deleting all customers at once is not allowed. In the other hand, you want to allow the client to delete a single customer by performing a DELETE request to a URL that locates a single customer, such as /customers/{id}.
If the request succeeds, consider one of the following status codes, as defined in the RFC 7231:
If a DELETE method is successfully applied, the origin server SHOULD
send a 202 (Accepted) status code if the action will likely succeed
but has not yet been enacted, a 204 (No Content) status code if the
action has been enacted and no further information is to be supplied,
or a 200 (OK) status code if the action has been enacted and the
response message includes a representation describing the status.

S3 REST API and POST method

I'm using AWS S3 REST API, and after solving some annoying problems with signing it seems to work. However, when I use correct REST verb for creating resource, namely POST, I get 405 method not allowed. Same request works fine with method PUT and creates resource.
Am I doing something wrong, or is AWS S3 REST API not fully REST-compliant?
Yes, you are wrong in mapping CRUD to HTTP methods.
Despite the popular usage and widespread misconception, including high-rated answers here on Stack Overflow, POST is not the "correct method for creating resource". The semantics of other methods are determined by the HTTP protocol, but the semantics of POST are determined by the target media type itself. POST is the method used for any operation that isn't standardized by HTTP, so it can be used for creation, but also can be used for updates, or anything else that isn't already done by some other method. For instance, it's wrong to use POST for retrieval, since you have GET standardized for that, but it's fine to use POST for creating a resource when the client can't use PUT for some reason.
In the same way, PUT is not the "correct method for updating resource". PUT is the method used to replace a resource completely, ignoring its current state. You can use PUT for creation if you have the whole representation the server expects, and you can use PUT for update if you provide a full representation, including the parts that you won't change, but it's not correct to use PUT for partial updates, because you're asking for the server to consider the current state of the resource. PATCH is the method to do that.
In informal language, what each method says to the server is:
POST: take this data and apply it to the resource identified by the given URI, following the rules you documented for the resource media type.
PUT: replace whatever is identified by the given URI with this data, ignoring whatever is in there already, if anything.
PATCH: if the resource identified by the given URI still has the same state it had the last time I looked, apply this diff to it.
Notice that create or update isn't mentioned and isn't part of the semantics of those methods. You can create with POST and PUT, but not PATCH, since it depends on a current state. You can update with any of them, but with PATCH you have an update conditional to the state you want to update from, with PUT you update by replacing the whole entity, so it's an idempotent operation, and with POST you ask the server to do it according to predefined rules.
By the way, I don't know if it makes sense to say that an API is or isn't REST-compliant, since REST is an architectural style, not a spec or a standard, but even considering that, very few APIs who claim to be REST are really RESTful, in most cases because they are not hypertext driven. AWS S3 is definitely not RESTful, although where it bears on your question, their usage of HTTP methods follows the HTTP standard most of the time.
+--------------------------------------+---------------------+
| POST | PUT |
+--------------------------------------+---------------------+
| Neither safe nor idempotent Ex: x++; | Idempotent Ex: x=1; |
+--------------------------------------+---------------------+
To add to #Nicholos
From the http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
POST:
The posted entity is subordinate to the URI in the same way that a
file is subordinate to a directory containing it, a news article is
subordinate to a newsgroup to which it is posted, or a record is
subordinate to a database
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result
If a resource has been created on the origin server, the response
SHOULD be 201 (Created)
PUT:
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already existing
resource, the enclosed entity SHOULD be considered as a modified
version of the one residing on the origin server. If the Request-URI
does not point to an existing resource, and that URI is capable of
being defined as a new resource by the requesting user agent, the
origin server can create the resource with that URI. 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
IMO PUT can be used to create or modify/replace the enclosed entity.
In the original HTTP specification, the resource given in the payload of a POST request is "considered to be subordinate to the specified object" (i.e. the request URL). TimBL has said previously (can't find the reference) that it was modelled on the identically-named method in NNTP.