Is HTTP method POST necessarily idempotent? - rest

I'm stuck in a theoretical issue with REST.
Imagine a simple product stock API. The database contains one collection of movements referencing a product, a quantity and a status.
I have one prerequisite: I don't want the API users to manipulate the status. The status value can be reserved or confirmed.
First, I want to create a reservation of a product. Here is the corresponding URL path and HTTP method to represent that:
[POST] /products/{product-id}/reservations
This create the movement with a status reserved and return the id of the created movement.
Now, I want to confirm this reservation:
[POST] /reservations/{movement-id}/confirmations
In a semantic way, it seems to me that I create a confirmed reservation. In fact, I just change the status of the movement.
So, 2 questions:
My second POST is idempotent. I was unable to find the information in the RFC, but can a POST be idempotent?
Do you see a better way to represent the confirmation?

I would use PUT instead. e.g. PUT /reservations/{movement-id}/status "confirmed".
note:
It does not matter that your POST is idempotent, since you remove the link after the reservation was confirmed (HATEOAS), so the chance is very low that 2 confirmation arrive for the same reservation. Anyways I think PUT is a better fit.

Related

REST API: How to deal with processing logic

I read (among others) the following blog about API design: https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling. It helped me to better understand a lot of aspects, but I have one question remaining:
How do I deal with functionality that processes some data and gives a response directly. Think, verbs like translate, calculate or enrich. Which noun should they have and should they be called by GET, PUT or POST?
P.S. If it should be GET, how to deal with the maximum length of a GET request
This is really a discussion about naming more so than functionality. Its very much possible to have processed logic in your API, you just need to be careful about naming it.
Imaginary API time. Its got this resource: /v1/probe/{ID} and it responds to GET, POST, and DELETE.
Let's say we want to launch our probes out, and then want the probe to give us back the calculated flux variation of something its observing (totally made up thing). While it isn't a real thing, let's say that this has to be calculated on the fly. One of my intrepid teammates decides to plunk the calculation at GET /v1/1324/calculateflux.
If we're following real REST-ful practices... Oops. Suddenly we're not dealing with a noun, are we? If we have GET /v1/probe/1324/calculateflux we've broken RESTful practices because we're now asking for a verb - calculateflux.
So, how do we deal with this?
You'll want to reconsider the name calculateflux. That's no good - it doesn't name a resource on the probe. **In this case, /v1/probe/1324/fluxvalue is a better name, and /v1/probe/1324/flux works too.
Why?
RESTFUL APIs almost exclusively use nouns in their URIs - remember that each URI needs to describe a specific thing you can GET POST PUT or DELETE or whatever. That means that any time there is a processed value we should give the resource the name of the processed (or calculated) value. This way, we remain RESTful by adhering to the always-current data (We can re-calculate the Flux value any time) and we haven't changed the state of the probe (we didn't save any values using GET).
Well, I can tell you that I know about this.
GET // Returns, JUST return
DELETE // Delete
POST // Send information that will be processed on server
PUT // Update a information
This schema is for laravel framework. Will be most interesting that you read the link in ref
Ref:
https://rafaell-lycan.com/2015/construindo-restful-api-laravel-parte-1/
You should start with the following process:
Identify the resources (nouns) in your system.
They should all respond to GET.
Let's take your translation example. You could decide that every word in the source language is a resource. This would give:
http://example.com/translations/en-fr/hello
Which might return:
Content-Type: text/plain
Content-Language: fr
bonjour
If your processes are long-running, you should create a request queue that clients can POST to, and provide them with another (new) resource that they can query to see if the process has completed.

Is HTTP PUT with filtering still idempotent?

I’m working on a restful service and I am not sure if what I am doing is valid HTTP. I understand how to use the following HTTP methods: GET, DELETE and POST, but when supporting PUT, I am not so sure. I understand PUT is idempotent but what if I were to use filtering?
For clarity, if you were to use my service, you can:
GET /User
Which would list ALL users.
GET /User/1
Which would get the User who has an ID of 1.
POST /User
Which will create a new User.
PUT /User/2
Which will create a new User with an ID of 2 and if the User already exists, the User will be updated.
Where I start to struggle is when I want to implement filtering on a PUT request. For example, I allow:
PUT /User?FirstName=Andrew&LastName=Schools
This would update the resource that has a FirstName of Andrew and a LastName of Schools. Furthermore, you can also do:
PUT /User?status=1
Which will update any User who has a status of 1 with the contents from the body of the request.
My question is, since I am enabling filtering on a PUT, is this still idempotent? My initial thought is no because the first time you PUT using the filter above, this could change what the same exact filter finds in a subsequent PUT, thus, is NOT idempotent. If the above statement is indeed TRUE, would this feature be better served in a POST?
I don't see a problem. What's relevant is the final state of the resource. If you apply the PUT twice, and on the second request the filter identifies less or no resources, does it change the state of the resources you did want to modify?

