Javascript - заголовок No-Access-Control-Allow-Origin присутствует на запрошенном ресурсе
Мне нужно отправить данные через XmlHttpRequest с javascript на сервер python. Поскольку я использую localhost, мне нужно использовать CORS. Я использую флеш-фреймворк и его модуль flask_cors. Как javascript у меня есть это:
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("POST", "http://localhost:5000/signin", true);
var params = "email=" + email + "&password=" + password;
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText);
}
}
xmlhttp.send(params);
и код python:
@app.route('/signin', methods=['POST'])
@cross_origin()
def sign_in():
email = cgi.escape(request.values["email"])
password = cgi.escape(request.values["password"])
но когда я его выполню, я получу это сообщение:
XMLHttpRequest не может загрузить localhost: 5000/signin. нет Заголовок заголовка Access-Control-Allow-Origin присутствует в запрошенном ресурс. Поэтому исходный "null" не допускается.
Как я должен это исправить? Я знаю, что мне нужно использовать заголовок "Access-Control-Allow-Origin", но я не знаю, как его реализовать в этом коде. Кстати, мне нужно использовать чистый javascript. Спасибо вам
Ответы
Ответ 1
Я получил Javascript, работающий с Flask, используя этот декоратор и добавив "ОПЦИИ" в список моих приемлемых методов. Декоратор должен использоваться под вашим декоратором маршрута, например:
@app.route('/login', methods=['POST', 'OPTIONS'])
@crossdomain(origin='*')
def login()
...
Edit:
Ссылка кажется нарушенной. Здесь декоратор я использовал.
def crossdomain(origin=None, methods=None, headers=None, max_age=21600,
attach_to_all=True, automatic_options=True):
"""Decorator function that allows crossdomain requests.
Courtesy of
https://blog.skyred.fi/articles/better-crossdomain-snippet-for-flask.html
"""
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():
""" Determines which methods are allowed
"""
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
"""The decorator function
"""
def wrapped_function(*args, **kwargs):
"""Caries out the actual cross domain code
"""
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)
h['Access-Control-Allow-Credentials'] = 'true'
h['Access-Control-Allow-Headers'] = \
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
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
Ответ 2
Я использовал расширение flask-cors.
Установите с помощью pip install flask-cors
Тогда это просто
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
Это позволит всем доменам
Ответ 3
Старый вопрос, но для будущих гуглеров с этой проблемой я решил (и несколько других проблем с обратным ходом, связанным с CORS) для моего приложения, поддерживающего флягу, добавив следующее в файл app.py:
app = Flask(__name__)
api = Api(app)
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return response
if __name__ == '__main__':
app.run()
Ответ 4
На самом деле на сайте Flask есть яркий фрагмент, чтобы изменить заголовок сервера Access-Control-Allow-Origin
. http://flask.pocoo.org/snippets/56/
У вас есть легкий путь оттуда, который позволяет каждому домену *
получить доступ к вашему URL-адресу или указать ваш выбор URL-адресов внутри заголовка.
Из статьи MDN на CORS:
В этом случае сервер отвечает с помощью Access-Control-Allow-Origin: *
, что означает, что доступ к ресурсу может осуществляться любым доменом на межсайтовой основе. Если владельцы ресурсов в http://bar.other хотел ограничить доступ к ресурсу только с http://foo.example, они отправили бы обратно: Access-Control-Allow-Origin: http://foo.example
.
Ответ 5
При использовании python 2.7
app = Flask(__name__)
api = Api(app)
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return response
if __name__ == '__main__':
app.run()
При запуске на python3 или вперёд,
установите фляжки с помощью команды pip install flask-cors
Добавьте следующее:
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
Ответ 6
Я использовал решение от Zachary. Хорошо работает.
Для тех, кто задается вопросом, где разместить новый декоратор:
Просто скопируйте код из ссылки, предоставленной Захари, и поместите ее в файл .py
Поместите его в папку, в которой присутствуют ваши модули python (зависит от используемой вами системы и от того, используете ли вы виртуальную среду).
В своем флеш-приложении импортируйте метод crossdomain
из вновь созданного модуля python и используйте его.
Ответ 7
Допустимый доступ Access-Control-Allow-Origin должен быть отправлен сервером, а не вами. Когда вы совершаете вызов в другом домене, браузер проверяет, возвращается ли этот заголовок сервером. Если это не так, вызов завершится неудачно. Я не знаю Python, поэтому я не знаю, как заставить ваш сервер отправлять этот заголовок, или даже если вы вообще можете модифицировать сервер.