6

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?

  • 1
  • Can you add your method's signature as well ? – Muhammad Raja Mar 24 '16 at 13:43
  • @gbjbaanb That's very useful indeed. – Mahdi Mar 24 '16 at 13:45
  • What is the real world case here? – Luc Franken Mar 29 '16 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. – Luc Franken Mar 29 '16 at 15:10
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.

  • 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 Mar 24 '16 at 13:47
  • 2
    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 Mar 24 '16 at 13:51
  • We did something similar to this working with RavenDB and it worked pretty well. – Graham Mar 29 '16 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 Oct 23 '18 at 21:24
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

2

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

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)

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