如何在 Flask 中启用 CORS

2025-01-13 08:53:00
admin
原创
132
摘要:问题描述:我正在尝试使用 jquery 发出跨源请求,但它一直被拒绝并显示以下消息XMLHttpRequest 无法加载 http://... 请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 Origin ...。我正在使用 flask、heroku 和 jq...

问题描述:

我正在尝试使用 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);
            }
        });
    }); 
});

在 heroku 方面我使用 flask,它是这样的

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+"

"+description
    )

    return '200 OK'

if __name__ == '__main__':
    app.run()

解决方案 1:

这是我部署到 Heroku 时起作用的东西。

http://flask-cors.readthedocs.org/en/latest/

通过运行安装 flask-cors -
pip install -U flask-cors

/!\ 警告:允许所有来源可能会带来安全风险。建议仅针对指定的域或路由允许 CORS ,列出以下内容:

CORS(api, resources={r"/api/*": {"origins": "http://localhost:3000"}})
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app) # allow CORS for all domains on all routes.
app.config['CORS_HEADERS'] = 'Content-Type'

@app.route("/")
@cross_origin()
def helloWorld():
  return "Hello, cross-origin-world!"

解决方案 2:

我刚刚遇到同样的问题,我开始相信其他的答案比它们需要的要复杂一些,所以对于那些不想依赖更多库或装饰器的人来说,这是我的方法:

CORS 请求实际上由两个 HTTP 请求组成。一个是预检请求,另一个是只有预检成功通过后才会发出的实际请求。

飞行前请求

在实际跨域POST请求之前,浏览器将发出一个OPTIONS请求。此响应不应返回任何正文,而应返回一些令人放心的标头,告诉浏览器可以执行此跨域请求,并且这不是某些跨站点脚本攻击的一部分。

make_response我编写了一个 Python 函数来使用模块中的函数构建此响应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

解决方案 3:

OK,我认为 galuszkak 提到的官方代码片段不应该到处都用,我们应该关注处理程序(例如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"

就这样啦~~

解决方案 4:

如果您想为所有路由启用 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 无关。

解决方案 5:

我使用 flask 和这个库在 python 中解决了同样的问题。

文件 init.py 中flask_cors

#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/

解决方案 6:

您首先需要安装flask-cors。您可以按如下方式进行操作:

pip install flask-cors

安装完成后,您可以在 Flask 应用程序中使用它,如下所示:

  1. 如果需要为所有路由启用 CORS:

from flask_cors import CORS

app = Flask(__name__)
CORS(app)
  1. 如果只想CORS为特定路由启用,可以将 resources 参数传递给该CORS函数。例如,

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

在此示例中,此代码将CORS仅启用以 开头的路由/api/,并允许来自任何来源的请求。您可以自定义资源参数以满足您的需求。

欲了解更多信息,请阅读文档

解决方案 7:

改进此处描述的解决方案: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

解决方案 8:

上述所有响应都正常工作,但如果应用程序抛出您未处理的错误(例如,如果您未正确进行输入验证,则会出现键错误),您仍可能会收到 CORS 错误。您可以添加错误处理程序来捕获所有异常实例,并在服务器响应中添加 CORS 响应标头

因此定义一个错误处理程序——errors.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

然后使用Billal 的答案:

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 

解决方案 9:

尝试以下装饰器:

@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+"

"+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

解决方案 10:

要仅为特定来源启用 CORS,请使用 flask-cors:

cors = CORS(app, origins=['http://localhost:3000', 'https://example.com'])

有关更多信息,请参阅官方文档:https ://flask-cors.corydolphin.com/en/latest/api.html#extension

解决方案 11:

我的解决方案是围绕 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():
    ...

解决方案 12:

如果您找不到问题,并且代码应该可以工作,那么可能是您的请求刚好达到 Heroku 允许您发出请求的最大时间。如果请求时间超过 30 秒,Heroku 会取消请求。

参考:https ://devcenter.heroku.com/articles/request-timeout

解决方案 13:

CORS 错误大多是因为浏览器屏蔽了某些未知请求。可以使用以下步骤解决。如果您尚未安装 Flask-CORS 包,可以使用 pip 安装。

pip install Flask-CORS

在 Flask 应用程序中启用 CORS:

您可以为整个 Flask 应用程序或特定路由启用 CORS。

对于整个应用程序:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route('/')
def index():
    return "CORS is enabled!"

对于特定路线:

from flask import Flask
from flask_cors import CORS, cross_origin

app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "*"}})

@app.route('/api/data')
@cross_origin()
def data():
    return {"key": "value"}

解决方案 14:

安装 Flask-CORS:不需要安装 Flask-CORS,可以通过 pip 安装:

pip install flask-cors

在 app.py 中配置 CORS: 没有 app.py,可以通过以下方式配置 CORS 允许待办事项的操作系统标头:

cors = CORS(app, resources={r"/*": {"origins": "*", "allow_headers": ["Content-Type", "Token"]}})
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2379  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1510  
  PLM(产品生命周期管理)系统在企业项目管理中扮演着至关重要的角色,它能够整合产品从概念设计到退役的全流程信息,提升协同效率,降低成本。然而,项目范围蔓延是项目管理过程中常见且棘手的问题,在PLM系统环境下也不例外。范围蔓延可能导致项目进度延迟、成本超支、质量下降等一系列不良后果,严重影响项目的成功交付。因此,如何在P...
plm项目经理是做什么   16  
  PLM(产品生命周期管理)系统在现代企业的产品研发与管理过程中扮演着至关重要的角色。它不仅仅是一个管理产品数据的工具,更能在利益相关者分析以及沟通矩阵设计方面提供强大的支持。通过合理运用PLM系统,企业能够更好地识别、理解和管理与产品相关的各类利益相关者,构建高效的沟通机制,从而提升产品开发的效率与质量,增强企业的市场...
plm是什么   20  
  PLM(产品生命周期管理)项目管理对于企业产品的全生命周期规划、执行与监控至关重要。在项目推进过程中,监控进度偏差是确保项目按时、按质量完成的关键环节。五维健康检查指标体系为有效监控PLM项目进度偏差提供了全面且系统的方法,涵盖了项目的多个关键维度,有助于及时发现问题并采取针对性措施。需求维度:精准把握项目基石需求维度...
plm项目管理软件   18  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用