experimental-accounting-api/accounting/decorators.py
Joar Wandborg 8abbe3462f [tests] Check transactions for errors before being added
- Added support for Exception-specific HTTP response codes for
  AccountinExceptions.
2013-12-26 21:48:45 +01:00

90 lines
2.5 KiB
Python

# Part of accounting-api project:
# https://gitorious.org/conservancy/accounting-api
# License: AGPLv3-or-later
from functools import wraps
from flask import jsonify, request
from accounting.exceptions import AccountingException
def jsonify_exceptions(func):
'''
Wraps a Flask endpoint and catches any AccountingException-based
exceptions which are returned to the client as JSON.
'''
@wraps(func)
def wrapper(*args, **kw):
try:
return func(*args, **kw)
except AccountingException as exc:
response = jsonify(error=exc)
response.status_code = exc.http_code
return response
return wrapper
def cors(origin_callback=None):
'''
Flask endpoint decorator.
Example:
.. code-block:: python
@app.route('/cors-endpoint', methods=['GET', 'OPTIONS'])
@cors()
def cors_endpoint():
return jsonify(message='This is accessible via a cross-origin XHR')
# Or if you want to control the domains this resource can be requested
# from via CORS:
domains = ['http://wandborg.se', 'http://sfconservancy.org']
def restrict_domains(origin):
return ' '.join(domains)
@app.route('/restricted-cors-endpoint')
@cors(restrict_domains)
def restricted_cors_endpoint():
return jsonify(
message='This is accessible from %s' % ', '.join(domains))
:param function origin_callback: A callback that takes one str() argument
containing the ``Origin`` HTTP header from the :data:`request` object.
This can be used to filter out which domains the resource can be
requested via CORS from.
'''
if origin_callback is None:
origin_callback = allow_all_origins
def decorator(func):
@wraps(func)
def wrapper(*args, **kw):
response = func(*args, **kw)
cors_headers = {
'Access-Control-Allow-Origin':
origin_callback(request.headers.get('Origin')) or '*',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': 3600,
'Access-Control-Allow-Methods': 'POST, GET, DELETE',
'Access-Control-Allow-Headers':
'Accept, Content-Type, Connection, Cookie'
}
for key, val in cors_headers.items():
response.headers[key] = val
return response
return wrapper
return decorator
def allow_all_origins(origin):
return origin