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

React调用Python Pyramid API时出现CORS预请求错误

解决React调用Pyramid API的CORS预请求错误

问题背景

我有一个ReactJS构建的前端Web应用,调用Python Pyramid框架开发的API。本地测试时,前端部署在localhost:6543,Python应用部署在localhost:3000,调用API时出现CORS预请求错误。

前端请求代码

const onFinish = (values) => {
    fetch(`${baseUrl}login`, {
      method: "POST",
      mode: 'no-cors',
      headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": "http://localhost:3000",
      },
      body: JSON.stringify(values),
});

Pyramid后端CORS配置代码

from pyramid.config import Configurator
from invest_web.authentication.security import SecurityPolicy
from pyramid.response import Response
from pyramid.events import NewRequest
from invest_web.models.models import User, Issuer

def add_cors_headers_response_callback(event):
    def cors_headers(request, response):
        
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'POST,GET,DELETE,PUT,OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'access-control-allow-origin,content-type'
        response.headers['Access-Control-Allow-Credentials'] = 'true'        
    event.request.add_response_callback(cors_headers)

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    with Configurator(settings=settings) as config:
        config.include('pyramid_jinja2')

        config.set_security_policy(
            SecurityPolicy(
                secret=settings['invest_web.secret']
            ),
        )

        config.add_subscriber(add_cors_headers_response_callback, NewRequest)
        config.include('.routes')
        config.include('.models')
        config.scan()

    return config.make_wsgi_app()

错误截图

CORS预请求错误


问题分析及修复方案

1. 前端请求修正

  • 移除mode: 'no-cors':该模式会让请求变为不透明类型,浏览器会屏蔽所有响应信息,直接导致CORS逻辑失效。
  • 移除请求头中的Access-Control-Allow-Origin:这是服务器返回的响应头,前端无需设置。

修改后的前端代码:

const onFinish = (values) => {
    fetch(`${baseUrl}login`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(values),
    })
    .then(response => response.json())
    .catch(error => console.error('请求错误:', error));
};

2. 后端CORS配置完善

当前后端仅添加了响应头,但未正确处理OPTIONS预请求(浏览器发送非简单请求前会先触发该请求),需补充相关逻辑:

from pyramid.config import Configurator
from invest_web.authentication.security import SecurityPolicy
from pyramid.response import Response
from pyramid.events import NewRequest
from invest_web.models.models import User, Issuer

def add_cors_headers_response_callback(event):
    def cors_headers(request, response):
        # 动态匹配请求Origin,支持带凭证的CORS请求(*和凭证不能共存)
        origin = request.headers.get('Origin')
        response.headers['Access-Control-Allow-Origin'] = origin if origin else '*'
        
        response.headers['Access-Control-Allow-Methods'] = 'POST,GET,DELETE,PUT,OPTIONS'
        response.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # 设置预请求缓存时长,减少重复OPTIONS请求
        response.headers['Access-Control-Max-Age'] = '3600'
    
    event.request.add_response_callback(cors_headers)

def options_response(request):
    # 专门处理OPTIONS预请求,返回200状态码
    return Response(status=200)

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    with Configurator(settings=settings) as config:
        config.include('pyramid_jinja2')

        config.set_security_policy(
            SecurityPolicy(
                secret=settings['invest_web.secret']
            ),
        )

        config.add_subscriber(add_cors_headers_response_callback, NewRequest)
        # 给所有路由绑定OPTIONS请求处理
        config.add_route('options', '*subpath', request_method='OPTIONS')
        config.add_view(options_response, route_name='options')
        
        config.include('.routes')
        config.include('.models')
        config.scan()

    return config.make_wsgi_app()

3. 关键注意事项

  • 若前端需要携带凭证(如Cookie),Access-Control-Allow-Origin不能设为*,必须指定具体的请求源(如上代码中动态获取)。
  • Access-Control-Allow-Headers需包含前端实际使用的请求头,比如如果用到Authorization也要加入列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:32:45