Clarification on using Http PUT & POST and their differences

I found this good post about understanding Http PUT & POST.
http://www.elharo.com/blog/software-development/web-development/2005/12/08/post-vs-put/
So the take away from the post are:
PUT:
PUT puts a page at a specific URL. If there is already a page there, it’s replaced. If there’s no page, a new one is created.
PUT is a limited operation that never does anything more than PUT one page at a specified URL.
PUT should be used when the client specifies the location for the page. e.g giving id of the object in a database table.
POST:
POST sends some data to a specified URL. The server on the other end of this URL can do whatever it wants with this data. It can store it in a new page, It can insert, update, or delete records in a database, It can start brewing coffee etc.
POST is used when the client sends the page to the server, and the server then tells the client where it put it. e.g after insertion in database returns generated id.
All good, but I have following questions:
I know it is possible to create new objects using PUT. That means even if I don't specify the location or id where object should be put, PUT method works. So, the statement made by the author PUT should be used when the client specifies the location for the page makes little sense or unconvincing when deciding when to use PUT.
My second question is regarding this statement POST sends some data to a specified URL. The server on the other end of this URL can do whatever it wants with this data. But the same is possible with PUT method once the data has been received on the server. Which leads to conflict with his another statement PUT is a limited operation that never does anything more than PUT one page at a specified URL.
Finally, are Http methods(PUT, POST, GET etc) more of a design concept or have technical implications when used.
POST is used to create new object while PUT is used to update existing object.
If a server doesn't respect this rule it breaks the semantic.
Your question #3 is on the right track: The HTTP methods don't have a technical implication on their own, but display a certain intent. These are defined in for example RFC 7231 / Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
Theoretically, nothing stops you from implementing software that listens on a DELETE to trigger something other than a delete, create new entities from a PUT or delete when receiving a POST. Is that useful? Probably not, but definitely not impossible.
The HTTP methods are well defined as a kind of contract how they should be used, to allow interaction between different software components.
The Page analogy you gave doesnt fit into the context of PUT and POST.
PUT,POST,GET,DELETE etc are all HTTP operations to do certain operations on a resource
Let us consider a simple resource , this enpoint is written by a pet house who wants to track dogs through a REST based back-end(server side software)
/dogs
When we want to add a dog to the records of dogs, we do a
POST /dogs with body
{
color:'black'
breed:'xyz'
puppies: 0
bla
bla
bla
}
It creates a new dog under /dogs resource with a unique identifier say identifier 1
Now the owner of the pet house wants to see all the dogs he/she has so the call made is
GET /dogs
This will list all the dogs and I can see what colour, what bred they are etc etc etc
I want to see a specific Dog, what do I call
GET /dogs/1 (Here 1 is the Identifier of the dog)
Which gives all details of Dog with identifier 1
Now let us say the Dog now gets married and has puppies (just so that it looks good socially) and we want to update the number of puppies to 3, what do you do
PUT /dogs/1 with body
{
color:'black'
breed:'xyz'
puppies: 3
bla
bla
bla
}
and now the record of Dog 1 is updated.
Now the unfortunate moment the Dog dies , the owner makes this call
DELETE /dogs/1 and that resource is deleted from the records.
Another thing to understand is PUT is idempotent POST is not which means if you do
POST /dogs for 10 times 10 different instances of dogs are created
if you do for 10 times
PUT /dogs/1 , it still does the same thing to that 1 dog.
HTTP methods are more about semantics than actual implementations (that answers your 3rd question I guess). I would suggest that don't take any single person's opinion literally.
In general, I believe the following is true
PUT
PUT needs an identifier in the url. And it will replace existing resource with whatever you provided. Replace here is important because, if you need partial updates, you should go for PATCH instead. If you expect the server to create a resource, you should call POST and not PUT. Calling a PUT with an imaginary id and expecting server to create the resource with that id does not make sense. Now this is what should be followed, but I have seen code which does otherwise just for convenience :)
POST
POST should always create a resource. If the resource with similar details already exists, service may choose to return some kind of error code to denote that (may be 400 or 409)

