플라스크에서 CORS를 활성화하는 방법
jquery를 사용하여 cross origin 요청을 하려고 하는데 계속 거부됩니다.
XMLHttpRequest는 http://...를 로드할 수 없습니다.요청한 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다.따라서 오리진 ...에 액세스할 수 없습니다.
플라스크, 헤로쿠, 그리고 재쿼리를 사용하고 있습니다.
클라이언트 코드는 다음과 같습니다.
$(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()
헤로쿠에 배치했을 때 효과가 있었습니다.
http://flask-cors..org/en/latest/http://flask-cors.readthedocs.org/en/latest/
플라스크 코어는 다음을 수행하여 설치합니다.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!"
저는 방금 같은 문제에 직면했고 다른 답들이 필요 이상으로 복잡하다고 믿게 되었습니다. 그래서 더 많은 도서관이나 장식가에 의존하고 싶지 않은 사람들을 위한 저의 접근법은 다음과 같습니다.
CORS 요청은 실제로 두 개의 HTTP 요청으로 구성됩니다.사전 비행 요청 후 사전 비행이 성공적으로 통과한 경우에만 수행되는 실제 요청입니다.
비행 전 요청 사항
도메인 POST
에서 "", ""라는 메시지가 됩니다.OPTIONS
아무도 하지 않고 에 이 간 간 공격의 .이 응답은 본문을 반환하지 않고 일부 헤더만 브라우저에 이 도메인 간 요청을 수행해도 괜찮으며 일부 사이트 간 스크립팅 공격의 일부가 아님을 알려줍니다.
저는 이 응답을 만들기 위해 파이썬 함수를 작성했습니다.make_response
의 flask
모듈.
def _build_cors_preflight_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_preflight_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_preflight_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
좋아요, 저는 갈루슈카크가 언급한 공식적인 스니펫이 모든 곳에서 사용되어야 한다고 생각하지 않습니다. 우리는 다음과 같은 처리 중에 일부 버그가 발생할 수도 있다는 것을 우려해야 합니다.hello_world
기능. 에 반응정또부지여관한이계없부에확정는지확한이,,Access-Control-Allow-Origin
헤더는 우리가 걱정해야 할 것입니다.아래의 토막글처럼 매우 간단합니다.
# define your bluprint
from flask import Blueprint
blueprint = Blueprint('blueprint', __name__)
# put this sippet ahead of all your bluprints
# blueprint can also be app~~
@blueprint.after_request
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
# Other headers can be added here if needed
return response
# write your own blueprints with business logics
@blueprint.route('/test', methods=['GET'])
def test():
return "test success"
이상입니다.
모든 경로에 대해 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 오류 관련 메시지가 표시됩니다.
저는 플라스크와 이 라이브러리를 사용하여 파이썬에서 동일한 문제를 해결했습니다.flask_flash in file in in in in in it.py:
#pip install flask_cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
cors = CORS(app, resource={
r"/*":{
"origins":"*"
}
})
그리고 그것이 전부입니다.
참조: https://flask-cors.readthedocs.io/en/latest/
여기에 설명된 솔루션 개선: 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
위의 모든 응답은 정상적으로 작동하지만, 예를 들어 입력 유효성 검사를 제대로 수행하지 않는 경우, 응용 프로그램에서 처리하지 않는 오류(예: 키 오류)가 발생하면 여전히 CORS 오류가 발생할 수 있습니다.오류 처리기를 추가하여 모든 예외 인스턴스를 검색하고 서버 응답에 CORS 응답 헤더를 추가할 수 있습니다.
따라서 오류 처리기 - 오류를 정의합니다.py:
from flask import json, make_response, jsonify
from werkzeug.exceptions import HTTPException
# define an error handling function
def init_handler(app):
# catch every type of exception
@app.errorhandler(Exception)
def handle_exception(e):
#loggit()!
# return json response of error
if isinstance(e, HTTPException):
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": e.code,
"name": e.name,
"description": e.description,
})
else:
# build response
response = make_response(jsonify({"message": 'Something went wrong'}), 500)
# add the CORS header
response.headers['Access-Control-Allow-Origin'] = '*'
response.content_type = "application/json"
return response
그리고 빌랄의 대답을 사용합니다.
from flask import Flask
from flask_cors import CORS
# import error handling file from where you have defined it
from . import errors
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
errors.init_handler(app) # initialise error handling
먼설해야합을 설치해야 .flask-cors
이 작업은 다음과 같이 수행할 수 있습니다.
pip install flask-cors
설치가 완료되면 Flask 앱에서 다음과 같이 사용할 수 있습니다.
- 모든 경로에 대해 CORS를 활성화해야 하는 경우:
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
- 을
CORS
경로에 를 특정경에로대리매개변수에있수다니습전할달를소로 할 수 .CORS
기능. 를 들면를들면예.
CORS(app, resources={r"/api/*": {"origins": "*"}})
예에서는 이 하여 이예서이다활성합니다화을음코는드를 활성화합니다.CORS
로 시경대해만서로 /api/
모든 출처의 요청을 허용합니다.필요에 따라 리소스 매개 변수를 사용자 정의할 수 있습니다.
자세한 내용은 설명서를 참조하십시오.
다음 장식기를 사용해 보십시오.
@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
플라스크-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():
...
문제를 찾을 수 없고 코드가 작동해야 하는 경우, herku에서 요청할 수 있는 최대 시간에 도달한 것일 수 있습니다.Heroku는 30초 이상이 걸리면 요청을 취소합니다.
참조: https://devcenter.heroku.com/articles/request-timeout
언급URL : https://stackoverflow.com/questions/25594893/how-to-enable-cors-in-flask
'programing' 카테고리의 다른 글
Git 및 WordPress(+ 플러그인 및 미디어 관리) (0) | 2023.06.16 |
---|---|
SQL PLUS Oracle 11gr1에서 데이터베이스 명령 사용 (0) | 2023.06.16 |
MariaDB/MySQL : SQLite3에서 Attach DATABASE와 유사한 명령이 있습니까? (0) | 2023.06.16 |
ggplot2의 두 열로 그룹화 (0) | 2023.06.16 |
vb.net 의 사전에서 어떻게 반복할 수 있습니까? (0) | 2023.06.16 |