Python Flask CORS - 请求的资源上不存在 'Access-Control-Allow-Origin' header

Python Flask CORS - No 'Access-Control-Allow-Origin' header is present on the requested resource

我在 Shopify 产品页面上编写了一个简单的 Ajax 脚本。每当单击上传按钮时,都会触发此脚本并向 API 服务器发送 json 消息

 jQuery.ajax({
            url: "https://e20e2287e2cb.ngrok.io/return_json",
            type: "POST",
            data: form_data,
            processData: false,
            contentType: false,
            contentType: "application/json",
            success: function (result) {
              var obj = jQuery.parseJSON( result );
                jQuery(".select-loader").remove(); 
                jQuery("body").removeClass('active-loader');
                jQuery("#upload_image").removeClass("err");
                jQuery("#upload_image").val("");
                jQuery("#google_folder_id").val(obj.imguniquename);
                jQuery("#customImage").val(obj.imgname);
                jQuery("#customImageUrl").val(obj.folder_id);
                jQuery("#customUniqueImage").val(obj.imguniquename);
                
                jQuery("#upload_image").after('<p class="note note--success">Image uploaded successfully.</p>');
                Cookies.set('google_folder_id', obj.imguniquename);
                Cookies.set('customImage', obj.imgname);
                Cookies.set('customImageUrl', obj.folder_id);
                Cookies.set('customUniqueImage', obj.imguniquename);

            }
          });

在API服务器中,我在Python中写了如下代码:

#Flask Library
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin
from flask_ngrok import run_with_ngrok

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
logging.getLogger('flask_cors').level = logging.DEBUG
CORS(app)
run_with_ngrok(app) 

@app.route("/return_json", methods=["POST"])
def returnJson():
    return jsonify({'folder_id':'yoyo', 'img':'adad', 'imgname':'bibi', 'imguniquename':'kaka'})

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

谁能告诉我为什么每次触发 Ajax 脚本时浏览器控制台都会出现以下错误?

  1. 从源 'https://www.abcabc.com' 访问 'https://e20e2287e2cb.ngrok.io/return_json' 处的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' header。
  2. POST https://e20e2287e2cb.ngrok.io/return_json net::ERR_FAILED

同时,在 API 服务器端,调试日志对我来说看起来不错,如下所示:

DEBUG: flask_cors.extension:对“/return_json”的请求匹配 CORS 资源“/”。使用选项:{'origins': ['.'], 'methods': 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT', 'allow_headers': ['.'], 'expose_headers':None,'supports_credentials':错误,'max_age':None,'send_wildcard':错误,'automatic_options':正确,'vary_header':正确,'resources':'/','intercept_exceptions':正确,'always_send':正确}

DEBUG: flask_cors.core:CORS 请求收到 'Origin' https://www.abcabc.com

DEBUG: flask_cors.core: 请求的来源 header 匹配。发送 CORS headers.

DEBUG: flask_cors.core:设置CORS headers:MultiDict([('Access-Control-Allow-Origin', 'https://www.abcabc.com'), ( 'Vary', 'Origin')]) INFO:werkzeug:127.0.0.1 - - [23/Apr/2021 11:04:44] "POST /return_json HTTP/1.1" 200 -

由于我没有注意到您已经在使用 Flask-CORS 我正在通过进一步调查更新此答案。

我已经启动了一个测试环境,并设法在不更改代码的情况下使这个 cross-origin 请求正常工作。在此过程中,我为您的问题想出了以下可能的原因:

  1. 一定要请求一个现有的隧道端点。获取关闭的 NGROK 隧道端点会导致 CORS 错误,它不会引发 404。为了确保我正在请求正确的隧道,我写了一个索引视图路由,它只是 returns 成功。我还使用此端点确保为所有 HTTP 方法(GET、POST...)正确设置了 CORS;
  2. 请务必导入日志记录,Flask 可以延迟评估应用程序并仅在请求时引发异常。检查你的控制台是否有回溯;
  3. 在 Flask 中,如果在请求期间发生异常,请求处理流程将中止,并且永远不会调用 Flask-CORS 在响应 object 中添加它的 headers,并且你的浏览器总是会抱怨 'Access-Control-Allow-Origin'。这就是为什么您应该经常检查浏览器的 'Response Tab',它可能包含回溯或其他一些有用的信息;
  4. 访问 http://localhost:4040/ 查看 NGROK introspect 中的一些信息,它可能会帮助您跟踪许多问题;
  5. 我遇到了一些通过 pip 提供的 运行ning flask-ngrok 问题。我已经从 GitHub 下载了它的源代码并将其导入到我的演示应用程序中。坦率地说,我会放弃这个扩展,只在另一个控制台中使用 运行 $ ngrok http 5000
  6. 一定要设置 FLASK_DEBUG=true 否则它可能会对你隐藏一些 info/tracebacks。

查看此要点以获得我使用的源代码和一些证据:https://gist.github.com/magnunleno/8dad91f133a22322250d6cb609792597

如果您发现任何新信息或回溯,请告诉我,以便我们制定解决方案。

旧答案

当您 运行 您的服务器在特定域下(在您的情况下 e20e2287e2cb.ngrok.io)但您的网络客户端 运行 在不同的域中(假设 www.abcabc.com) and they try to communicate. You should really take a look at this.

可以通过管理您的应用程序来配置此行为 headers Access-Control-* 幸运的是,有一个名为 Flask-CORS.

的扩展程序可以为您完成此操作