jquery를 사용하여 원본 간 요청을 시도하고 있지만 메시지와 함께 계속 거부됩니다.
XMLHttpRequest에서 http : //를로드 할 수 없습니다 … 요청 된 리소스에 ‘Access-Control-Allow-Origin’헤더가 없습니다. 따라서 Origin … 액세스가 허용되지 않습니다.
나는 flask, heroku 및 jquery를 사용하고 있습니다.
클라이언트 코드는 다음과 같습니다.
$(document).ready(function() {
$('#submit_contact').click(function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://...',
// data: [
// { name: "name", value: $('name').val()},
// { name: "email", value: $('email').val() },
// { name: "phone", value: $('phone').val()},
// { name: "description", value: $('desc').val()}
//
// ],
data:"name=3&email=3&phone=3&description=3",
crossDomain:true,
success: function(msg) {
alert(msg);
}
});
});
});
헤 로쿠 쪽은 플라스크를 사용하고 있는데 이렇게
from flask import Flask,request
from flask.ext.mandrill import Mandrill
try:
from flask.ext.cors import CORS # The typical way to import flask-cors
except ImportError:
# Path hack allows examples to be run without installation.
import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0, parentdir)
from flask.ext.cors import CORS
app = Flask(__name__)
app.config['MANDRILL_API_KEY'] = '...'
app.config['MANDRILL_DEFAULT_FROM']= '...'
app.config['QOLD_SUPPORT_EMAIL']='...'
app.config['CORS_HEADERS'] = 'Content-Type'
mandrill = Mandrill(app)
cors = CORS(app)
@app.route('/email/',methods=['POST'])
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __name__ == '__main__':
app.run()
답변
Heroku에 배포했을 때 효과가 있었던 것은 다음과 같습니다.
http://flask-cors.readthedocs.org/en/latest/
다음을 실행하여 flask-cors를 설치합니다.
pip install -U flask-cors
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
@app.route("/")
@cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
답변
좋아요, galuszkak에서 언급 한 공식 스 니펫이 모든 곳에서 사용되어야한다고 생각하지 않습니다 hello_world
. 함수 와 같은 핸들러 중에 일부 버그가 트리거 될 수있는 경우를 고려해야합니다 . 응답이 정확하든 부정확하든 Access-Control-Allow-Origin
헤더는 우리가 관심을 가져야 할 것입니다. 따라서 다음과 같이 매우 간단합니다.
@blueprint.after_request # blueprint can also be app~~
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
return response
그게 다야 ~~
답변
나는 방금 같은 문제에 직면했고 다른 답변이 필요한 것보다 조금 더 복잡하다고 믿게되었으므로 더 많은 라이브러리 나 데코레이터에 의존하고 싶지 않은 사람들을위한 나의 접근 방식은 다음과 같습니다.
CORS 요청은 실제로 두 개의 HTTP 요청으로 구성됩니다. 프리 플라이트 요청과 프리 플라이트가 성공적으로 통과 한 경우에만 수행되는 실제 요청입니다.
프리 플라이트 요청
실제 교차 도메인 POST
요청 전에 브라우저가 OPTIONS
요청 을 발행합니다 . 이 응답은 본문을 반환해서는 안되지만 브라우저에이 교차 도메인 요청을 수행해도 괜찮으며 일부 교차 사이트 스크립팅 공격의 일부가 아니라는 것을 알리는 일부 안심 헤더 만 반환해야합니다.
모듈 의 make_response
함수를 사용하여이 응답을 빌드하는 Python 함수를 작성했습니다 flask
.
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add("Access-Control-Allow-Methods", "*")
return response
이 응답은 모든 요청에 대해 작동하는 와일드 카드 응답입니다. CORS에서 추가 보안을 확보하려면 출처, 헤더 및 메소드의 화이트리스트를 제공해야합니다.
이 응답은 (Chrome) 브라우저가 계속해서 실제 요청을 수행하도록 설득합니다.
실제 요청
실제 요청을 처리 할 때 하나의 CORS 헤더를 추가해야합니다. 그렇지 않으면 브라우저가 호출하는 JavaScript 코드에 대한 응답을 반환하지 않습니다. 대신 클라이언트 측에서 요청이 실패합니다. jsonify를 사용한 예
response = jsonify({"order_id": 123, "status": "shipped"}
response.headers.add("Access-Control-Allow-Origin", "*")
return response
나는 또한 그것을위한 함수를 썼다.
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
한 줄로 되돌릴 수 있습니다.
최종 코드
from flask import Flask, request, jsonify, make_response
from models import OrderModel
flask_app = Flask(__name__)
@flask_app.route("/api/orders", methods=["POST", "OPTIONS"])
def api_create_order():
if request.method == "OPTIONS": # CORS preflight
return _build_cors_prelight_response()
elif request.method == "POST": # The actual request following the preflight
order = OrderModel.create(...) # Whatever.
return _corsify_actual_response(jsonify(order.to_dict()))
else
raise RuntimeError("Weird - don't know how to handle method {}".format(request.method))
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
답변
모든 경로에 대해 CORS를 활성화하려면 flask_cors 확장 ( pip3 install -U flask_cors
)을 설치하고 다음 과 app
같이 래핑 CORS(app)
합니다..
그것으로 충분합니다 ( POST
이미지 업로드 요청으로 이것을 테스트 했으며 저에게 효과적이었습니다).
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
중요 사항 : 경로에 오류가있는 경우 존재하지 않는 변수를 인쇄하려고하면 실제로 CORS와 관련이없는 CORS 오류 관련 메시지가 표시됩니다.
답변
다음 데코레이터를 사용해보세요.
@app.route('/email/',methods=['POST', 'OPTIONS']) #Added 'Options'
@crossdomain(origin='*') #Added
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __name__ == '__main__':
app.run()
이 데코레이터는 다음과 같이 생성됩니다.
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
이 패키지 Flask-CORS를 확인할 수도 있습니다.
답변
내 솔루션은 app.route를 둘러싼 래퍼입니다.
def corsapp_route(path, origin=('127.0.0.1',), **options):
"""
Flask app alias with cors
:return:
"""
def inner(func):
def wrapper(*args, **kwargs):
if request.method == 'OPTIONS':
response = make_response()
response.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
response.headers.add('Access-Control-Allow-Headers', ', '.join(origin))
response.headers.add('Access-Control-Allow-Methods', ', '.join(origin))
return response
else:
result = func(*args, **kwargs)
if 'Access-Control-Allow-Origin' not in result.headers:
result.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
return result
wrapper.__name__ = func.__name__
if 'methods' in options:
if 'OPTIONS' in options['methods']:
return app.route(path, **options)(wrapper)
else:
options['methods'].append('OPTIONS')
return app.route(path, **options)(wrapper)
return wrapper
return inner
@corsapp_route('/', methods=['POST'], origin=['*'])
def hello_world():
...
답변
여기에 설명 된 솔루션 개선 : https://stackoverflow.com/a/52875875/10299604
이를 통해 after_request
CORS 응답 헤더를 처리하여 엔드 포인트에 추가 코드를 추가하지 않아도됩니다.
### CORS section
@app.after_request
def after_request_func(response):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
response = make_response()
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'x-csrf-token')
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
else:
response.headers.add('Access-Control-Allow-Credentials', 'true')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
return response
### end CORS section