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
|
import json
|
||||||
|
|
||||||
from flask import Blueprint, abort, request
|
from flask import Blueprint, abort, request, make_response
|
||||||
from flask.wrappers import Response
|
|
||||||
|
|
||||||
from platypush.backend.http.app import template_folder
|
from platypush.backend.http.app import template_folder
|
||||||
from platypush.backend.http.app.utils import logger, send_message
|
from platypush.backend.http.app.utils import logger, send_message
|
||||||
|
@ -61,14 +60,31 @@ def hook_route(hook_name):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
send_message(event)
|
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 there are matching hooks, wait for their completion before returning
|
||||||
if matching_hooks:
|
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(
|
if isinstance(rs, dict) and '___data___' in rs:
|
||||||
json.dumps({'status': 'ok', **event_args}), mimetype='application/json'
|
# 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:
|
except Exception as e:
|
||||||
logger().exception(e)
|
logger().exception(e)
|
||||||
logger().error('Error while dispatching webhook event %s: %s', event, str(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):
|
def send_response(self, response):
|
||||||
output = response.output
|
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)):
|
if isinstance(output, (dict, list)):
|
||||||
output = json.dumps(output)
|
output = json.dumps(output)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue