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.
Related
While there have been many topics related to this issue, I still couldn't find a solution to this problem.
I have a GET API REST call that can be very specific, example :
/v1/books?id=40,41,42,43,44,45,46,47...
However, I get a 414 Request-URI too long error sometimes because the list of ids is long.
I've read on every topic related to this problem that we have to use POST instead of GET when there are many parameters (instead of trying to change the max limit in apache, which I agree is not a good solution)
But I'm trying to fetch books, not create ones! REST API is very specific that POST is for creating new entries.
And since I'm using Slim Framework, if I call a POST to fetch books, it'll be expecting different parameters to create a new book. Slim can't specify two different POST /v1/books as it'll always use the first one it finds, no matter the parameters you send... (I'll either be fetching or creating books, never both at the same time)
So, is there a solution somewhere to my problem ?
I'm a bit surprised there's not a REST solution yet...
Looked so hard, couldn't find anything...
Thanks in advance!
PS : I'm consuming this GET API using cURL/PHP, no JS/AJAX in there.
But I'm trying to fetch books, not create ones! REST API is very specific that POST is for creating new entries.
No, POST is for all sorts of things. See It is Okay to Use POST, by Roy T Fielding.
It isn’t RESTful to use POST for information retrieval when that information corresponds to a potential resource, because that usage prevents safe reusability and the network-effect of having a URI.
414 URI Too Long indicates that the target-uri in the request's start-line has tripped the server's arbitrary length limit. Since the server is the authority for its own resources, it gets to make that sort of decision for itself.
The idiomatically correct answer is to create a new resource; which is to say you POST your information to the server, and the server creates a new resource and a matching identifier. For example, the server could save the contents of your post into a random file name, and then send you back the information you wanted with an identifier that encodes that filename, so that you can GET any updates later.
POST /v1/books
id=40,41,42,43,44,45,46,47...
201 Created
Location: /v1/book-lists/9d133345-ded1-47ab-a954-a81c1d6d487f
Content-Location: /v1/book-lists/9d133345-ded1-47ab-a954-a81c1d6d487f
-- current representation of /v1/book-lists/9d133345-ded1-47ab-a954-a81c1d6d487f here --
Subsequent requests to see if the representation has changed could then be sent to the book-lists URI.
This is not, of course, free. Somebody has to decide that they want this in their domain application protocol, design the resources, implement the server side caching of the query payload, and so on.
Also, note that this doesn't actually solve the problem, being that the server should not be expected to support arbitrarily long (aka infinitely long) requests. It really only gives you some breathing room between the length that the server thinks is too long for a target-uri and the length that the server thinks is too long for a payload (413 Payload to Large).
So if you are designing an API, you need to think about what use cases you want to support, what data lengths are at the extremes of those use cases, and choose a domain application protocol that satisfies them, subject to your other constraints.
This is more a theorical question than a practical one.
We have a backend application that uploads csv files to a frontend application, then and only then the backend sends an empty POST request to tell the frontend to start to process those files to update its database.
For this question it doesn't matter if this is a good design (I think it isn't), what are those files, and what database is: I am only want to know better about the REST "sintax".
I'm referring to wikipedia and restfulapi.net, but I'm not convinced about any alternative, because:
GET: Request sender doesn't receive data;
POST (the currently used): Request sender doesn't want to insert data that are on the request body (just data from external files, if existent. Also they can be insert/update/delete);
PUT: Sounds good, but again, data are not on the request body;
PATCH: Sounds best, but data are not on the body (Also, I am wrong or is it deprecated/unused?);
DELETE: Doesn't always need to delete.
I know it is habit to use POST requests to let machines yell "go!" to each other, but I never thought it was right.
What do you think - in theory - would be the proper method?
The actual reference for the semantics of the HTTP methods is the RFC 7231 and not the ones you referenced in your question.
POST is a catch all method and requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
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):
Providing a block of data, such as the fields entered into an HTML
form, to a data-handling process;
Posting a message to a bulletin board, newsgroup, mailing list,
blog, or similar group of articles;
Creating a new resource that has yet to be identified by the
origin server; and
Appending data to a resource's existing representation(s).
[...]
Responses to POST requests are only cacheable when they include
explicit freshness information. However, POST caching is not widely implemented.
In these scenarios, the receiving application knows where the CSV files will be and monitors that location. When it finds one, it processes it and then deletes or archives it. The application will likely have its own criteria for considering itself ready to process, e.g. time of day, size of file etc.
If the data load on the front end takes a long time you could "partition" the updates based on "importance". How you define importance would be up to your business rules. You could then POST a list of CSV filenames/locations to the front end. The list would be ordered by importance. The front end could then update its database based on that importance. Scheduling less important data for a more appropriate time of day.
If the backend knows the difference between new users and updated users you could use PUT and POST. The front end could assign higher priority to PUT requests as they relate to new users, perhaps assigning lower priority and staggered syncing for CSV filenames in POST requests.
Consider a web API method that has no side effects, but which takes binary data as a parameter. An example would be a method that tells the user whether or not their image is photoshopped, but does not permanently store the image or the result on its servers.
Should such a method be a GET or a POST?
GET doesn't seem to have a recommended way of sending data outside of URL parameters, but the behavior of the method implies a GET, which according to the HTTP spec is for safe, stateless responses. This becomes particularly constraining under the semantics of REST, which imply that POST methods create a new object on the server.
This becomes particularly constraining under the semantics of REST, which imply that POST methods create a new object on the server.
While a POST request means that the entity sent will be treated "as a new subordinate of the resource identified by the Request-URI", there is no requirement that this result in the creation of a new permanent object or that any such new object be identified by a URI (so no new object as far as the client knows). An object can be transient, representing the results of e.g. "Providing a block of data, such as the result of submitting a form, to a data-handling process" and not persisting after the entity representing that object has been sent.
While this means that a POST can create a new resource, and is certainly the best way to do so when it is the server that will give that new resource its URI (with PUT being the more appropriate method when the client dictates the new URI) it is can also be used for cases that delete objects (though again if it's a deletion of a single* resource identifiable by a URI then DELETE is far more appropriate), both create and delete objects, change multiple objects, it can mean that your kitchen light turns on but that the response is the same whether that worked or failed because the communication from the webserver to the kitchen light doesn't allow for feedback about success. It really can do anything at all.
But, your instincts are good in wanting this to be a GET: While the looseness of POST means we can make a case for it for just about every request (as done by approaches that use HTTP for an RPC-like protocol, essentially treating HTTP as if it was a transport protocol), this is inelegant in theory, inefficient in practice and clumsy in definition. You have an idempotent function that depends on solely on what the client is interested in, and that maps most obviously the GET in a few ways.
If we could fit everything in a URI then GET would be easy. E.g we can define a simple integer addition with something like http://example.net/addInts?x=1;y=2 representing the addition of 71 and 2 and hence being a permanent immutable resource representing the number 3 (since the results of GET can vary with changes to a resource over time, but this resource never changes) and then use a mechanism like HTML's <form> or javascript to allow the server to inform the client as to how to construct the URIs for other numbers (to maintain the HATEOS and/or COD constraints). Simples!
Your problem here is that you do not have input that can be represented as concisely as the numbers 1 and 2 can above. In theory you could do something like http://example.net/photoshoppedCheck?image=data:image/png;base64,iVBORw0KGgoAAAANSU… and hence create a URI that represents the resource of the results of the check. This URI will though will have 4 characters for every 3 bytes in the image. While there's no absolute limit on URI length both the theory and the practice allow this to fail (in theory HTTP allows for proxies and servers to set a limit on URI length, and in practice they do).
An argument could be made for using GET and sending a request body the same way as you would with a POST, and some webservers will even allow you to do this. However, GET is defined as returning an entity describing the resource identified in the URI with headers restricting how that entity does that describing: Since the request body is not part of that definition it must be ignored by your code! If you were tempted to bend this rule then you must consider that:
Some webservers will refuse the request or strip the body, so you may not be able to.
If your webserver does allow it, the fact that its not specified means you can't be sure an upgrade won't "fix" this and so break your code.
Some proxies will refuse or strip the request.
Some client libraries will most certainly refuse to allow developers to send a request body along with a GET.
So it's a no-no in both theory and practice.
About the only other approach we could do apart from POST is to have a URI that we consider as representing an image that was not photoshopped. Hence if you GET that you get an entity describing the image (obviously it could be the actual image, though it could also be something else if we stretch the concept of content-negotiation) and then PUT will check the image and if its deemed to not be photoshopped it responds with the same image and a 200 or just a 204 while if it is deemed to be photoshopped it responds with a 400 because we've tried to PUT a photoshopped image as a resource that can only be a non-photoshopped image. Because we respond immediately, there's no race-condition with simultaneous requests.
Frankly, this would be darn-right horrible. While I think I've made a case for it by the letter of the specs, it's just nasty: REST is meant to help us design clear APIs, not obtuse APIs we can offer a too-clever-for-its-own-good justification of.
No, in all the way to go here is to POST the image to a fixed URI which then returns a simple entity describing the analysis.
It's perfectly justifiable as REST (the POST creates a transient object based on that image, and then responds with an entity describing that object, and then that object disappears again). It's straight-forward. It's about as efficient as it could be (we can't do any HTTP caching† but most of the network delay is going to be on the upload rather than the download anyway). It also fits into the general use-case of "process something" that POST was first invented for. (Remember that first there was HTTP, then REST described why it worked so well, and then HTTP was refined to better play to those strengths).
In all, while the classic mistake that moves a web application away from REST is to abuse POST into doing absolutely everything when GET, PUT and DELETE (and perhaps the WebDAV methods) would be superior, don't be afraid to use its power when those don't meet the bill, and don't think that the "new subordinate of the resource" has to mean a full long-lived resource.
*Note that a "single" resource here might be composed of several resources that may have their own URIs, so it can be easy to have a single DELETE that deletes multiple objects, but if deleting X deletes A, B & C then it better be obvious that you can't have A, B or C if you don't have X or your API is not going to be understandable. Generally this comes down to what is being modelled, and how obvious it is that one thing depends on another.
†Strictly speaking we can, as we're allowed to send cache headers indicating that sending an identical entity to the same URI will have the same results, but there's no general-purpose web-software that will do this and your custom client can just "remember" the opinion about a given image itself anyway.
It's a difficult one. Like with many other scenarios there is no absolutely correct way of doing it. You have to try to interpret RESTful principles in terms of the limitations of the semantics of HTTP. (Incidentally, I don't think it's right to think of REST having semantics, REST is an architectural style which is commonly used with HTTP services, but can be used for any type of interface.)
I've faced a similar situation in my current project. We chose to use a POST but with the response code being a 200 (OK) rather than the 201 (Resource Created) usually returned by RESTful Web APIs.
I am writing a little app that does one thing only: takes some user-provided data, does some analysis on it, and returns a "tag" for that data. I am thinking that the client should either GET or POST their request to /getTag in order to get a response back.
Nothing is stored on the server when the client does this, so it feels weird to use a POST. However, there is not a uniform URI for the analysis either, so using a GET feels weird, since it will return different things depending on what data is provided.
What is the best way to represent this functionality with REST?
The "best way" is to do whatever is most appropriate for your application and its needs. Not knowing that, here are a few ideas:
GET is the most appropriate verb since you're not creating or storing anything on the server, just retrieving something that the server provides.
Don't put the word get in the URI as you've suggested. Verbs like that are already provided by HTTP, so just use /tag and GET it instead.
You should use a well-understood (or "cool") URI for this resource and pass the data as query parameters. I wouldn't worry about it feeling weird (see this question's answers to find out why).
To sum up, just GET on /tag?foo=bar&beef=dead, and you're done.
POST can represent performing an action. The action doesn't have to be a database action.
What you have really created is a Remote Procedure. RPC is usually all POST. I don't think this is a good fit for REST, but that doesn't have to stop you from using simple URLs and JSON.
It seems to me like there would probably be a reason you or the user who generated the original data would want the generated tag to persist, wouldn't they?
If that's a possibility, then I'd write it as POST /tags and pass the /tags/:id resource URI back as a Location: header.
If I really didn't care about persisting the generated tag, I'd think about what the "user-generated data" was and how much processing is happening behind the scenes. If the "tag" is different enough from whatever data is being passed into the system, GET /tag might be really confusing for an API consumer.
I'll second Brian's answer: use a GET. If the same input parameters return the same output, and you're not really creating anything, it's an idempotent action and thus perfectly suited for a GET.
You can use GET and POST either:
GET /tag?data="..." -> 200, tag
The GET method means retrieve whatever information (in the form of an
entity) is identified by the Request-URI. If the Request-URI refers to
a data-producing process, it is the produced data which shall be
returned as the entity in the response and not the source text of the
process, unless that text happens to be the output of the process.
POST /tag {data: "..."} -> 200, tag
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.
according to the HTTP standard / method definitions section.
I would use GET if I were you (and POST only if you want to send files).
What is the practical benefit of using HTTP GET, PUT, DELETE, POST, HEAD? Why not focus on their behavioral benefits (safety and idempotency), forgetting their names, and use GET, PUT or POST depending on which behavior we want?
Why shouldn't we only use GET, PUT and POST (and drop HEAD, DELETE)?
The [REST][1] approach uses POST, GET, PUT and DELETE to implement the CRUD rules for a web resource. It's a simple and tidy way to expose objects to requests on the web. It's web services without the overheads.
Just to clarify the semantic differences. Each operation is rather different. The point is to have nice HTTP methods that have clear, distinct meanings.
POST creates new objects. The URI has no key; it accepts a message body that defines the object. SQL Insert. [Edit While there's no technical reason for POST to have no key, the REST folks suggest strongly that for POST to have distinct meaning as CREATE, it should not have a key.]
GET retrieves existing objects. The URI may have a key, depends on whether you are doing singleton GET or list GET. SQL Select
PUT updates an existing object. The URI has a key; It accepts a message body that updates an object. SQL Update.
DELETE deletes an existing object. The URI has a key. SQL Delete.
Can you update a record with POST instead of PUT? Not without introducing some ambiguity. Verbs should have unambiguous effects. Further, POST URI's have no key, where PUT must have a key.
When I POST, I expect a 201 CREATED. If I don't get that, something's wrong. Similarly, when I PUT, I expect a 200 OK. If I don't get that, something's wrong.
I suppose you could insist on some ambiguity where POST does either POST or PUT. The URI has to be different; also the associated message could be different. Generally, the REST folks take their cue from SQL where INSERT and UPDATE are different verbs.
You could make the case that UPDATE should insert if the record doesn't exist or update if the record does exist. However, it's simpler if UPDATE means UPDATE and failure to update means something's wrong. A secret fall-back to INSERT makes the operation ambiguous.
If you're not building a RESTful interface, then it's typical to only use GET and POST for retrieve and create/update. It's common to have URI differences or message content differences to distinguish between POST and PUT when a person is clicking submit on a form. It, however, isn't very clean because your code has to determine if you're in the POST=create case or POST=update case.
POST has no guarantees of safety or idempotency. That's one reason for PUT and DELETE—both PUT and DELETE are idempotent (i.e., 1+N identical requests have the same end result as just 1 request).
PUT is used for setting the state of a resource at a given URI. When you send a POST request to a resource at a particular URI, that resource should not be replaced by the content. At most, it should be appended to. This is why POST isn't idempotent—in the case of appending POSTS, every request will add to the resource (e.g., post a new message to a discussion forum each time).
DELETE is used for making sure that a resource at a given URI is removed from the server. POST shouldn't normally be used for deleting except for the case of submitting a request to delete. Again, the URI of the resource you would POST to in that case shouldn't be the URI for the resource you want to delete. Any resource for which you POST to is a resource that accepts the POSTed data to append to itself, add to a collection, or to process in some other way.
HEAD is used if all you care about is the headers of a GET request and you don't want to waste bandwidth on the actual content. This is nice to have.
Why do we need more than POST? It allows data to flow both ways, so why would GET be needed? The answer is basically the same as for your question. By standardizing the basic expectations of the various methods other processes can better know what to do.
For example, intervening caching proxies can have a better chance of doing the correct thing.
Think about HEAD for instance. If the proxy server knows what HEAD means then it can process the result from a previous GET request to provide the proper answer to a HEAD request. And it can know that POST, PUT and DELETE should not be cached.
No one posted the kind of answer I was looking for so I will try to summarize the points myself.
"RESTful Web Services" chapter 8 section "Overloading POST" reads: "If you want to do without PUT and DELETE altogether, it’s entirely RESTful to expose safe operations on resources through GET, and all other operations through overloaded POST. Doing this violates my Resource-Oriented Architecture, but it conforms to the less restrictive rules of REST."
In short, replacing PUT/DELETE in favor of POST makes the API harder to read and PUT/DELETE calls are no longer idempotent.
In a word:
idempotency
In a few more words:
GET = safe + idempotent
PUT = idempotent
DELETE = idempotent
POST = neither safe or idempotent
'Idempotent' just means you can do it over and over again and it will always do exactly the same thing.
You can reissue a PUT (update) or DELETE request as many times as you want and it will have the same effect every time, however the desired effect will modify a resource so it is not considered 'safe'.
A POST request should create a new resource with every request, meaning the effect will be different every time. Therefore POST is not considered safe or idempotent.
Methods like GET and HEAD are just read operations and are therefore considered 'safe' aswell as idempotent.
This is actually a pretty important concept because it provides a standard/consistent way to interpret HTTP transactions; this is particularly useful in a security context.
Not all hosters don't support PUT, DELETE.
I asked this question, in an ideal world we'd have all the verbs but....:
RESTful web services and HTTP verbs
HEAD is really useful for determining what a given server's clock is set to (accurate to within the 1 second or the network round-trip time, whichever is greater). It's also great for getting Futurama quotes from Slashdot:
~$ curl -I slashdot.org
HTTP/1.1 200 OK
Date: Wed, 29 Oct 2008 05:35:13 GMT
Server: Apache/1.3.41 (Unix) mod_perl/1.31-rc4
SLASH_LOG_DATA: shtml
X-Powered-By: Slash 2.005001227
X-Fry: That's a chick show. I prefer programs of the genre: World's Blankiest Blank.
Cache-Control: private
Pragma: private
Connection: close
Content-Type: text/html; charset=iso-8859-1
For cURL, -I is the option for performing a HEAD request. To get the current date and time of a given server, just do
curl -I $server | grep ^Date
To limit ambiguity which will allow for better/easier reuse of our simple REST apis.
You could use only GET and POST but then you are losing out on some of the precision and clarity that PUT and DELETE bring. POST is a wildcard operation that could mean anything.
PUT and DELETE's behaviour is very well defined.
If you think of a resource management API then GET, PUT and DELETE probably cover 80%-90% of the required functionality. If you limit yourself to GET and POST then 40%-60% of your api is accessed using the poorly specified POST.
Web applications using GET and POST allow users to create, view, modify and delete their data, but do so at a layer above the HTTP commands originally created for these purposes. One of the ideas behind REST is a return to the original intent of the design of the Web, whereby there are specific HTTP operations for each CRUD verb.
Also, the HEAD command can be used to improve the user experience for (potentially large) file downloads. You call HEAD to find out how large the response is going to be and then call GET to actually retrieve the content.
See the following link for an illustrative example. It also suggests one way to use the OPTIONS http method, which hasn't yet been discussed here.
There are http extensions like WebDAV that require additional functionally.
http://en.wikipedia.org/wiki/WebDAV
The web server war from the earlier days probably caused it.
In HTTP 1.0 written in 1996, there were only GET, HEAD, and POST. But as you can see in Appendix D, vendors started to add their own things. So, to keep HTTP compatible, they were forced to make HTTP 1.1 in 1999.
However, HTTP/1.0 does not sufficiently take into consideration
the effects of hierarchical proxies, caching, the need for
persistent connections, or virtual hosts. In addition, the proliferation
of incompletely-implemented applications calling themselves
"HTTP/1.0" has necessitated a protocol version change in order for
two communicating applications to determine each other's true capabilities.
This specification defines the protocol referred to as "HTTP/1.1". This protocol includes more stringent requirements than HTTP/1.0 in order
to ensure reliable implementation of its features.
GET, PUT, DELETE and POST are holdovers from an era when sophomores thought that a web page could be reduced to a few hoighty-toity principles.
Nowadays, most web pages are composite entities, which contain some or all of these primitive operations. For instance, a page could have forms for viewing or updating customer information, which perhaps spans a number of tables.
I usually use $_REQUEST[] in php, not really caring how the information arrived. I would choose to use GET or PUT methods based on efficiency, not the underlying (multiple) paradigms.