Updating resources but is idempotent, can httpGet be used or post - rest

I read posts and did research on rest call. However I cant figure out this particular situation.
I don't know if I should be using Get or Post.
I have a service call that update the database (unlocking a record, changing a flag to false). It's changing the data in database, however no matter how many times you call this service, the change will only happen once, even if you unlock the record three times, the state will still be unlock, so Idempotent.
So that means I can use Get for this instead of post? but can I use Get when I am updating data in the database?
The service call also only take in one Id, I want to add it to the query parameter instead of the body, it would be weird to use post without body right?

All GET requests should be safe. This means that doing a GET request should have no consequences to the state of your database.
Usually when a resource is changed, PUT is used. POST is also ok. It doesn't matter that POST is not guaranteed to be idempotent. If it does in some cases (like yours) it doesn't break the spec.
However, it sounds like in your case PUT is more appropriate.

Related

How to design DELETE REST API that requires lots of data?

I want to implement a DELETE REST API. But I need the option to provide a list of IDs to be deleted. This list could be arbitrarily long and may not fit within a URL.
I know POST supports this, but support for this and DELETE seems debatable. I wonder how others are handling this case.
How would an API be designed to handle this case?
This is unfortunately one of the biggest limitations in REST, but there are ways around it.
In this case I would abstract out a new entity, DeletionRequest, and have that get posted or put with the appropriate IDs. Since it is a new entity it would have its own rest endpoints.
A nice side effect of this is that the endpoints and entity can be expanded out to support async requests. If you want to delete a ton of data you don't want to rely on it happening in a single request, as things like timeouts can get in the way. With a DeletionRequest the user can get an ID for the deletion request on the first push, and then check the status with a GET request. Behind the scenes you can use an async system (celery, sidekiq, etc) to actually delete things and update the status of the DeletionRequest.
You don't have to take it that far to start, of course, but this would allow you to expand the application in that direction without having to change your API.
The URI is the resource identifier, so in my opinion the DELETE should not contain a body even if you can do it with your client and server. Either you send your data in the URI or you send it prior the DELETE.
I see 3 options here, but maybe there are others:
Do what Robert says and POST a transaction resource instead like DeletionRequest.
Group the resources you want to delete and DELETE the entire group.
Do a massive hack and PATCH the collection of resources you want to delete from.

Confusion about HTTP verbs

