Changeset - 2eecd641dda8
[Not reviewed]
0 2 0
Joar Wandborg - 10 years ago 2013-12-20 13:51:32
joar@wandborg.se
Added CORS Flask endpoint decorator
2 files changed with 99 insertions and 6 deletions:
0 comments (0 inline, 0 general)
accounting/decorators.py
Show inline comments
...
 
@@ -5,5 +5,5 @@
 
from functools import wraps
 

	
 
from flask import jsonify
 
from flask import jsonify, request
 

	
 
from accounting.exceptions import AccountingException
...
 
@@ -23,2 +23,64 @@ def jsonify_exceptions(func):
 

	
 
    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
accounting/web.py
Show inline comments
...
 
@@ -11,8 +11,9 @@ import logging
 
import argparse
 

	
 
from flask import Flask, jsonify, request
 
from flask import Flask, jsonify, request, render_template
 
from flask.ext.script import Manager
 
from flask.ext.migrate import Migrate, MigrateCommand
 

	
 
from accounting.models import Transaction
 
from accounting.storage import Storage
 
from accounting.storage.ledgercli import Ledger
...
 
@@ -20,5 +21,5 @@ from accounting.storage.sql import SQLStorage
 
from accounting.transport import AccountingEncoder, AccountingDecoder
 
from accounting.exceptions import AccountingException
 
from accounting.decorators import jsonify_exceptions
 
from accounting.decorators import jsonify_exceptions, cors
 

	
 

	
...
 
@@ -57,14 +58,39 @@ def index():
 
    return 'Hello World!'
 

	
 
@app.route('/client')
 
def client():
 
    return render_template('client.html')
 

	
 

	
 
@app.route('/transaction', methods=['OPTIONS'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_options():
 
    return jsonify(status='OPTIONS')
 

	
 

	
 
@app.route('/transaction/<string:transaction_id>', methods=['OPTIONS'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_by_id_options(transaction_id=None):
 
    return jsonify(status='OPTIONS')
 

	
 

	
 
@app.route('/transaction', methods=['GET'])
 
def transaction_get():
 
@app.route('/transaction/<string:transaction_id>', methods=['GET'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_get(transaction_id=None):
 
    '''
 
    Returns the JSON-serialized output of :meth:`accounting.Ledger.reg`
 
    '''
 
    return jsonify(transactions=storage.get_transactions())
 
    if transaction_id is None:
 
        return jsonify(transactions=storage.get_transactions())
 

	
 
    return jsonify(transaction=storage.get_transaction(transaction_id))
 

	
 

	
 
@app.route('/transaction/<string:transaction_id>', methods=['POST'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_update(transaction_id=None):
...
 
@@ -86,4 +112,5 @@ def transaction_update(transaction_id=None):
 

	
 
@app.route('/transaction/<string:transaction_id>', methods=['DELETE'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_delete(transaction_id=None):
...
 
@@ -97,4 +124,5 @@ def transaction_delete(transaction_id=None):
 

	
 
@app.route('/transaction', methods=['POST'])
 
@cors()
 
@jsonify_exceptions
 
def transaction_post():
...
 
@@ -146,5 +174,8 @@ def transaction_post():
 
          Assets:Checking                                              $ 100
 
    '''
 
    transactions = request.json.get('transactions')
 
    if not isinstance(request.json, Transaction):
 
        transactions = request.json.get('transactions')
 
    else:
 
        transactions = [request.json]
 

	
 
    if not transactions:
0 comments (0 inline, 0 general)