CodeLikeBeaker
CodeLikeBeaker

Reputation: 21312

Cross-Origin Resource Sharing Multiple Sites

I have the following site which contains css/js/images/etc:

global.mysite.com

The __init__.py of the site has the following:

from flask import Flask
from flask.ext.cors import CORS

app = Flask('web')
CORS(app)

I am able to load the resources from another site (we will call it siteA) no problem. Until I attempt to use a 2nd site (siteB) on the same machine, I get the following error:

Font from origin 'http://global.mysite.com' has been blocked from loading by Cross-Origin Resource Sharing policy: The 'Access-Control-Allow-Origin' header has a value 'http://siteA.mysite.com' that is not equal to the supplied origin. Origin 'http://siteB.mysite.com' is therefore not allowed access.

Is there something I need to configure in the CORS aspect of the site, or perhaps a parameter in the __init__.py that I need to add in order allow multiple sites?

This also might look like some sort of caching issue. If so, any thoughts to resolve this?

If you need more info, please feel free to comment.

Upvotes: 3

Views: 481

Answers (2)

CESCO
CESCO

Reputation: 7758

I have never used CORS extension, but it looks weird since you need to run the app with it. Making impossible to used other extension like Flask-SocketIO

This decorator works on any route and it does not require any extra extension.

from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper


def crossdomain(origin=None, methods=None, headers=None,
                max_age=21600, attach_to_all=True,
                automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, basestring):
        origin = ', '.join(origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        if methods is not None:
            return methods

        options_resp = current_app.make_default_options_response()
        return options_resp.headers['allow']

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            if automatic_options and request.method == 'OPTIONS':
                resp = current_app.make_default_options_response()
            else:
                resp = make_response(f(*args, **kwargs))
            if not attach_to_all and request.method != 'OPTIONS':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = str(max_age)
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return update_wrapper(wrapped_function, f)
    return decorator

And use it

@app.route('/my_service')
@crossdomain(origin='*')
def my_service():
    return jsonify(foo='cross domain ftw')

Upvotes: 1

Ketouem
Ketouem

Reputation: 3857

You need to specify the origin when you instantiate the CORS class.

cors = CORS(app, resources={r"/fonts/*": {"origins": "*"}})

In this example I've put a wildcard which can is overkill in most cases and not very "securitish". So feel free to adapt with your own domain ;-)

More info about resource specific CORS

Upvotes: 0

Related Questions