26

Is it against best-practices to use a POST request to read data? Are there any exceptions to this? e.g. Authentication requests where you have to POST data to perform a read action.

I have an API call that requires a lot of parameters and it's basically a Read action. I can't use GET request because it may hit the URI limit.

I have heard that it's against REST best-practices to use a POST request to read data and I highly prefer to follow the best-practices as the API is supposed to be publicly accessible to the company's clients.

If I should not do that, how should I design my API to properly address these cases?

13
  • 3
  • Can you add your method's signature as well ? Commented Mar 24, 2016 at 13:43
  • @gbjbaanb That's very useful indeed.
    – Mahdi
    Commented Mar 24, 2016 at 13:45
  • What is the real world case here? Commented Mar 29, 2016 at 12:00
  • 1
    If you stick to not saving then yes your only option is to use parameters. In that way your only option is to reduce their size (like single character params names: ?l=1221331,1212321&d=123213123etc). In REST you would more likely create a resource: POST /routes which then returns; /routes/somerandomid so you can keep updating the resource. So you would store it then. If you don't want long term storage you could even add a timer (cron) after which you remove the older rows. Just make sure your code understands error 404 and that will work quite seamless also. Commented Mar 29, 2016 at 15:10

4 Answers 4

7

One thing we've done where I work is to have a "storage" service API. Basically, you POST a JSON object to the service, and it returns a UUID. You send the UUID as a query parameter on any subsequent API call and it will get the parameters/data from the storage service. It's especially handy if you will be making multiple calls with the same data, as you only have to send it once.

5
  • That's one of the things we were thinking here also, but I'm not sure about the pros and cons of this method.
    – Mahdi
    Commented Mar 24, 2016 at 13:47
  • 4
    Cons are it does add a level of indirection to calls that use the service, and if you don't have some kind of expiration policy you wind up with a lot of abandoned data. Pros are you avoid the issue you're having, and it's more RESTful than reading with a POST, plus you can share data across multiple calls, so you can establish a "context" for a series of related calls.
    – TMN
    Commented Mar 24, 2016 at 13:51
  • We did something similar to this working with RavenDB and it worked pretty well.
    – GHP
    Commented Mar 29, 2016 at 12:22
  • Even though I upvoted the answer as a recognition of interesting thinking on TMN's part I would still advice caution with this technique. It just doesn't sound a very good idea to bind the client side to the server side like this. At the very least it's unexpected and "counter-intuitive" trying to explain such an approach for a ReST API. It also makes the backend more complex and might require more roundtrips to the db to fetch the pre-stored POST data. Just saying.
    – XDS
    Commented Oct 23, 2018 at 21:24
  • 1
    I just had a long conversation with a customer of mine, explaining how our API uses this pattern. He just wanted to consume the data, then get on with is life. After a while explaining how this was the restful way, he agreed, but then said "but its not really out-of-the-box". That was a gentle way of explaining to me how this approach is flawed. Yes I will continue to push and support this way of consuming our data, but ultimately a POST with a relevant response would make my customers' life simpler. As such I'm considering to just add it as an alternative way to "just get the our data". Commented Oct 1, 2020 at 21:27
3

After reading couple of similar questions I realised that REST is not actually designed to solve this problem. So I have decided to go for JSON-RPC rather REST which offers more flexibility and seems to be the right solution for these sort of problems.

1
  • 2
    5 years later: how did it go?
    – jcollum
    Commented Nov 2, 2021 at 18:55
2

Yes, you can make it work at least using WCF, it's bit different in MVC and Web API where you add attributes to methods like [GET] [POST] etc..

I have heard that it's against REST best-practices to use a POST request to read data and I highly prefer to follow the best-practices as the API is supposed to be publicly accessible to the company's clients.

Off course it is bad practice to use POST for getting data as POST is for creating resources in system not getting them.

Best practices for REST

I have an API call that requires a lot of parameters and it's basically a Read action. I can't use GET request because it may hit the URI limit.

Use array for sending parameters or create objects if your parameters are related

1
  • 2
    "Use array for sending parameters or create objects if your parameters are related" isn't a great deal of use without an example.
    – holdenweb
    Commented Apr 20, 2022 at 18:00
0

To improve on TMT's answer instead of using a storage service to store UUIDs against request parameters. You can instead write a stateless API using JSON Web Tokens. This will eliminate the issue of managing storage, will allow reuse and caching.

The flow will look like this:

  1. Client sends a JSON object with request params as a POST request to your Tokenize API.
  2. API returns a JSON Web Token generated using JSON object provided as payload.
  3. Client issues a GET request to your actual API with that token as a parameter.
  4. Your API (or ideally a middleware) decodes the token to get the request params and processes the request.

This method requires no storage.
Implementation of actual API does not require any special consideration.
Ensures tokens do not get tampered on the way.
Since there is no state there is no need to worry about data corruption. Caching is much easier. Applying to multiple APIs is trivial and can be done without supervision of any other team member.

Keep in mind that if your payload is too large JWT can be large too. Ensure your url length does not exceed 2000 characters. I tried with a 1.9K JSON and got a 1695 char JWT (which should be more than enough IMO)

1
  • 1
    You can do this using httpGet and adding those strings in header. Commented Jun 23, 2021 at 8:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.