Improve API errors
TODO
-
Handle APIError
exception -
Update diagnostics plugin -
Update OpenVPN plugin -
Update plugins template
Action points
- API endpoints are not redirected the same way as others (default page)
- Return JSON for API endpoints
When an error occurs, API should return a JSON with error description. Right now 404 or 500 errors have response in HTML format. This is OK for views that should render HTML, but not all are like that.
This uncovers a wider issue - the Flask application is a mix of API endpoints and "HTML" endpoints. Maybe we should separate them somehow.
Another issue is that requesting a non-existeng page, e.g. reforis/diagnostics/api/reportsz/2019-09-18_98a1b102
(should be reports
) results in 200 OK response with HTML page of notifications instead of 404 (which would make sense for API endpoints).
An example from OpenVPN plugin (excerpt from HTML response, Internal Server Error):
Traceback (most recent call last): File "/message_router.py", line 91, in process_message File "/message_router.py", line 40, in wrapper File "/message_router.py", line 76, in validate File "/validator.py", line 257, in validate File "/validators.py", line 348, in validate jsonschema.exceptions.ValidationError: {'device': 'tun_turris', 'enabled': True, 'ipv6': False, 'network': '10.111.111.0', 'network_netmask': '255.255.255.0', 'port': 1194, 'protocol': 'udp', 'route_all': True, 'routes': [{'netmask': '255.255.255.0', 'network': '192.168.1.0'}], 'server_hostname': '', 'use_dns': True} is not valid under any of the given schemas Failed validating 'oneOf' in schema['properties']['data']: {'oneOf': [{'additionalProperties': False, 'properties': {'enabled': {'enum': [True]}, 'ipv6': {'type': 'boolean'}, 'network': {'format': 'ipv4', 'type': 'string'}, 'network_netmask': {'format': 'ipv4', 'type': 'string'}, 'protocol': {'enum': ['udp', 'tcp']}, 'route_all': {'type': 'boolean'}, 'use_dns': {'type': 'boolean'}}, 'required': ['enabled', 'network', 'network_netmask', 'route_all', 'use_dns', 'protocol', 'ipv6'], 'type': 'object'}, {'additionalProperties': False, 'properties': {'enabled': {'enum': [False]}}, 'required': ['enabled'], 'type': 'object'}]} On instance['data']: {'device': 'tun_turris', 'enabled': True, 'ipv6': False, 'network': '10.111.111.0', 'network_netmask': '255.255.255.0', 'port': 1194, 'protocol': 'udp', 'route_all': True, 'routes': [{'netmask': '255.255.255.0', 'network': '192.168.1.0'}], 'server_hostname': '', 'use_dns': True}
Instead of this, the API could return a JSON (Bad Request) describing which fields are wrong, e.g.
{
"route_all": "Value should be boolean"
}
which will allow the API consumer to use this information to provide feedback for the user, and eventually display the errors in a for (just an example).