Meaningless Drivel is fun!*
The moose likes Web Services and the fly likes RESTful APIs: GETs with bodies? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Java » Web Services
Bookmark "RESTful APIs: GETs with bodies?" Watch "RESTful APIs: GETs with bodies?" New topic
Author

RESTful APIs: GETs with bodies?

Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 60077
    
  65

OK, I've done some poking around, and it seems that the HTTP Specification doesn't specifically prohibit GET request with bodies, but it's just something doesn't get done very often. In fact, libraries like HttpClient don't even allow it (hence my question here).

As we know, GETs should be used when a resource is being queried with no effects on the server state.

What I'm thinking of is a GET that obtains a list of resources based upon search criteria that is on the complicated side -- too lengthy and too complicated to flatten into a simple name/value query string. An XML representation is perfect, but because of the no-body nature of the traditional GET, there's really no way to send such information along.

What say you RESTers? How would you handle this?

Simply defining it as a POST (or worse, a PUT) simply so that the search criteria can be carried in the request body seems to violate the precepts of REST and feels just plain dirty.


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 60077
    
  65

P.S. I found this while poking around.
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2906
Originally posted by Bear Bibeault:
What I'm thinking of is a GET that obtains a list of resources based upon search criteria that is on the complicated side -- too lengthy and too complicated to flatten into a simple name/value query string. An XML representation is perfect, but because of the no-body nature of the traditional GET, there's really no way to send such information along.


The RESTian way to deal with this is to create a query result resource.
  • POST the query representation to the parent search resource. A successful search will return the result resource URI.
  • GET the result resource representation.


  • How long you intend to keep your result resource around is up to you. If the searched space is fairly static you can reuse the result for duplicate queries for a limited amount of time. You could even allow the creator to DELETE the result (though a timeout would still be necessary).

    A GET with a body wouldn't be considered RESTful - in my opinion - because the search result wouldn't have a unique URI as it is the case with query parameters in the URI. A GET with a body is RPC all over again ...
    [ November 20, 2008: Message edited by: Peer Reynders ]

    "Don't succumb to the false authority of a tool or model. There is no substitute for thinking."
    Andy Hunt, Pragmatic Thinking & Learning: Refactor Your Wetware p.41
    Bear Bibeault
    Author and ninkuma
    Marshal

    Joined: Jan 10, 2002
    Posts: 60077
        
      65

    Originally posted by Peer Reynders:
    The RESTian way to deal with this is to create a query result resource.
    Ah. I hadn't considered a 2-phase, dynamic resource approach.

    Can you tell I'm new to this REST stuff?

    A GET with a body wouldn't be considered RESTful - in my opinion - because the search result wouldn't have a unique URI as it is the case with query parameters in the URI.
    Got it!

    Thanks.
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2906
    Originally posted by Peer Reynders:
    If the searched space is fairly static you can reuse the result for duplicate queries for a limited amount of time.


    Another scenario for a dynamic search space would be that the result resource implementation actually stores the query - so it processes the query every time a GET is performed on it, returning an updated result representation. The resource's lease on life could be extended every time it experiences a GET. Furthermore the client could submit a desired life span for the result resource in the query representation - in case an (automated) client wants to periodically repeat the query.

    The only problem with this implementation is that the resource's representation wouldn't be cache-able any longer, as it could change at any point of time. You could still save sending identical representations over the wire by supporting conditional-GET (with the If-None-Match HTTP Header); that would require that you send back an ETag HTTP Header that contains the hash sum for the result representation for every normal GET. Once you have that in place you have the motivation to place implementation optimizations for detecting whether a new result set will differ from an earlier one.

    As you can see the RESTful approach tends to create more opportunities for achieving scalability compared to an RPC-oriented approach (that doesn't mean that it comes for free).

    I also didn't explicitly mention that the result resource would be a sub-resource to the parent search resource ("parent" was meant to imply that).
    [ November 20, 2008: Message edited by: Peer Reynders ]
    Bear Bibeault
    Author and ninkuma
    Marshal

    Joined: Jan 10, 2002
    Posts: 60077
        
      65

    Originally posted by Peer Reynders:
    I also didn't explicitly mention that the result resource would be a sub-resource to the parent search resource ("parent" was meant to imply that).

    Could you expand that into a larger paragraph?
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2906
    A crude example:



    So by URI design /query/results/A34FA0095 is a sub-resource to /query/results - /query/results is the "parent" of /query/results/A34FA0095. I call this crude because best practices dictate that you should use "meaningful" URIs. The context decides what is meaningful. A contrived example would be /query/results/USA/Houston/A34FA0095 - it could mean that the query's "most significant" query parameter values are "USA" and "Houston" while the hash value for the complete set of query parameter names and values is "A34FA0095".
    [ November 20, 2008: Message edited by: Peer Reynders ]
    Bear Bibeault
    Author and ninkuma
    Marshal

    Joined: Jan 10, 2002
    Posts: 60077
        
      65

    Excellent. That gives me enough of a framework to move on this. Thanks muchly!
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: RESTful APIs: GETs with bodies?
     
    Similar Threads
    Alternatives to HttpClient?
    RESTful query query #2: Executing a stored query
    Java sound: how to play a file?
    How to get response code and message when using jersey client
    Astral Projection