A RESTful singleton resource

I'm coming from the RPC world but currently investigating if using REST is a good idea for my project. As for as I understand from Wikipedia the basic idea of RESTful services is to provide access to collections and their individual elements.
In my case the server would be a measuring instrument. I must be able to start, stop, and pause the measurement routine, and read the data at any time.
Currently, I'm considering the following:
POST /measure (start measurement, this continues until stopped by the user)
PUT /measure pause=true/false (pause/unpause)
DELETE /measure (stop)
GET /measure (get measurement data)
However, I'm not sure if this fits the REST model, since I don't really work with collections or elements here.
My question: How would I access a singleton resource and do the start/stop requests to the server break the RESTful stateless constraint?
Not RESTful
No, your approach isn't RESTful, because if I understand the workflow, you would delete the resource to stop the measurement and then get the resource to read out the final result. But deleting a resource implies that there would be nothing left to GET.
The fact that your resource is a singleton isn't a problem at all. The problem lies in the way you're mapping verbs and state.
Your description is a bit abstract, so let's be a bit more concrete: let's assume that the instrument in question measures the angular velocity of a fly wheel in radians/sec. This instrument has some cost associated with measurement, so the client needs to be able to disable measurement for some periods of time as a cost-saving measure. If this is roughly analogous to your scenario, then the exposition below should be applicable to your scenario.
Verbs
Now, let's review your verbs.
GET returns a representation of a resource. So when you GET /measure, it should return some data that represents the current measurement.
PUT creates or updates a specific, named resource. The resource is named by its URL. So PUT /measure implies that you're updating the state of a resource called /measure, or creating that resource if it doesn't already exist. In your case, the instrument value is read-only: we can't write a radian/sec value to the instrument. But the paused/active state of the instrument is mutable, so PUT /measure should include a body that modifies the state of the instrument. You could use a lot of different representations here, but one simple approach would be a request body like active=true or active=false to indicate what thew instrument's new state should be.
POST is similar to PUT, except that the client does not specify the name of the resource that should be created or updated. In a different API, for example, the client might POST /articles to create a new a article. The server would create a resource and give it a name like /articles/1234 and then it would tell the client about this new name by returning a 201 CREATED HTTP code and adding a Location: /articles/1234 header to tell the client where the new resource is. In your scenario, POST isn't a meaningful verb because you always know what the name of your singleton resource is.
DELETE means you remove a resource, and since a resource is identified by a URL, DELETE /measure implies that /measure no longer exists. A subsequent GET /measure should return either 404 NOT FOUND or 410 GONE. In your case, the client can't actually destroy the instrument, so DELETE isn't meaningful a meaningful verb.
Conclusion
So in sum, a RESTful design for your service would be to have PUT /measure with a request body that tells the instrument whether it should be active or not active (paused) and GET /measure to read the current measurement. If you GET /measure on a paused instrument, you should probably return a 409 CONFLICT HTTP status. Your service shouldn't use POST or DELETE at all.
You are still working on a resource, and the way you broke it down sounds good to me. Fielding explicitly mentions temporaral services in the REST chapter:
The key abstraction of information in REST is a resource. Any
information that can be named can be a resource: a document or image,
a temporal service (e.g. "today's weather in Los Angeles")
Maybe it would make sense to give each measurement a unique id though. That way you can uniquely refer to each measurement (you don't even have to store the old ones, but if someone refers to an old measurement you can tell them, that what they are requesting is not up to date anymore).
Building upon the last answer. Here is how you might want to break it down
measures/ - GET all the measures from the instrument (Paginate/limit if needed based on query params)
measures/:measure_id - GET a particular measure
measures/ - POST - Starts a new measure. This returns the new measure ID which you can deal with later.
measures/:measure_id - DELETE - stop the measure.
measures/:measure_id - PUT - update the measure
measures/last_measure - Last measured resource.

Appending to a resource's attribute RESTfully

This is a follow up to Updating a value RESTfully with Post
How do I simply append to a resource's attribute using REST. Imagine I have customer.balance and balance is an int. Let' say I just want to tell the server to append 5 to whatever the current balance is. Can I do this restfully? If so, how?
Keep in mind that the client doesn't know the customer's existing balance, so it can't just
get customer
customer.balance += 5
post customer
(there would also be concurrency issues with the above.)
Simple, slightly ugly:
This is a simpler variation of my answer to your other question.
I think you're still within the constraints of REST if you do the following. However, I'm curious about what others think about this situation as well, so I hope to hear from others.
Your URI will be:
/customer/21/credits
You POST a credit resource (maybe <credit>5</credit>) to the URI, the server can then take the customer's balance and += it with the provided value. Additionally, you can support negative credits (e.g. <credit>-10</credit>);
Note that /customer/21/credits doesn't have to support all methods. Supporting POST only is perfectly acceptable.
However, this gets a little weird if credits aren't a true resource within your system. The HTTP spec says:
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.
Technically you're not creating a resource here, you're appending to the customer's balance (which is really an aggregate of all previous credits in the system). Since you're not keeping the credit around (presumably), you wouldn't really be able to return a reference to the newly "created" credit resource. You could probably return the customer's balance, or the <customer> itself, but that's a bit unintuitive to clients. This is why I think treating each credit as a new resource in the system is easier to work with (see below).
My preferred solution:
This is adapted from my answer in your other question. Here I'll try to approach it from the perspective of what the client/server are doing:
Client:
Builds a new credit resource:
<credit>
<amount>5</amount>
</credit>
POSTs resource to /customer/21/credits
POSTing here means, "append this new <credit> I'm providing to the list of <credit>s for this customer.
Server:
Receives POST to /customer/21/credits
Takes the amount from the request and +=s it to the customer's balance
Saves the credit and its information for later retrieval
Sends response to client:
<credit href="/customer/21/credits/credit-id-4321234">
<amount>5</amount>
<date>2009-10-16 12:00:23</date>
<ending-balance>45.03</ending-balance>
</credit>
This gives you the following advantages:
Credits can be accessed at a later date by id (with GET /customer/21/credits/[id])
You have a complete audit trail of credit history
Clients can, if you support it, update or remove credits by id (with PUT or DELETE)
Clients can retrieve an ordered list of credits, if you support it; e.g. GET /customer/21/credits might return:
<credits href="/customer/21/credits">
<credit href="/customer/21/credits/credit-id-7382134">
<amount>13</amount>
...
</credit>
<credit href="/customer/21/credits/credit-id-134u482">
...
</credit>
...
</credits>
Makes sense, since the customer's balance is really the end result of all credits applied to that customer.
To think about this in a REST-ful way, you would need to think about the action itself as a resource. For example, if this was banking, and you wanted to update the balance on an account, you would create a deposit resource, and then add one of those. The consequence of this would be to update the customer's balance
This also helps deal with concurrency issues, because you would be submitting a +5 action rather than requiring prior knowledge of the customer's balance. And, you would also be able to recall that resource (say deposit/51 for deposit with an ID of 51) and see other details about it (ie. Reason for deposit, date of deposit etc.).
EDIT: Realised that using an id of 5 for the deposit actually confuses the issue, so changed it to 51.
Well, there is alternative other than #Rob-Hruska 's solution.
The fundamental idea is the same: to think each credit/debit operation as a standalone transaction. However I once used a backend which supports storing schema-less data in json, so that I end up with defining the API as PUT with dynamic field names. Something like this:
PUT /customer/21
{"transaction_yyyymmddHHMMSS": 5}
I know this is NOT appropriate in the "credit/debit" context because an active account could have growing transaction records. But in my context I am using such tactics to store finite data (actually I was storing different batches of GPS way points during a driving trip).
Cons: This api style has heavy dependence on backend behavior's schema-less feature.
Pros: At least my approach is fully RESTful from the semantic point of view.
By contrast, #Rob-Hruska 's "Simple, slightly ugly" solution 1 does not have a valid Location header to return in the "201 Created" response, which is not a common RESTful behavior. (Or perhaps, we can let #Rob-Hruska's solution 1 to also return a dummy Location header, which points to a "410 Gone" or "404 Not Found" page. Is this more RESTful? Comments are welcome!)