While building my Web API, I have encountered some cases, where I'm not sure what HTTP verbs to use.
Downloading a file with a side effect
My first thought was to use GET, but later I did realize, when a client calls the API to download a file, the server also updates the counter in the DB indicating total number of downloads and the date of the last download.
Isn't this against the specification? The server state was changed, after all. Shouldn't this be a POST/PUT? But if the POST/PUT would be used, I wouldn't be able to share the link and use it from the browser.
Generating random list of values
In my case I need to call the API to generate random list of questions for a test (exam). The request doesn't change anything on the server, it just produces different response content each time the client calls it, so I guess using GET is alright. The indempotency applies only for the server state, not the result handed to the client, right? So is it allowed to request (GET) the same resource repeatedly with different outcome (as seen from the client)?
Generating list of values based on the user input
The last case is similar to the previous. I need the server to generate list of questions. This time based on the previous test's wrong answers. Again, the request doesn't alter server data, but I need to send to the server (relatively) long list of items, which wouldn't have to fit as a query string. That's why I would think a POST with a payload in the body could be used. But to be honest, it feels weird.
Is there a definitive answer which verbs to use for each case?
Downloading a file with a side effect
My first thought was to use GET
And that's the right answer. HTTP Methods are about semantics, not implementation.
HTTP does not attempt to require the results of a GET to be safe. What
it does is require that the semantics of the operation be safe, and
therefore it is a fault of the implementation, not the interface
or the user of that interface, if anything happens as a result that
causes loss of property -- Fielding (2002)
Generating random list of values
it just produces different response content each time the client calls it, so I guess using GET is alright.
Yup - again, as long as the semantics are safe, GET is a fine choice.
Generating list of values based on the user input
I need to send to the server (relatively) long list of items, which wouldn't have to fit as a query string. That's why I would think a POST with a payload in the body could be used. But to be honest, it feels weird.
So if you weren't worried about length of the identifier, GET would be the usual answer here, with all of the user input encoded into the URI.
At this point, you have a couple of options.
The simplest one is to simply use POST, with the user input in the message body, and the resulting list of values in the Response. That shouldn't feel weird -- POST is the method in HTTP with the fewest semantic constraints.
Alternatively, you can rethink your protocol such that the client is creating a "query resource", using the message body as the payload. So POST could work here again, or alternatively you could use PUT (with a somewhat different handling of the URI).
A third possibility is to look in the Hypertext Transfer Protocol Method Registry to see if there is an extension method with the semantics that you need, paying careful attention to whether or not the method is safe. SEARCH and REPORT might fit your needs.
If I decide later, I want to record each generated test to the DB, would you recommend to change the API to POST or keep it as it is? In case of changing the HTTP verb, the client wouldn't notice any functional change, but it would break the API, so semantics-wise, wouldn't it be more appropriate to use POST right from the start, after all? In both cases the meaning would be "create a new test".
No, but change things up a bit and things get interesting. The interesting bit isn't really "record to the database", but "be able to pull it out of the database later". When you start looking toward creating a new resource that can be retrieved later, GET stops being a good fit.
it would break the API
Only because you are ignoring an important REST constraint - REST api are hypertext driven. On the web, we can easily change from GET to POST by changing from a link to a form (or from a GET form to a POST form). The client isn't playing "guess the URI" or "guess the method" because the representation of state includes these details.
But yes, if you make a big enough change to the semantics, it's not going to be backwards compatible. So don't try to pretend that it is backwards compatible - just create a new protocol using new resources.

Server load difference between an http response with a single value or an object containing more data

I want to naI want to know if there is a real practical difference between different types of content in an HTTP response. Let me explain my self better.
Say I submit a POST request to a server with typical resource payload. Let's use a client with client_name, client_email, client_phone.
Would there be an actual difference if the server returns just an id:
{id:100}
Or if it returns the fully created resource without sensible data, like so:
{client_name: 'Some Client', client_email: 'email#sample.com', client_phone: '417-235-4622'}
Suppose that the application as a considerable amount of active users, creating resources at any given moment. Is there a significant cost in server resources associated with returning data from the server (just an ID or a full object)
Given the following scenarios when creating a resource:
Submit POST request, receive resource ID, complete all data visualization feedback with data in memory (info in form element).
Submit POST request, receive full object with id, email and phone. Continue with UI things.
If there is a difference in cost, and its significant, then the response ID is the way to go. But, I'm thinking that if I have lot's fields to submit, and most of them are required, and I'm only expecting an ID in return, then that'a a guarantee that te resource got created but it doesn't mean it was created completely. Suppose I submit the data, and one of those fields fails silently to submit to database (email for example), the server returns ID, the UI shows the user that the resource was created, the user reloads the page and the email is gone.
If the server returns the full object I get the feeling that the transaction is more atomic.
So, to wrap up. Is there a significante difference in terms of cost to the server ?
but it doesn't mean it was created completely. Suppose I submit the data, and one of those fields fails silently to submit to database (email for example)
Even if the email were to be saved in a different table than the rest of the data, it will still have to be done in a transactional manner (an indivisible operation that must succeed or fail as a complete unit; it can never be only partially complete). This could even mean rolling back changes if a failure is detected at any point during the save operation.
Now back to the main question, REST just says that you should conform to the uniform interface. In other words, it says you should do what POST is supposed to do as per the HTTP spec. Here is the quote from that spec that is relevant,
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
(see section 14.30).
I think it all depends on the use case scenarios. If the client immediately needs to display info regarding the newly created object, I really do not see any advantage to returning only the ID and doing a GET request after, to get the data you could have got with your initial POST.
Anyway as long as your API is consistent I think that you should choose the pattern that fits your needs the best. There is not any correct way of how to build a REST API, imo.
Is there a significante difference in terms of cost to the server ?
That's totally unanswerable by us. How powerful is the server? What software are you running on it? What's the breakdown of your expected traffic? What performance targets are you expected to hit? etc..
Performance problems should be solved through a combination of more better hardware and a sensible software architecture that still does everything you need it to. You don't even know if you have a problem yet and you're trying to fix it.
You're asking the wrong question. The question you should be asking is: when my clients create a user, are they likely to need server-created information beyond the URI immediately? Of course, we can't really answer that either. If the server isn't (and won't ever!) be creating anything, there's an obvious answer. If it is, or may, you may want to return a full representation even if the client doesn't need it now, so it's not a breaking change later if they decide they do. The pain there depends a lot on whether this is an internal- or external-facing API, and who owns the clients.
In addition to the other answers given, which are quite comprehensive, I would just like to add that it is contrary to the design of the web to provide object IDs and expect the client to know what to do with them. You should instead be providing URLs to the object in question. Clients can then do a GET request on the provided URL to fetch the full set of data for the object, should they want to. And I f the responses to these GET requests have already been cached, your server will not have to do any work at all to satisfy them!

