You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask桥接前后端传递经纬度时遭遇CORS跨域错误求助

Flask前后端数据传递遭遇CORS错误排查与解决

我用Flask做前后端桥接,将前端获取的纬度(latitude)、经度(longitude)传递至Python脚本,但提交数据时始终遇到以下CORS错误:

Access to XMLHttpRequest at 'http://localhost:5000/weather-producer.py' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. script.js:15 POST http://localhost:5000/weather-producer.py net::ERR_FAILED 403 (Forbidden)

Python代码

from flask import Flask, request
import logging
from os.path import dirname, abspath
from time import gmtime
import http.client
from flask_cors import CORS

from confluent_kafka import Producer

logger = logging.getLogger('')  # Root logger, to catch all submodule logs
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s.%(msecs)03d|%(levelname)s|%(filename)s| %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
formatter.converter = gmtime  # Log UTC time

if len(logger.handlers) == 0:
    console = logging.StreamHandler()
    console.setFormatter(formatter)
    logger.addHandler(console)


def _full_path_of(path):
    base_dir = dirname(dirname(dirname(abspath(__file__))))
    return f'{base_dir}{path}'


def delivery_callback(error, msg) -> None:
    """
    Per-message delivery callback (triggered by poll() or flush())

    :param error: None if the message was successfully delivered
    :param msg: Message metadata
    :return: None
    """
    if error is not None:
        logger.error(f'Failed to deliver message: {error}')
    else:
        logger.info(f'Produced record to topic {msg.topic()} partition [{msg.partition()}] @ offset {msg.offset()}')


def get_weather_data(latitude, longitude):
    conn = http.client.HTTPSConnection("weatherapi-com.p.rapidapi.com")

    headers = {
        'X-RapidAPI-Key': "randomAPIkey",
        'X-RapidAPI-Host': "weatherapi-com.p.rapidapi.com"
    }

    query = f"/current.json?q={latitude},{longitude}"
    conn.request("GET", query, headers=headers)

    res = conn.getresponse()
    data = res.read()

    return data.decode("utf-8")


app = Flask(__name__)
CORS(app, resources={r"/weather-producer.py": {"origins": "*"}})

@app.route("/weather-producer.py", methods=['POST'])
def weather_producer():
    latitude = request.form.get('textbox1')
    longitude = request.form.get('textbox2')

    topic = 'axual-local-example-weathertopic'

    configuration = {
        'bootstrap.servers': 'platform.local:31757',
        'security.protocol': 'SSL',
        'ssl.endpoint.identification.algorithm': 'none',
        'ssl.certificate.location': _full_path_of('/resources/client-cert/standalone/client.pem'),
        'ssl.key.location': _full_path_of('/resources/client-cert/standalone/clientkey.pem'),
        'ssl.ca.location': _full_path_of('/resources/client-cert/standalone/client.pem'),
        'acks': 'all',
        'logger': logger
    }

    producer = Producer(configuration)

    try:
        logger.info(f'Starting kafka producer to produce to topic: {topic}. ^C to exit.')
        for n in range(10):
            record_key = f'key_{n}'
            record_value = get_weather_data(latitude, longitude)

            producer.poll(0)
            producer.produce(topic, key=record_key, value=record_value, on_delivery=delivery_callback)

        logger.info('Done producing.')
    except KeyboardInterrupt:
        logger.info('Caught KeyboardInterrupt, stopping.')
    finally:
        if producer is not None:
            logger.info('Flushing producer.')
            producer.flush()

    return 'Success', 200


if __name__ == "__main__":
    app.run(port=5000, debug=True)

JavaScript代码

function submitForm(event) {
    event.preventDefault(); // Prevent form submission
  
    var textbox1Value = document.getElementById("textbox1").value;
    var textbox2Value = document.getElementById("textbox2").value;
  
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST", "http://localhost:5000/weather-producer.py", true);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText);
      }
    };
    xhttp.send("textbox1=" + textbox1Value + "&textbox2=" + textbox2Value);
  }

问题排查与修复步骤

  • 修正CORS路径匹配或改为全局允许:当前配置的resources={r"/weather-producer.py": {"origins": "*"}}可能存在路径匹配偏差,建议先改为全局允许进行测试(生产环境需限制指定origin):
    # 替换原CORS配置为全局允许
    CORS(app)
    
    若需精确匹配,确保路由路径与配置完全一致,可保留原配置但确认Flask路由无额外重写规则。
  • 处理origin为null的场景:前端直接打开本地HTML文件时,请求origin会是null,部分CORS配置对该origin支持不佳。解决方式二选一:
    • 将前端页面部署到HTTP服务器(如执行python -m http.server 8000,访问http://localhost:8000/xxx.html),让请求拥有正常origin;
    • 修改CORS配置显式允许null origin:
      CORS(app, resources={r"/weather-producer.py": {"origins": ["*", "null"]}})
      
  • 确认Flask-CORS加载顺序与版本:确保CORS(app)在app = Flask(__name__)之后、路由定义之前调用,同时确认已安装最新版flask-cors(执行pip install --upgrade flask-cors)。
  • 覆盖OPTIONS预检查请求:CORS预检查会发送OPTIONS请求,需确保配置覆盖该方法:
    CORS(app, resources={r"/weather-producer.py": {
        "origins": "*",
        "methods": ["POST", "OPTIONS"]
    }})
    

内容的提问来源于stack exchange,提问作者Gion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:50:57