0

I often find it difficult to manage complex GET requests without sending a JSON body. URL parameters just won't cut it. If I manage to find a work around with URL parameters, then it usual y adds more complexity and confusion.

I am not a web developer and I have not done any big applications but even small-ish applications that I do have requests like this:

{ page: { batch: 10, current: 1 }
, sort: { _id: -1 } 
, project: {history: 0, attach: 0}
, filter: { status: "new"}
}

This is a simple request without arrays. Arrays just make this even more problematic.

So, my questions are how do you manage complex GET requests without JSON body? What am I doing/thinking wrong? Why can't we have body with GET?

Yes, I can probably send this request using URL parameters but it makes life so much more difficult especially when you need to send filters, paging and what not ...

I got tired of all the difficulties and changed such GET requests to POST. I know it is wrong (hence the question) but it feels like huge load off my shoulders.

jww
  • 97,681
  • 90
  • 411
  • 885
r.sendecky
  • 9,933
  • 9
  • 34
  • 62
  • What's wrong with the POST requests? – Veselin Vasilev Mar 23 '15 at 04:52
  • @Veselin Vasilev Nothing wrong with the POST. That's what I use. But it feels wrong to request list of objects with POST. So, most of my APIs end up being "GET-less". It is just so much easier to shoot a structured JSON then fiddle with awkward URL parameters. – r.sendecky Mar 23 '15 at 04:59
  • Using `POST` requests to get a resource is a violation of REST principles. Using `POST` for a paging/filter request is RPC over HTTP. –  Mar 23 '15 at 08:09
  • @LutzHorn that's wrong. By that reasoning, any use of POST would be RPC. Check my answer below. – Pedro Werneck Mar 24 '15 at 14:20
  • @PedroWerneck No, that's not what I wrote. There are valid usages of `POST` like creating a new child (for which the server assigns the full URL) of a collection resource. –  Mar 24 '15 at 16:56
  • @LutzHorn it's implied by what you wrote. You can say POST is RPC when the targeted resource is determined by the payload, not by the URI, like sending an identifier in the payload. – Pedro Werneck Mar 25 '15 at 02:36
  • @PedroWerneck If the resource can not be identified solely by the URI it is not REST (over HTTP). –  Mar 25 '15 at 06:42
  • @LutzHorn that's what I just said. :) – Pedro Werneck Mar 25 '15 at 11:00

2 Answers2

1

I got tired of all the difficulties and changed such GET requests to POST. I know it is wrong (hence the question) but it feels like huge load off my shoulders.

That's not true at all. POST is the method to go for any action that isn't standardized by HTTP. GET is standardized for retrieval, so in principle you can say it's wrong to use POST for something you should do with GET, but there's a catch...

There's absolutely nothing preventing you from sending a payload on a GET request. RFC 7231 says a GET payload has no defined semantics, so it's fine for you to include it as long as you document it. Since there's no standard semantics, you have to determine an uniform interface for your API ecosystem. However, the big problem is that although your application may deal with a GET payload just fine, a lot of HTTP implementations between you and your client might not. Maybe the client or your HTTP server ignores it, or a cache server won't cache it, etc.

With that in mind, POST is also the method to be used to circumvent broken implementations. For instance, many public APIs have a X-HTTP-Method-Override header allowing you to make a PUT or a PATCH request using the POST method, specifying the actual method to be used in the header, in case some implementation in between doesn't understand PUT and PATCH.

So, in your place I would simply use POST and document how I'm using it, as you already did; or I would accept a payload on GET requests and allow clients to use POST to make the request with a payload in case some implementation is broken, setting an override header for that.

Pedro Werneck
  • 40,902
  • 7
  • 64
  • 85
  • OK. This answer gives me some confidence in what I do. I'll continue using POST for complex queries and won't feel guilty/wrong about it. Thanks. – r.sendecky Mar 24 '15 at 02:57
  • You mention the uniform interface. What would the uniform interface be of a `GET` request with a body? If two such requests only differ in payload, would they be for the same or for different resources? –  Mar 24 '15 at 16:54
  • As I said, GET with a body has no defined semantics, so it's up to you. When I use it, I consider the body to have the same meaning as the querystring parameters, but allowing more complexity. Caching might be disabled too, since most cache implementations will ignore a GET body. – Pedro Werneck Mar 24 '15 at 20:40
0

I think that these two links could give you some hints:

I think that it depends on the complexity of the query you want to handle within your request. You can leverage this with query parameters but if it's too complex to design the query with them, you could use a method POST with a content describing it.

You can have a look at the way OData manages this (especially query parameters $filter, $count, $orderby, $skip, and $top). See this link for more details: http://docs.oasis-open.org/odata/odata/v4.0/csprd01/part2-url-conventions/odata-v4.0-csprd01-part2-url-conventions.html#_Toc355091894.

Hope it helps you, Thierry

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360