What is the idiomatic way to represent a once-writeable resource in a RESTful API (in HTTP)? In CRUD terms it should be possible to create the resource but to disallow updates?
EDIT:
Just to add the clarification in the comment on Rosenheimer's answer below. I'd like to allow the client to specify the URL rather than have it generated by a POST handler.
If the resource doesn't exist before (that means "once-writable" actually is "creation" of the resource) then it would be easy to just call the parent for a POST, like this: POST example.com/Resources to send the resource.
Later, do not allow either PUT or PATCH to the specific resource at example.com/Resources/123 where 123 would be the identifier of the resource.
So the resource can be written once but can not be changed later.
I think the correct would be to accept PUT method for the first time resource is saved and return 409 Conflict HTTP status code on any subsequent attempt to update already existing resource.
You could use the HTTP status 405 Method Not Allowed or 403 Forbidden to forbid subsequent update.
Some use POST for resource creation:
# C of CRUD
POST ./phones -> 200 OK with the id of the object created
# R or CRUD
GET ./phones/{id}
# U of CRUD
PATCH/PUT ./phones/{id}
# D of CRUD
DELETE ./phones/{id}
Some may use PUT for object creation but the issue of using PUT is that the method have 2 meaning for the client.
Related
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
how to handle resource checking on server side?
For example, my api looks like:
/books/{id}
After googling i found, that i should use HEAD method to check, if resource exists.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
I know, that i can use GET endpoint and use HEAD method to fetch information about resource and server does not return body in this case.
But what should i do on server side?
I have two options.
One endpoint marked as GET. I this endpoint i can use GET method to fetch data and HEAD to check if resource is available.
Two endpoints. One marked as GET, second as HEAD.
Why i'm considering second solution?
Let's assume, that GET request fetch some data from database and process them in some way which takes some time, eg. 10 ms
But what i actually need is only to check if data exists in database. So i can run query like
select count(*) from BOOK where id = :id
and immediately return status 200 if result of query is equal to 1. In this case i don't need to process data so i get a faster response time.
But... resource in REST is a object which is transmitted via HTTP, so maybe i should do processing data but not return them when i use HEAD method?
Thanks in advance for your answer!
You could simply delegate the HEAD handler to the existing GET handler and return the status code and headers only (ignoring the response payload).
That's what some frameworks such as Spring MVC and JAX-RS do.
See the following quote from the Spring MVC documentation:
#GetMapping — and also #RequestMapping(method=HttpMethod.GET), are implicitly mapped to and also support HTTP HEAD. An HTTP HEAD request is processed as if it were HTTP GET except but instead of writing the body, the number of bytes are counted and the "
Content-Length header set.
[...]
#RequestMapping method can be explicitly mapped to HTTP HEAD and HTTP OPTIONS, but that is not necessary in the common case.
And see the following quote from the JAX-RS documentation:
HEAD and OPTIONS requests receive additional automated support. On receipt of a HEAD request an implementation MUST either:
Call a method annotated with a request method designator for HEAD or, if none present,
Call a method annotated with a request method designator for GET and discard any returned entity.
Note that option 2 may result in reduced performance where entity creation is significant.
Note: Don't use the old RFC 2616 as reference anymore. It was obsoleted by a new set of RFCs: 7230-7235. For the semantics of the HTTP protocol, refer to the RFC 7231.
Endpoint should be the same and server side script should make decision what to do based on method. If method is HEAD, then just return suitable HTTP code:
204 if content exists but server don't return it
404 if not exists
4xx or 5xx on other error
If method is GET, then process request and return content with HTTP code:
200 if content exists and server return it
404 if not exists
4xx or 5xx on other error
The important thing is that URL should be the same, just method should be different. If URL will be different then we talking about different resources in REST context.
Your reference for HTTP methods is out of date; you should be referencing RFC 7231, section 4.3.2
The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section).
This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification.
You asked:
resource in REST is a object which is transmitted via HTTP, so maybe i should do processing data but not return them when i use HEAD method?
That's right - the primary difference between GET and HEAD is whether the server returns a message-body as part of the response.
But what i actually need is only to check if data exists in database.
My suggestion would be to use a new resource for that. "Resources" are about making your database look like a web site. It's perfectly normal in REST to have many URI that map to a queries that use the same predicate.
Jim Webber put it this way:
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
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.
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.
According to the HTTP 1.1. spec:
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.
So in other words, PUT can be used to create & update. More specifically, if I do a PUT request e.g.
PUT /users/1
and that user does not exist, I would expect the result of this request to create a user with this ID. However, how would this work if your backend is using an auto-increment key? Would it be a case of simply ignoring it if it's not feasible (e.g. auto-increment is at 6 and I request 10) & creating if it is possible (e.g. request 7)?
From the snippet I have extracted above it does appear to give you this flexibility, just looking for some clarification.
I'd suggest that you use POST, not PUT, for an auto-increment key, or do not use the auto-increment key in the resource ID.
If you use POST, then you'd POST to /users rather than to /users/1. The reply might redirect you to /users/1 or whatever the ID is.
If you use PUT, then you might PUT to /users/10292829 where the number is a unique resource key generated on the client. This key can be time-generated, or it can be a hash of time, session ID, and some other factors to guarantee uniqueness of the value across your client audience. The server can then generate its own auto-incremented index, distinct from 10292829 or whatever.
For more on that, see PUT vs POST in REST
Following up. . .
In the case of allowing PUT to /users/XXXXXXX, for all users, you'd end up with two distinct unique keys that refer to the same resource. (10292829 and 1 might refer to the same user). You'd need to decide how to allow the use of each of these different keys in a REST-style URL. Because of the need to reconcile the use of these two distinct ids, I'd prefer to use the first option, POSTing to /users and getting a unique REST url of the created resource in the response.
I just re-read the relevant section of RFC 2616, and saw a return code specifically designed for this in REST applications:
10.2.2 201 Created
The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. 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. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead.
So, the RESTful way to go is to POST to /users and return a 201 Created, with a Location: header specifying /users/1.
You should be using POST to create resources while the PUT should only be used for updating. Actually REST semantics forces you to do so.