forked from platypush/platypush
Implemented support for returning richer HTTP responses on webhooks.
A `WebhookEvent` hook can now return a tuple in the format `(data, http_code, headers)` in order to customize the HTTP status code and the headers of a response.
This commit is contained in:
parent
96b2ad148c
commit
c5b12403d0
2 changed files with 39 additions and 6 deletions
|
@ -1,7 +1,6 @@
|
|||
import json
|
||||
|
||||
from flask import Blueprint, abort, request
|
||||
from flask.wrappers import Response
|
||||
from flask import Blueprint, abort, request, make_response
|
||||
|
||||
from platypush.backend.http.app import template_folder
|
||||
from platypush.backend.http.app.utils import logger, send_message
|
||||
|
@ -61,14 +60,31 @@ def hook_route(hook_name):
|
|||
|
||||
try:
|
||||
send_message(event)
|
||||
rs = make_response(json.dumps({'status': 'ok', **event_args}))
|
||||
headers = {}
|
||||
status_code = 200
|
||||
|
||||
# If there are matching hooks, wait for their completion before returning
|
||||
if matching_hooks:
|
||||
return event.wait_response(timeout=60)
|
||||
rs = event.wait_response(timeout=60)
|
||||
try:
|
||||
rs = json.loads(rs.decode()) # type: ignore
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return Response(
|
||||
json.dumps({'status': 'ok', **event_args}), mimetype='application/json'
|
||||
)
|
||||
if isinstance(rs, dict) and '___data___' in rs:
|
||||
# data + http_code + custom_headers return format
|
||||
headers = rs.get('___headers___', {})
|
||||
status_code = rs.get('___code___', status_code)
|
||||
rs = rs['___data___']
|
||||
|
||||
rs = make_response(rs)
|
||||
else:
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
rs.status_code = status_code
|
||||
rs.headers.update(headers)
|
||||
return rs
|
||||
except Exception as e:
|
||||
logger().exception(e)
|
||||
logger().error('Error while dispatching webhook event %s: %s', event, str(e))
|
||||
|
|
|
@ -58,6 +58,23 @@ class WebhookEvent(Event):
|
|||
|
||||
def send_response(self, response):
|
||||
output = response.output
|
||||
if isinstance(output, tuple):
|
||||
# A 3-sized tuple where the second element is an int and the third
|
||||
# is a dict represents an HTTP response in the format `(data,
|
||||
# http_code headers)`.
|
||||
if (
|
||||
len(output) == 3
|
||||
and isinstance(output[1], int)
|
||||
and isinstance(output[2], dict)
|
||||
):
|
||||
output = {
|
||||
'___data___': output[0],
|
||||
'___code___': output[1],
|
||||
'___headers___': output[2],
|
||||
}
|
||||
else:
|
||||
# Normalize tuples to lists before serialization
|
||||
output = list(output)
|
||||
if isinstance(output, (dict, list)):
|
||||
output = json.dumps(output)
|
||||
|
||||
|
|
Loading…
Reference in a new issue