I am writing a web-service that perform some software installation in a asynchronous way. In one case a manual action is needed in the middle of the installation. Thus I paused the installation and wait for the user to request the application to resume the installation.
Currently we can retrieve the running installations by performing a GET request on /running-install and cancel a installation with a DELETE on /running-install/<id> but I can't find the appropriate method to use to resume a paused installation.
I was thinking of something like a doing PUT on /running-install/<id> with a body containing {"status":"running"} but it does not feel very right to me.
Thank you
Which HTTP method is the most appropriate to resume an asynchronous task?
Semantically you want to replace the state of a given task with a new state. PUT seems to be a reasonable choice for this scenario.
Quoting the RFC 7231:
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. [...]
Then send a representation of the new state in the request payload:
PUT /api/installation/1/status HTTP/1.1
Host: example.org
Content-Type: application/json
{ "value" : "running" }
A successful operation could, for example, return 204 and an attempt to modify the status with an invalid state could return 409.
Note: This answer may also be helpful.
If you were implementing this protocol as a sequence of web pages using an html representation, then you would probably use POST here, as you likely don't want clients treating this as a safe interaction.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
Hard to go wrong with that.
Something to keep in mind is that the resources are integration resources.
You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
So if you are having trouble shoehorning the messages you need into the limited resources you have available, then add more resources.
You can make a case for any of POST, PUT, DELETE being correct depending on how you choose to model the integration protocol.
The truth is, if you are actually doing REST, it's perfectly reasonable to offer multiple integration protocols to achieve the same effect. The hypermedia clients can choose which protocol to follow based on the semantics associated with the links on the bookmark page.
Related
I am looking for a REST API to do following
Search based on parameters sent, if results found, return the results.
If no results found, create a record based on search parameters sent.
Can this be accomplished by creating one single API or 2 separate APIs are required?
I would expect this to be handled by a single request to a single resource.
Which HTTP method to use
This depends on the semantics of what is going on - we care about what the messages mean, rather than how the message handlers are implemented.
The key idea is the uniform interface constraint it REST; because we have a common understanding of what HTTP methods mean, general purpose connectors in the HTTP application can do useful work (for example, returning cached responses to a request without forwarding them to the origin server).
Thus, when trying to choose which HTTP method is appropriate, we can consider the implications the choice has on general purpose components (like web caches, browsers, crawlers, and so on).
GET announces that the meaning of the request is effectively read only; because of this, general purpose components know that they can dispatch this request at any time (for instance, a user agent might dispatch a GET request before the user decides to follow the link, to make the experience faster).
That's fine when you intend the request to provide the client with a copy of your search results, and the fact that you might end up making changes to server local state is just an implementation detail.
On the other hand, if the client is trying to edit the results of a particular search (but sometimes the server doesn't need to change anything), then GET isn't appropriate, and you should use POST.
A way to think about the difference is to consider what action you want to be taken when an intermediate cache holds a response from an earlier copy of "the same" request. If you want the cache to reuse the response, GET is the best; on the other hand, if you want the cache to throw away the old response (and possibly store the new one), then you should be using POST.
I know the use of http verbs is based on standard specification. But my question if I use "GET" for update operations and write a code logic to update, does it create issues in any scenario? Apart from the standard, what else could be the reason to use these verbs for a specific purpose only?
my question if I use "GET" for update operations and write a code logic to update, does it create issues in any scenario?
Yes.
A simple example - suppose the network between the client and the server is unreliable; specifically, for a time, HTTP responses are being lost. A general purpose component (like a web proxy) might time out, and then, noticing that the method token of the request is GET, resend the request a second/third/fourth time, with your server performing its update on every GET request.
Let us further assume that these multiple update operations lead to an undesirable outcome; where do we properly affix blame?
Second example: you send someone a copy of the link to the update operation, so that they can send you a request at the appropriate time. But suppose you send that link to them in an email, and the email client recognizes the uri and (as a performance optimization) pre-fetches the link, triggering your update operation too early. Where do we properly affix the blame?
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
In these, and other examples, blame is correctly affixed to your server, because GET has a standardized meaning which include the constraint that the semantics of the request are safe.
That's not to say that you can't have side effects when handling a GET request; "hit counters" are almost as old as the web itself. You have a lot of freedom in your implementation; so long as you respect the uniform interface, there won't be too much trouble.
Experience report: one of our internal tools uses GET requests to trigger scheduling; in our carefully controlled context (which is not web scale), we get away with it, and have for a very long time.
To borrow your language, there are certainly scenarios that would give us problems; but given our controls we manage to avoid them.
I wouldn't like our chances, though, if requests started coming in from outside of our carefully controlled context.
I think it's a decent question. You're asking a hypothetical: is there any value to doing the right other than that's we agree to use GET for fetching? e.g.: is there value beyond the fact that it's 'semantically nice'. A similar question in HTML might be: "Is it ok to use a <div> with an onclick instead of a <button>? (the answer is no).
There certainly is. Clients, servers and intermediates all change their behavior depending on what method is used. Even if your server can process GET for updates, and you build a client that uses this, your browser might still get confused.
If you are interested in this subject, don't ask on a forum; read the spec. The HTTP specification tells you what clients, servers and proxies should do when they encounter certain methods, statuses and headers.
Start at RFC7231
what is the best practice in defining web service that represent a non REST command invocation?
For REST, basically we use POST to create new record(s), GET to retrieve record(s), PUT to update record(s) and DELETE to remove record(s). Which http verb should I use if I just want to invoke some other non resource function, for example - to flush a system cache?
Which http verb should I use if I just want to invoke some other non resource function, for example - to flush a system cache?
HTTP request methods should be selected based on their alignment with their defined semantics.
The most important of these is to determine whether or not the semantics are safe
Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server.
Advertising a safe link invites consumers to pre-fetch a link, or to crawl and index the representation found there.
If having Google and a billion of her closest friends flushing your system cache sounds expensive, then you probably don't want a safe method.
PUT and PATCH are unsafe methods with semantics of manipulating representations. So if you had a schema that described a system cache, a client might PUT a representation of an empty cache in the entity body, and send that to you, whereupon you could flush the cache. You could achieve a similar things with PATCH, sending a list of the edits needed to make the change.
Both of these rely on the illusion that your resources are just documents. I GET a representation of your resource, I load that into my generic editor, make changes, send my edited representation back to you, and then it's up to you to manifest those changes (or not).
But they aren't required -- if you want to simply document that
PUT /df1645af-f960-4cc4-ad7a-d0ddd29903f8
Content-Length: 0
has the side effect of flushing the system cache, the REST Police aren't going to come after you just because you've introduced a bit of RPC into the mix.
Of course, if you were doing this with HTML, then your only choice would be POST.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
Which is to say, POST is always an option.
It's easy enough to imagine the flow -- you load up some bookmark, follow a system cache link, find a form with a flush cache button, and submit. The browser would create the request as described in the form elements and submit it.
So that's going to be fine too. And the REST police won't bother you for that, because that protocol is actually RESTful.
If those answers are unsatisfying, or if you are just surveying the space to know what options are available, you can review the HTTP Method Registry. To be honest, I've never found anything there I've wanted to use. But if WebDAV is your jam....
I don't quite get how the HTTP verbs are defined as idempotent. All I've read is GET and PUT is idempotent. POST is not idempotent. But you could create a REST API using POST that doesn't change anything (in the database for example), or create a REST API for PUT that changes every time it is called.
Sure, that probably is the wrong way to do things but if it can be done, why is PUT labeled as idempotent (or POST as not) when it is up to the implementation? I'm not challenging this idea, I'm probably missing something and I ask to clear my understanding.
EDIT:
I guess one way to put my question is: What would be the problem if I used PUT to make a non-idempotent call and POST to do so?
You are right in pointing out there is nothing inherent within the HTTP protocol that enforces the idempotent attribute of methods/verbs like PUT and DELETE. HTTP, being a stateless protocol, retains no information or status of each request that the user makes; every single request is treated as independent.
To quote Wikipedia on the idempotent attribute of HTTP methods (emphasis mine):
Note that whether a method is idempotent is not enforced by the
protocol or web server. It is perfectly possible to write a web
application in which (for example) a database insert or other
non-idempotent action is triggered by a GET or other request. Ignoring
this recommendation, however, may result in undesirable consequences,
if a user agent assumes that repeating the same request is safe when
it isn't.
So yes, it is possible to deviate from conventional implementation, and rollout things like non-changing POST implementation, non-idempotent PUT etc. probably with no significant, life-threatening technical problems. But you might risk upsetting other programmers consuming your web services, thinking that you don't know what you're doing.
Here's an important quote from RFC2616 on the HTTP methods being safe (emphasis mine):
Implementors should be aware that the software represents the user in
their interactions over the Internet, and should be careful to allow
the user to be aware of any actions they might take which may have an
unexpected significance to themselves or others.
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects, so
therefore cannot be held accountable for them.
UPDATE: As pointed out by Julian, RFC 2616 has been replaced by RFC 7231. Here's the corresponding section.
So when you publish a web service as a PUT method, and I submit a request that looks like:
PUT /users/<new_id> HTTP/1.1
Host: example.com
I will expect a new user resource to be created. Likewise, if my request looks like:
PUT /users/<existing_id> HTTP/1.1
Host: example.com
I will expect the corresponding existing user to be updated. If I repeat the same request by submitting the form multiple times, please don't pop up a warning dialog (because I like the established convention).
Conversely, as a consumer of a POST web service, I will expect requests like:
POST /users/<existing_id> HTTP/1.1
Host: example.com
to update the corresponding existing user, while a request that looks like:
POST /users/<new_id> HTTP/1.1
Host: example.com
to raise an error because the URL doesn't exist yet.
Indeed, an implementation can do anything it wants. However, if that is incorrect according to the protocol spec, surprising things might happen (such as as library or intermediary repeating a PUT if this first attempt failed).
hope the link helps to you:HTTP Method idempotency
Be careful when dealing with safe methods as well: if a seemingly safe method like GET will change a resource, it might be possible that any middleware client proxy systems between you and the server, will cache this response. Another client who wants to change this resource through the same URL(like: http://example.org/api/article/1234/delete), will not call the server, but return the information directly from the cache. Non-safe (and non-idempotent) methods will never be cached by any middleware proxies.
I don't see a huge benefit of designing a REST API service that uses PUT and DELETE to update and delete data. These 2 verbs can be easily replaced by using a POST and a unique url.
The only benefit I see of using PUT and DELETE is it cuts down the number of url's that the REST API service uses which isn't much. Are there other benefits that I'm overlooking?
This actually has not so much to do with REST, but more with the Hypertext Transfer Protocol (HTTP).
The basic idea of HTTP is that you perform a certain action (one of the HTTP methods, such as GET, POST, PUT and DELETE) on a certain resource (identified by its URL). So if you start deviating from that by adding the action into the URL (such as http://example.com/api/books/123/delete) and using a different HTTP method, you are violating the HTTP protocol.
The downsides of this might not be instantly visible (because it will still work), and might be limited if you are only using the API by yourself. However, if other programmers are using the API as well, you are creating certain expectations by stating that you have a RESTful HTTP API while you are actually not adhering to the protocol.
For instance, if calling GET /api/books/123 returns a representation of the book resource, a developer expects to be able to call PUT on that same URL to update the information on that book, and DELETE to remove the book alltogether. (of course, if he does not have permissions to do that, you don't actually remove the book but you return a 403 'Forbidden' or 405 'Method Not Allowed' status code - which are also part of the HTTP specification)
However, if you deviate from the protocol (basically inventing your own protocol), you will have to describe somewhere that instead of calling DELETE /api/books/123 developers have to call POST /api/books/123/remove/the/book. They will have to be aware of all your API's custom rules because you are not following the standard.
Another good point is made by Darrel Miller in his answer. The HTTP methods all have a certain meaning and also certain characteristics. For instance, GET is supposed to be a safe method, used to retrieve information without making any changes on the server side. And PUT and DELETE are idempotent, which means that (even though they are not safe methods like GET) you can make as many requests as you like without any unwanted side effects (deleting a book one or ten times has the same effect: the book is gone). POST however is not idempotent: if you do ten POST requests to create a new book, you will most likely end up with 10 duplicate book entries.
Because of these characteristics, developers and tools are able to make certain assumptions. For instance, a search indexer such as Googlebot will only do GET requests, in order to not break anything on the server. However, if you would be violating the HTTP specification by having a URL http://example.com/api/books/123/delete in order to delete a book, you might notice at one day that your database is completely empty because Google has been indexing your site. That wouldn't be Google's fault but yours, because you didn't follow the specification.
So to make a long story short: using a protocol or standard (such as HTTP) sets certain expectations, and if you then deviate from the protocol you will create unexpected behavior and possible unwanted side effects.
It is not required to use PUT and DELETE to get the benefits of a REST based system.
Using the more precise methods can be advantageous in certain cases. Usually it is intermediary components that take advantage of the semantics. PUT and DELETE are idempotent methods, so if some generic component receives a 503, in theory it could retry a PUT/DELETE until it gets a successful response. With a POST method, the intermediary can't do that.
With a DELETE method a client knows not to send a body. With a PUT, it knows to send a complete representation. With a POST method, you need to communicate to the client how to make the request in some other way, like a link relation.
You can live without PUT and DELETE.
This article tells you why: http://www.artima.com/lejava/articles/why_put_and_delete.html
..BUT (quote from Fielding): "A REST API should not contain any changes to the communication protocols aside from filling-out or fixing the details of underspecified bits of standard protocols, such as HTTP’s PATCH method or Link header field. Workarounds for broken implementations (such as those browsers stupid enough to believe that HTML defines HTTP’s method set) should be defined separately, or at least in appendices, with an expectation that the workaround will eventually be obsolete. [Failure here implies that the resource interfaces are object-specific, not generic.] "
(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)