Recommended strategy for passing complex query parameters to a REST API

1,439 views
Skip to first unread message

ke...@amplifieddevelopment.net

unread,
May 19, 2015, 8:50:22 PM5/19/15
to web...@googlegroups.com
We are developing a RESTful API.  One of our use cases requires that we query a resource with somewhat complex search criteria.  Internally, the search criteria would be represented by a data structure similar to this:

search_criteria = {'date':'5/31/2015',
'locations':[{'location_name':'Los Angeles',
'attendees':10,
'services':['Housekeeping','Catering']
},
{'location_name':'New York',
'attendees':5,
'services':['Housekeeping']
}
],
'duration':60
}

What would be a recommended strategy for passing complex query parameters to a RESTful API built with web2py?

Our short term solution has been to provide simple query parameters that can contain delimited values.  For example:

    GET  .../api/available_resources/?date=2015-05-31&locations=Los Angeles|New York&attendees=10|5&services=Housekeeping,Catering|Housekeeping&duration=60

But, this seems less than ideal.  It is not intuitive that Los Angeles should be associated with 10 attendees and the two specified services.

Options we have considered include:
  • Treating the search criteria as a resource.  Thus, we would first POST the complex search criteria and receive a handle in return.  Then, we would GET available_resources, passing the search criteria handle.  (This seems to be messy regarding how to handle the search criteria.  Is it stored statefully in the session?  Is it written to the database?  When would it get cleaned up?)
  • Treat the search as a command.  We would POST a resource search command with a JSON representation of the search criteria in the body.  
  • Implement oData parsing for the query string.  (While it is true that oData syntax could be constructed to meet the needs, yikes!, that's a lot of overhead for the API consumer and the API parser.)
Are any of these considered best practice?  Or, is there yet another strategy that we could consider?

Many thanks for your help!

Kevin



Ron Chatterjee

unread,
May 20, 2015, 12:01:37 AM5/20/15
to web...@googlegroups.com
I have to say, things like this, you can do very well using mongodb. Because its json like structure. And then use lower level pymongo to do search.find_one(). Idk how DAL will handle such dbase setup.

Massimo Di Pierro

unread,
May 20, 2015, 1:38:36 AM5/20/15
to web...@googlegroups.com, ke...@amplifieddevelopment.net
Hello Kevin,

the best way is to make an Ajax request with content type 'application/json' and put the JSON search_criteria into the HTTP request body. For example:

curl -H "Content-Type: application/json" - X POST -d "{...}" http://..../mypage

where {...} is your JSON object. Then in the web2py app

def mypage():
     data = request.post_vars
     ...

data will contain the parsed JSON as a python object.

ke...@amplifieddevelopment.net

unread,
May 21, 2015, 11:42:12 PM5/21/15
to web...@googlegroups.com, ke...@amplifieddevelopment.net
Thanks, Massimo.  I can see how that would work well in the web2py environment.

In our organization, however, we have heterogeneous systems that use REST interfaces to share data.  So, I am hoping to find a solution that aligns as closely as possible with REST principles.

Dave S

unread,
May 22, 2015, 12:57:51 AM5/22/15
to web...@googlegroups.com


On Thursday, May 21, 2015 at 8:42:12 PM UTC-7, ke...@amplifieddevelopment.net wrote:
Thanks, Massimo.  I can see how that would work well in the web2py environment.

In our organization, however, we have heterogeneous systems that use REST interfaces to share data.  So, I am hoping to find a solution that aligns as closely as possible with REST principles.


JSON appears to align with REST principle.  From Wikipedia:
"Unlike SOAP-based web services, there is no "official" standard for RESTful web APIs.[10] This is because REST is an architectural style, while SOAP is a protocol. Even though REST is not a standard per se, most RESTful implementations make use of standards such as HTTP, URI, JSON, and XML."
<URL:en.wikipedia.org/wiki/Representational_state_transfer>

However, your resources may already use a defined API in a non-JSON form.  RedHat, for instance, has a RESTful storage API that uses XML.
In the Web2Py book, chapter 10 has a section on XMLRPC that may be helpful, as well as the REST section:
<URL:http://www.web2py.com/books/default/chapter/29/10/services#Restful-Web-Services>

If the resources are not yet defined, you have the option of choosing any of above choices, and perhaps others, as fits your needs,
while still being RESTful.

/dps



 

Michele Comitini

unread,
May 22, 2015, 6:49:40 AM5/22/15
to web...@googlegroups.com
In REST you can use any data encoding.
I suppose Kevin referst to OData (https://en.wikipedia.org/wiki/Open_Data_Protocol#A_sample_OData_JSON_data_payload) and needs to use GET and not POST, since that is a query not an insertion (PUT) or a modification (POST).
I do not know if OData is apt to make a search query, but one can try the following

GET  .../api/available_resources/?search_criteria='%7B%22date%22%3A%20%225/31/2015%22%2C%20%22duration%22%3A%2060%2C%20%22locations%22%3A%20%5B%7B%22services%22%3A%20%5B%22Housekeeping%22%2C%20%22Catering%22%5D%2C%20%22attendees%22%3A%2010%2C%20%22location_name%22%3A%20%22Los%20Angeles%22%7D%2C%20%7B%22services%22%3A%20%5B%22Housekeeping%22%5D%2C%20%22attendees%22%3A%205%2C%20%22location_name%22%3A%20%22New%20York%22%7D%5D%7D'

search_criteria parameter is created from search_criteria dict as following:

urllib.quote(json.dumps(searc_criteria))


--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Derek

unread,
May 22, 2015, 6:31:39 PM5/22/15
to web...@googlegroups.com
you can also simply urlencode it. as json...

?searchcriteria={'date':'5/31/2015','locations':[{'location_name':'Los+Angeles','attendees':10,'services':['Housekeeping','Catering']},{'location_name':'New+York','attendees':5,'services':['Housekeeping']}],'duration':60}

Massimo Di Pierro

unread,
May 28, 2015, 1:29:33 AM5/28/15
to web...@googlegroups.com, ke...@amplifieddevelopment.net
I assume what you mean by rest principles is that you want to do a GET and not a POST. Problem is some browsers (for example IE) have limits on the size of the path_info in GET methods. So if you do not care about that you can do

.../api/available_resources?query={...}

where query here is a url-encoded jsonobject.
web2py does offer two more sophisticated mechanisms:


Reply all
Reply to author
Forward
0 new messages