Reputation: 21312
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
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
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