REST API using POST instead of GET

30

august 2021

REST API using POST instead of GET

De: Tree Web Solutions | Etichete: rest api, post, get, rest, what is rest

Let's assume a service offers some funcionality that I can use like this:

GET /service/function?param1=value1&param2=value2

Is it right to say that I can use it with a POST query?

POST /service/function { param1 : value1, param2 : value2 }

Are these two queries the same? Can I use the second variant in any case or the documentation should explicitly say that I can use both GET and POST queries?

There's no general answer to this - it depends on the individual implementation. And GET and POST should have different semantics, so maybe the general answer is "I hope not".
  • REST and function don't go well together. If an URL contains functionmethod, or command, I smell RPC.
     
  • if your goal is to hide the complexity from the url structure itself, don't bother. using a POST method just to clean it up is a misuse of POST if you're trying to follow RESTful principles.
  • There's no general answer to this in an HTTP API that doesn't follow the standard. You can do whatever you want. If it's RESTful, then you can't do a POST if it's not documented what the resource does with it. As a matter of fact, if it's RESTful, it must be using HATEOAS, and you wouldn't be doing an unexpected request to anything.
  • You can often get the same end results even if you use different HTTP verbs. It just depends on what goes inside your route controller and the return value.. etc. Still, it's good to stick to conventions.
  • @Kristian GET request length is limited, what if particular GET request is very complex and simply is too long? How can programmer solve this problem without using POST request, since POST request length is almost unlimited?

You can't use the API using POST or GET if they are not build to call using these methods separetly. Like if your API say

/service/function?param1=value1&param2=value2

is accessed by using GET method. Then you can not call it using POST method if it is not specified as POST method by its creator. If you do that you may got 405 Method not allowed status.

Generally in POST method you need to send the content in body with specified format which is described in content-type header for ex. application/json for json data.

And after that the request body gets deserialized at server end. So you need to pass the serialized data from the client and it is decided by the service developer.

But in general terms GET is used when server returns some data to the client and have not any impact on server whereas POST is used to create some resource on server. So generally it should not be same.

  • Should sever validate the content-type header? What if header is Content-Type: application/x-www-form-urlencoded and content is JSON?
  • But in GET request, the length of a URL is limited (maximum URL length is 2048 characters). So if I want to send a request to the API that has a parameter which is potentially a long string (JSON), I should use POST rather than GET?
  • Yes if your API request is large JSON then you should use POST which allows you to send the request body. Generally GET API doesn't need so many parameters or JSON request

I use POST body for anything non-trivial and line-of-business apps for these reasons:

  1. Security - If we use GET with query strings and https, the query strings can be saved in server logs and forwarded as referral links. Both of these are now visible by server/network admins and the next domain the user went to after leaving your app. So if we send a query containing confidential PII data such as a customer's name this may not be desired.
  2. URL maximum length - Not a big issue, but some browsers have a limit on the length. So if we have several items in our URL like query, paging, fields to return, etc....
  3. POST is not cached by default. Some say caching is desired; however, how often is that exact same set of search criteria for that exact object for that exact customer going to occur before the cache times out anyway?

BTW, I also put the fields to return in my POST body as I may not wish to expose my field names. Security is like an onion; it has many layers and makes us cry!

Query strings are normally saved in web server logs whatever the request type. If you think POST is more secure because you cant see some things then you are mistaken. Caching is something totally different.
  • I think Scott's point was that by using POST instead of GET, you don't have to use query strings at all.
  • Downvoted, The question is specifically about REST according to how the OP tagged it. This answer is irrelevant in this context, since it definitely isn't REST.
  • In this case, how can we differentiate whether a POST call is to create the object or to fetch the response?
It is unfortunate that Angular's Http Service does not allow the transmission of a body with a GET, which would solve the problem when a site is hosted on webservers that accept a body on a GET!

What is REST?

According to wikipedia:

The REST architectural style describes the following six constraints applied to the architecture, while leaving the implementation of the individual components free to design:

  • Client–server: Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable.
  • Stateless: The client–server communication is further constrained by no client context being stored on the server between requests.
  • Cacheable: Responses must, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests.
  • Layered system: A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches.
  • Code on demand (optional): Servers can temporarily extend or customize the functionality of a client by the transfer of executable code.
  • Uniform interface: The uniform interface between clients and servers, discussed below, simplifies and decouples the architecture, which enables each part to evolve independently. (i.e. HTTP GET, POST, PUT, PATCH, DELETE)

What the verbs should do

SO user Daniel Vasallo did a good job of laying out the responsibilities of these methods in the question Understanding REST: Verbs, error codes, and authentication:

When dealing with a Collection URI like: http://example.com/resources/

GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale.

PUT: Meaning defined as "replace the entire collection with another collection".

POST: Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.

DELETE: Meaning defined as "delete the entire collection".

So, to answer your question:

Is it right to say that I can use it with a POST query? ...

Are these two queries the same? Can I use the second variant in any case or the documentation should explicitly say that I can use both GET and POST queries?

If you were writing a plain old RPC API call, they could technically interchangeable as long as the processing server side were no different between both calls. However, in order for the call to be RESTful, calling the endpoint via the GET method should have a distinct functionality (which is to get resource(s)) from the POST method (which is to create new resources).

Side note: there is some debate out there about whether or not POST should also be allowed to be used to update resources... though i'm not commenting on that, I'm just telling you some people have an issue with that point.

So, it seems, REST API specifications are not ready for real-world cases when we want to use some other verb instead of GET for retrieving the list of entities for various reasons (URL length limits, no body support for GET in many frameworks etc.). Which means there are many hacky, inconsistent solutions to work around the issue while there are no specifications to guide developers.

Think about it. When your client makes a GET request to an URI X, what it's saying to the server is: "I want a representation of the resource located at X, and this operation shouldn't change anything on the server." A PUT request is saying: "I want you to replace whatever is the resource located at X with the new entity I'm giving you on the body of this request". A DELETE request is saying: "I want you to delete whatever is the resource located at X". A PATCH is saying "I'm giving you this diff, and you should try to apply it to the resource at X and tell me if it succeeds." But a POST is saying: "I'm sending you this data subordinated to the resource at X, and we have a previous agreement on what you should do with it."

If you don't have it documented somewhere that the resource expects a POST and does something with it, it doesn't make sense to send a POST to it expecting it to act like a GET.

REST relies on the standardized behavior of the underlying protocol, and POST is precisely the method used for an action that isn't standardized. The result of a GET, PUT and DELETE requests are clearly defined in the standard, but POST isn't. The result of a POST is subordinated to the server, so if it's not documented that you can use POST to do something, you have to assume that you can't.

It is nice that REST brings meaning to HTTP verbs (as they defined) but I prefer to agree with Scott Peal.

Here is also item from WIKI's extended explanation on POST request:

There are times when HTTP GET is less suitable even for data retrieval. An example of this is when a great deal of data would need to be specified in the URL. Browsers and web servers can have limits on the length of the URL that they will handle without truncation or error. Percent-encoding of reserved characters in URLs and query strings can significantly increase their length, and while Apache HTTP Server can handle up to 4,000 characters in a URL,[5] Microsoft Internet Explorer is limited to 2,048 characters in any URL.[6] Equally, HTTP GET should not be used where sensitive information, such as user names and passwords, have to be submitted along with other data for the request to complete. Even if HTTPS is used, preventing the data from being intercepted in transit, the browser history and the web server's logs will likely contain the full URL in plaintext, which may be exposed if either system is hacked. In these cases, HTTP POST should be used.

I could only suggest to REST team to consider more secure use of HTTP protocol to avoid making consumers struggle with non-secure "good practice".

  • This does not really provide something new in comparison to Scott Peal's answer. You only quoted wiki/provided and link and regarding this: While a link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. 

If I understand the question correctly, he needs to perform a REST GET action, but wonders if it's OK to send in data via HTTP POST method.

As Scott had nicely laid out in his answer earlier, there are many good reasons to POST input data. IMHO it should be done this way, if quality of solution is the top priority.

A while back we created an REST API to authenticate users, taking username/password and returning an access token. The API is encrypted under TLS, but exposed to public internet. After evaluating different options, we chose HTTP POST for the REST method of "GET access token," because that's the only way to meet security standards.

  • But the post is used to add something, not to get. If we can get the data as a response using the POST method. How can we perform that.

In REST, each HTTP verbs has its place and meaning.

For example,

  • GET is to get the 'resource(s)' that is pointed to in the URL.

  • POST is to instructure the backend to 'create' a resource of the 'type' pointed to in the URL. You can supplement the POST operation with parameters or additional data in the body of the POST call.

In you case, since you are interested in 'getting' the info using query, thus it should be a GET operation instead of a POST operation.

This wiki may help to further clarify things.

POST is valid to use instead of GET if you have specific reasons for doing so and process it properly. I understand it's not specifically RESTy, but if you have a bunch of spaces and ampersands and slashes and so on in your data [eg a product model like Amazon] then trying to encode and decode this can be more trouble than it's worth instead of just pre-jsonifying it. Make sure though that you return the proper response codes and heavily comment what you're doing because it's not a typical use case of POST.

Source: https://stackoverflow.com

 

Distribuie această postare