Example:
URL: http://example.com/collection/a%20search%20term
Method: GET
Response: All items in collection matching a search term.
Problem: The search term may be so long that it breaks the web server's maximum
URL length.
How do I allow extremely long search terms and still stay RESTful?
For inspiration, I just looked at Google Translate's API v2, which is "using
the RESTful calling style."
Naturally, texts to be translated can be quite long. And so Google optionally
allows sending a request with POST, but with a twist:
To use POST, you must use the X-HTTP-Method-Override header to tell the
Translate API to treat the request as a GET (use X-HTTP-Method-Override:
GET).
So it is possible to semantically transform a POST request into a GET request.
(This discovery led me to add the x-http-method-override tag to my question.)
REST does not restrict POST to creation. Be careful with mapping CRUD to HTTP methods and assume that's RESTful. POST is the method used for any action that isn't standardized by HTTP.
Since the standard doesn't establish a limit for URIs, this can be considered a broken implementation, and it's ok to fix it. As long as the workaround is loosely coupled to your API, you are still RESTful. This means your API shouldn't implement a translation or override directly, but on a pre-processor of some kind that rewrites the request properly. It should be clearly documented somewhere that this is due to a broken implementation, and you expect it to eventually become obsolete.
It's a bad smell if your query can be so long that it exceeds the maximum length (de facto for browsers is 2000 characters but it can be higher for other means of accessing REST APIs).
If the user can pass in that much data, it should go in the request body/data field, not in the URL.
Related
What's the most appropriate way in REST to export something as PDF or other document type?
The next example explains my problem:
I have a resource called Banana.
I created all the canonical CRUD rest endpoint for that resource (i.e. GET /bananas; GET /bananas/{id}; POST /bananas/{id}; ...)
Now I need to create an endpoint which downloads a file (PDF, CSV, ..) which contains the representation of all the bananas.
First thing that came to my mind is GET /bananas/export, but in pure rest using verbs in url should not be allowed. Using a more appropriate httpMethod might be cool, something like EXPORT /bananas, but unfortunately this is not (yet?) possible.
Finally I thought about using the Accept header on the same GET /bananas endpoint, which based on the different media type (application/json, application/pdf, ..) returns the corresponding representation of the data (json, pdf, ..), but I'm not sure if I am misusing the Accept header in this way.
Any ideas?
in pure rest using verbs in url should not be allowed.
REST doesn't care what spelling conventions you use in your resource identifiers.
Example: https://www.merriam-webster.com/dictionary/post
Even though "post" is a verb (and worse, an HTTP method token!) that URI works just like every other resource identifier on the web.
The more interesting question, from a REST perspective, is whether the identifier should be the same that is used in some other context, or different.
REST cares a lot about caching (that's important to making the web "web scale"). In HTTP, caching is primarily about re-using prior responses.
The basic (but incomplete) idea being that we may be able to re-use a response that shares the same target URI.
HTTP also has built into it a general purpose mechanism for invalidating stored responses that is also focused on the target URI.
So here's one part of the riddle you need to think about: when someone sends a POST request to /bananas, should caches throw away the prior responses with the PDF representations?
If the answer is "no", then you need a different target URI. That can be anything that makes sense to you. /pdfs/bananas for example. (How many common path segments are used in the identifiers depends on how much convenience you will realize from relative references and dot segments.)
If the answer is "yes", then you may want to lean into using content negotiation.
In some cases, the answer might be "both" -- which is to say, to have multiple resources (each with its own identifier) that return the same representations.
That's a normal thing to do; we even have a mechanism for describing which resource is "preferred" (see RFC 6596).
REST does not care about this, but the HTTP standard does. Using the accept header for the expected MIME type is the standard way of doing this, so you did the right thing. No need to move it to a separate endpoint if the data is the same just the format is different.
Media types are the best way to represent this, but there is a practical aspect of this in that people will browse a rest API using root nouns... I'd put some record-count limits on it, maybe GET /bananas/export/100 to get the first 100, and GET /bananas/export/all if they really want all of them.
I understand the semantics of GETting vs. POSTing, one endpoint should get data, the other should post it. The latter being a request that you may not wish the user to be able to easily replay.
That said, on the project I'm working on at the moment - the approach has been to POST to endpoints that are clearly responsible for responding with data, and these endpoints do not transform data in any way.
The reasoning behind this has been that the payloads are (potentially) of considerable size and seem more appropriate for a body as opposed to a query string.
Can anybody please shed light on which request would be right for a GET request that takes a large request payload? I'm not asking for opinion, I'm asking for what would be compliant to RESTful deisgn.
Further Context
The request is potentially large due to the fact it's a search DTO from the UI, where users may choose to pass any number of filters or search terms.
Can anybody please shed light on which request would be right for a GET request that takes a large request payload? I'm not asking for opinion, I'm asking for what would be compliant to RESTful deisgn.
Today's answer: It's OK to use POST.
For requests that are fundamentally read-only, we'd like to use standardized HTTP semantics to communicate that to general purpose components, so that they can themselves do intelligent things.
BUT: GET, while being both safe and ubiquitous, isn't an appropriate choice when you need to include a message-body in the request:
content received in a GET request has no generally defined semantics
So if you can't, for whatever reason, copy the information you need into a resource identifier, then GET is not an option.
Now, if your payloads are consistent with WebDAV, then you might be able to use one of the safe methods described in those specifications. But, as far as I can tell, they aren't really appropriate for general use.
Tomorrow's answer: the HTTP-WG accepted a proposal for a safe-method-with-body. So we should eventually expect to see a registered HTTP method that is safe and has defined semantic for the request content.
Then, depending on what those semantics are, we may be able to use it for requests like yours.
I am designing my first REST API.
Suppose I have a (SOAP) web service that takes MyData1 and returns MyData2.
It is a pure function with no side effects, for example:
MyData2 myData2 = transform(MyData myData);
transform() does not change the state of the server. My question is, what REST call do I use? MyData can be large, so I will need to put it in the body of the request, so POST seems required. However, POST seems to be used only to change the server state and not return anything, which transform() is not doing. So POST might not be correct? Is there a specific REST technique to use for pure functions that take and return something, or should I just use POST, unload the response body, and not worry about it?
I think POST is the way to go here, because of the sheer fact that you need to pass data in the body. The GET method is used when you need to retrieve information (in the form of an entity), identified by the Request-URI. In short, that means that when processing a GET request, a server is only required to examine the Request-URI and Host header field, and nothing else.
See the pertinent section of the HTTP specification for details.
It is okay to use POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
It's not a great answer, but it's the right answer. The real issue here is that HTTP, which is a protocol for the transfer of documents over a network, isn't a great fit for document transformation.
If you imagine this idea on the web, how would it work? well, you'd click of a bunch of links to get to some web form, and that web form would allow you to specify the source data (including perhaps attaching a file), and then submitting the form would send everything to the server, and you'd get the transformed representation back as the response.
But - because of the payload, you would end up using POST, which means that general purpose components wouldn't have the data available to tell them that the request was safe.
You could look into the WebDav specifications to see if SEARCH or REPORT is a satisfactory fit -- every time I've looked into them for myself I've decided against using them (no, I don't want an HTTP file server).
According REST API design recomendations, getting user by id must be
GET /users/{id}
How will look getting user by unique phone number?
GET /users/phone/{number}
or
GET /users/?phone=xxxxxxxxxxx
or
GET /phones/{number}/users
or anything else?
Or for example getting last user comments with limitation:
/users/{id}/comments/limit/{limit}
or
/users/{id}/comments/?limit='xx'
There are constraints or recomendations in such cases?
Which HTTP method is better to send request for making some actions (for example SMS sending).
There are a lot of different aspects in your question, so I am picking some and hope the answer is somewhat helpful to you.
Generally speaking, a URI ist he unique identifier of a certain ressource. Further more, "good REST-API URIs" contain only nouns (to 'name' the resource), not verbs (what should be done with the resource). URI parameters may be used to parameterize the ressources representation, e.g. sorting or filtering.
In your example,
/users/{id}/?limit='xx'
would be a valid way to fetch a list of some sub-ressources (possibly the users comments), but here is nothing on the URI that refers to a specific property or sub-ressource (e.g. comments).
A more meaningful ressource URI would be
/useres/{id}/comments/?max=100&sort=asc
In this case, the first part (users/{id}/comments/) identifies the ressource, while the params are used to parameterize its representation. Proper URI's do not rely on URI params to uniquely identify ressources.
Filter criteria in the URI may be treated similiar. You could put them in parameters, but that may lead to problems with multiple and/or complex filters, e.g.
GET
/useres/?phone=1234&phonemode=startswith&name=foo&namemode=contains
One way to do this could be to create a filter (maybe just temporarily) and then retrieving the filtered information with a subsequent GET request like this:
POST /users/filter
name='mycomplexfilter'
poperty='name'
value='foo'
mode='contains'
GET /useres/filter/mycomplexfilter
Hope this helps to shed some light on the topic
[EDIT]
See this summary for an explanation of the commonly used HTTP methods (aka verbs): Which HTTP methods match up to which CRUD methods?
See this question for a similiar answer.
Initiating a server sent notification (perhaps via SMS) should be requested using POST (e.g. to the ressource URI /notifications) with text and recipient in the payload. HTTP headers could be used to indicate the desired type of the notfication, while the HTTP status codes indicate the success of the sending attempt. Status code 201 indicates successfull sending of the message, returning also the URI for the newly created ressource.
Client request:
POST /notifications
recipient="+0049123456789"
text="this is the SMS text"
Server response:
201 - Created
Location: /notifications/9876
I get confused when and why should you use specific verbs in REST?
I know basic things like:
Get -> for retrieval
Post -> adding new entity
PUT -> updating
Delete -> for deleting
These attributes are to be used as per the operation I wrote above but I don't understand why?
What will happen if inside Get method in REST I add a new entity or inside POST I update an entity? or may be inside DELETE I add an entity. I know this may be a noob question but I need to understand it. It sounds very confusing to me.
#archil has an excellent explanation of the pitfalls of misusing the verbs, but I would point out that the rules are not quite as rigid as what you've described (at least as far as the protocol is concerned).
GET MUST be safe. That means that a GET request must not change the server state in any substantial way. (The server could do some extra work like logging the request, but will not update any data.)
PUT and DELETE MUST be idempotent. That means that multiple calls to the same URI will have the same effect as one call. So for example, if you want to change a person's name from "Jon" to "Jack" and you do it with a PUT request, that's OK because you could do it one time or 100 times and the person's name would still have been updated to "Jack".
POST makes no guarantees about safety or idempotency. That means you can technically do whatever you want with a POST request. However, you will lose any advantage that clients can take of those assumptions. For example, you could use POST to do a search, which is semantically more of a GET request. There won't be any problems, but browsers (or proxies or other agents) would never cache the results of that search because it can't assume that nothing changed as a result of the request. Further, web crawlers would never perform a POST request because it could not assume the operation was safe.
The entire HTML version of the world wide web gets along pretty well without PUT or DELETE and it's perfectly fine to do deletes or updates with POST, but if you can support PUT and DELETE for updates and deletes (and other idempotent operations) it's just a little better because agents can assume that the operation is idempotent.
See the official W3C documentation for the real nitty gritty on safety and idempotency.
Protocol is protocol. It is meant to define every rule related to it. Http is protocol too. All of above rules (including http verb rules) are defined by http protocol, and the usage is defined by http protocol. If you do not follow these rules, only you will understand what happens inside your service. It will not follow rules of the protocol and will be confusing for other users. There was an example, one time, about famous photo site (does not matter which) that did delete pictures with GET request. Once the user of that site installed the google desktop search program, that archieves the pages locally. As that program knew that GET operations are only used to get data, and should not affect anything, it made GET requests to every available url (including those GET-delete urls). As the user was logged in and the cookie was in browser, there were no authorization problems. And the result - all of the user photos were deleted on server, because of incorrect usage of http protocol and GET verb. That's why you should always follow the rules of protocol you are using. Although technically possible, it is not right to override defined rules.
Using GET to delete a resource would be like having a function named and documented to add something to an array that deletes something from the array under the hood. REST has only a few well defined methods (the HTTP verbs). Users of your service will expect that your service stick to these definition otherwise it's not a RESTful web service.
If you do so, you cannot claim that your interface is RESTful. The REST principle mandates that the specified verbs perform the actions that you have mentioned. If they don't, then it can't be called a RESTful interface.