REST API HTTP methods

We are planning to use GET for all retrievals and DELETE for all delete operations.
HTTP PUT , POST and PATCH is confusing. After a lot of reading, this is my understanding. Please correct if I am wrong.
POST - Not Idempotent ; so can be used for creating new resources/subordinate resource. Each time it creates a new one the ID gets changed and so it is best suited.
PUT - Idempotent; cannot be used for create since the second time the same request comes, it creates a new resource again with different ID.
Can be used for update but all attributes should be passed each time it is updated. To achieve this, a GET should be done prior to update operation. Overhead.
Why not use POST for updates too?
PATCH -Not sure if it is suitable for JAX-RS 1.1.
Thanks in advance.
I think your question is this:
Why not use POST for updates too?
The benefit of having POST and PUT make different types of changes to the resource you're allowing an extra vector of the request to modify the action without having to add more URLs. That way, URLs can stay short, clean, and reflective of what it is the represent.
However, to clear things up PATCH is often used for partial updates. So, like PUT it is idempotent, but will only modify the parts of the resource which you send in the request body whereas PUT is expected to modify the whole thing. This is often overlooked in REST. You can read more on the Rest Cookbook website.
Apart from that, from what I can tell your understanding is very good. Enjoy RESTing!

How do I create a stack in a REST API?

I am working on a distributed execution server. I have decided to use a REST API based on HTTP on the server. The clients will connect to the server and GET the next task to be accomplished. Obviously I need to "update" the task that is retrieved to ensure that it is only processed once. A GET is not supposed to have any side effects (like changing the state of the resource retrieved). I could use a POST (to update the resource), but I also need to retrieve it. I am thinking that I could have a URL that a POST marks the task as "claimed", then a GET marks the task as retrieved. Unfortunately I have a side effect on GET again. Is this just not going to work in REST? I am OK with have a "function" resource to do this, but don't want to give up the paradigm without a little research.
Pat O
If nothing else fits, you're supposed to use a POST request. Nothing prevents you from returning the resource on a POST request. But it becomes apparent that something (in this case) will happen to that resource, which wouldn't be the case when using a GET request.
REST is really just a concept, and you can implement it however you want. There is no one 'right way', as everyones use cases are different. (yes I understand that there is a defined spec out there, but you can still do it however you want) In this situation if your GET needs to have a side effect, it will have a side effect. Just make sure to properly document what you did (and potentially why you did it).
However it sounds like you're just trying to create a queue with multiple subscribers, and if the subscribers are automated (such as scripts or other machines) you may want to look at using an actual queue. (http://www.rabbitmq.com/getstarted.html).
If you are using this to power a web UI or something where actual people process this, you could also use a queue, with your GET request simply pulling the next item from the queue.
Note that when using most of the messaging systems you will not be able to guarantee the order in which the messages are pulled from the queue, so if the order is necessary you may not be able to use this approach.