I'm building a REST API with flask-restful and one thing I'd like to enable is the ability to batch request resources, similar to how the Facebook Graph API works:
curl \
-F 'access_token=…' \
-F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/friends?limit=50"}]' \
https://graph.facebook.com
Which then returns an array with each request resolved with its status code and result:
[
{ "code": 200,
"headers":[
{ "name": "Content-Type",
"value": "text/javascript; charset=UTF-8" }
],
"body": "{\"id\":\"…\"}"},
{ "code": 200,
"headers":[
{ "name":"Content-Type",
"value":"text/javascript; charset=UTF-8"}
],
"body":"{\"data\": [{…}]}}
]
I've been able to replicate this in flask-restful by simply looping over the requests and calling urlopen against my own app. This seems really inefficient and I have to think there's a better way. Is there a simpler and/or better way to make the requests against my own application from within a request handler?
Since you need to return headers my recommendation is that you send these batched requests into yourself (i.e. send the requests to localhost
), that way the responses will be consistent with those that you would get when making individual calls.
Consider that when your API receives a batch request you will need at least one free worker to take on these indirect requests while the first worker blocks and waits. So you will need to have at least two workers. Even with this you risk a deadlock, if two batch requests arrive at the same time and take your two workers. So in reality you need to have as many workers as batch requests you expect to receive concurrently plus at least one more to handle the indirect requests.
Looking at this from another side, you will want to run as many of these indirect requests in parallel, because if they end up running one after another the benefit of using batch requests is lost. So you also need to have sufficient number of workers to allow for parallelism.
In all honesty I don't see this as a great feature. In most client-side languages it is fairly easy to execute several requests in parallel, so you don't need to provide this is a server-side feature. Specially easy if you are using Javascript, but also easy in Python, Ruby, etc.