7

WE are designing an iPhone app that will call back to a RESTful service running in Tomcat. We need to send many query parameters and have exceeded the maximum that the phone will allow.

Would it be RESTful to use a PUT call with the parameters in the body, even though the intent in not to modify the server? A POST does not seem correct because it is not idempotent, while a PUT is (and thus more closely resembles the behavior or of a GET).

Thanks.

Ralph
  • 31,584
  • 38
  • 145
  • 282
  • 4
    The principles and spirit of REST are much more important than your product. Therefore, your product shouldn't exist. – Mark Oct 01 '10 at 17:47
  • 3
    @Mark: Excellent point. If you can't follow the spirit of the law, just stop development! Why didn't I think of that? I'm calling my boss right now and telling him that this crazy data model doesn't fit the original Relational Model as articulated by Chen, and we should really just stop work. Excellent! – S.Lott Oct 01 '10 at 17:52
  • @S.Lott: We are running up against limits on the iPhone (as I said in the original question). – Ralph Oct 01 '10 at 17:52
  • @Aliostad: Why does it matter? Can we send the parameters in the body of a GET if they are XML or JSON? – Ralph Oct 01 '10 at 17:53
  • 1
    just for interest how big is your URI or what is the limit of iphone? Extremely long URIs can be a design smell. Why is it so big? Is it the number of parameters or the size of the parameter-values? – manuel aldana Oct 01 '10 at 18:22
  • Extending off of what @manuel aldana said, sometimes you can compress values into a single value to help compact the length of your get and reduce the number of parameters. So if you had something like ?a=true&b=true&c=false you could instead use ?abc=3 I believe it's called bit masking and is often used in assigning user permissions or setting binary states in applications. I use it for column ordering on webpage data tables. – Snekse Oct 01 '10 at 19:11
  • The values being sent back are a list of object ids that are already on the iPhone. I do not know the length *a-priori*. The developer who is doing the iPhone work is checking on the limits. – Ralph Oct 01 '10 at 19:20
  • Use POST. It is there to handle the cases where the other methods don't work for you. – Darrel Miller Oct 01 '10 at 19:39
  • @Darrel: As I understand it, POST is *not* idempotent. Since this is clearly just a query with multiple parameters, calling the server many times with the same request should **not change the server**. I think PUT is the better choice here. – Ralph Oct 02 '10 at 13:36
  • @Ralph POST is not guaranteed to be idempotent. A particular request may or may not be idempotent. The semantics of PUT are quite precise. It should replace the identified resource with the sent body. – Darrel Miller Oct 02 '10 at 15:50

3 Answers3

6

You have three options that are maximally conformant with HTTP:

First, you have the option of sending your params compressed in some fashion to form a shorter URL.

Second, there's nothing about GET that says you can't send a message-body in the request, in whatever Content-Type or -Length you choose. Not all servers support this, but the HTTP protocol itself does.

Third, you can POST the parameters to a /queries/ resource, and have that respond with 201 Created and a new URL (like /queries/78a65g82) in the Location response header, which the client then calls GET on (repeatedly, or even in Ranges, if that's a benefit) to retrieve the result.

fumanchu
  • 14,419
  • 6
  • 31
  • 36
  • 4
    I think you may find some proxies will not forward a the body of a GET request. – Darrel Miller Oct 01 '10 at 19:33
  • Like Darrel set, you shouldn't pass GET message-payloads, it could work in your dev-setup, but can crash in your prod-setup. It is just too unreliable and the routing (and the involved proxies) often not under you control. – manuel aldana Oct 02 '10 at 15:34
  • +1 for the /queries/78a65g82 suggestion, this is what we use. – balupton Oct 03 '10 at 12:27
  • Unfortunately, this makes your system far less scalable as you need to store this state (and share it amongst multiple instances in fail-over cases for example) -- you'd basically no longer be stateless. There's the question of how long this state should be stored as well and the overhead of making two requests (slows down the user experience as additional round-trips are needed). It's also downright silly as the first response could contain the full answer as all information is known to satisfy it. – john16384 Oct 01 '14 at 05:26
4

If you want it RESTful, you could go about it this way: PUT the parameters to the server (at a location of your choosing), or you could POST them and let the server place them for you. Either way, you have just created a resource that holds the parameters you need. Then you send a GET referring to that particular resource. In answering your GET, the server therefore knows where to get its large set of parameters. That would be RESTful.

That said, however, sending two requests isn't very efficient, if you can do the same thing with a single request. I'd just try to be pragmatic.

Consider this: PUT tells proxies that they shouldn't cache the response, but a retry (by any infrastructure element along the line) is definitely possible, since it's idempotent (just like GET). What does GET give you over PUT? The response can be cached. But with that large number of parameters, I would assume that most requests will be unique anyway, right? So, caching isn't going to deliver much pay off very often. Therefore, using PUT seems to be the pragmatic, and thus the correct choice.

jbrendel
  • 2,390
  • 3
  • 18
  • 18
  • As I said in an earlier comment, the reason we have many parameters is that each one is the ID of a record already on the iPhone. We are trying to keep from resending those records on a refresh. Your comment about not caching and uniqueness is apropos. – Ralph Oct 04 '10 at 11:45
1

It violates the spirit of REST, but if it works, be pragmatic.

Snekse
  • 15,474
  • 10
  • 62
  • 77
  • Is there a RESTful way to do it? I'm not a stickler for the letter of the law (or specification in this case), but would like to follow the standards if there is a way. – Ralph Oct 01 '10 at 17:55