Skip to content

Instantly share code, notes, and snippets.

@shifr
Last active August 29, 2019 13:01
Show Gist options
  • Save shifr/c409f23eedca6e79ced7adc288a95c4a to your computer and use it in GitHub Desktop.
Save shifr/c409f23eedca6e79ced7adc288a95c4a to your computer and use it in GitHub Desktop.
Aiohttp: execute subrequest inside current request
import json
from aiohttp.web import Request, json_response
async def sub_request_handler(request: Request):
request._read_bytes = None # to have an ability to clone the root request
sub_requests = [
{"url": "/api/v1/sub-url-1", "method": "POST", "payload": {"param1": "value1"}},
{"url": "/api/v1/sub-url-2/entity-id", "method": "PATCH", "payload": {"param2": "value2"}},
{"url": "/api/v1/sub-url-3/entity-id", "method": "DELETE"},
]
responses = []
for sub_req_data in sub_requests:
payload = sub_req_data.get("payload")
sub_req = request.clone(method=sub_req_data["method"], rel_url=sub_req_data["url"]) # clone root request with new params
if payload:
body = json.dumps(payload).encode()
sub_req._read_bytes = body # now `await sub_req.json()` will return `body`
sub_req._payload.unread_data(body) # feed body to sub request to replace its `content` property with `body`
route_info = await request.app.router.resolve(sub_req) # resolve a router for the sub request
sub_req._match_info = route_info # it should match
sub_resp = await route_info.handler(sub_req) # call router handler with the sub request
try:
sub_resp_body = json.loads(sub_resp.text) # read sub response
except json.JSONDecodeError:
sub_resp_body = {}
response_payload = {"code": sub_resp.status, "payload": sub_resp_body} # fill sub response payload
responses.append(response_payload)
return json_response({"data": responses}) # return all payloads from sub requests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment