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

Flask本地前后端POST请求触发CORS错误,寻求解决方案

Flask POST请求CORS错误排查与解决

问题情况

本地前端(localhost:5173)向Flask后端(localhost:5000)发送请求时,GET路由可正常运行,但POST请求持续触发CORS错误,错误核心提示为预请求的响应包含重定向,不符合CORS规则。

相关代码

后端配置代码

import os
from flask import Flask
from flask_cors import CORS

from app.extensions import db, migrate, api

from app.controller.livro_controller import api as livro_ns

class testConfig():
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'flask_boilerplate_main.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    
def create_app():
    app = Flask(__name__)
    app.config.from_object(testConfig)
    CORS(app)
    db.init_app(app)
    migrate.init_app(app, db)
    api.init_app(app)
    
    api.add_namespace(livro_ns, path="/livro")

    return app

livro_controller.py代码

from flask import request, make_response
from flask_restx import Resource, marshal
from flask_cors import CORS, cross_origin

from app.util.dto import LivroDto
from app.service.livro_service import (
    editar_livro,
    excluir_livro,
    listar_todas_livros,
    criar_livro,
)

api = LivroDto.api
_livro = LivroDto.livro


@api.route("/")
class Livro(Resource):
    @api.doc('list_of_registered_users')
    @api.response(201, 'User successfully created.')
    @api.expect(_livro, validate=True)
    def post(self):
        data = request.json
        try:
            response = criar_livro(data)
            return response, 201
        except Exception as e:
            return {"message": str(e)}, 500

    @api.marshal_list_with(_livro, envelope="data")
    def get(self):
        try:
            return listar_todas_livros(), 200
        except Exception as e:
            return {"message": str(e)}, 500


@api.route("/<int:id_livro>")
@api.param("id_livro", "Book ID")
class LivroComId(Resource):
    @api.expect(_livro, validate=True)
    def put(self, id_livro):
        data = request.json
        try:
            response = editar_livro(id_livro, data)
            return response, 200
        except Exception as e:
            return {"message": "An error occurred while updating the book."}, 500

    def delete(self, id_livro):
        try:
            response = excluir_livro(id_livro)
            return response, 204
        except Exception as e:
            return {"message": "An error occurred while deleting the book."}, 500

前端请求代码

import axios from "axios";
import { livroType } from "../types/livro";


export function criarLivro(livro: livroType) {
    return axios.post("http://localhost:5000/livro", livro);
}

export function todosLivros() {
    return axios.get("http://localhost:5000/livro"); 
}

错误信息

Access to XMLHttpRequest at 'http://localhost:5000/livro' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
POST http://localhost:5000/livro net::ERR_FAILED
xhr.js:158 Uncaught (in promise) AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
apiFunctions.ts:6 XHR failed loading: POST "http://localhost:5000/livro".

解决方案

1. 解决路由重定向问题

错误核心是预请求被重定向,这是Flask默认strict_slashes行为导致的:当请求路径末尾无斜杠,而路由定义带斜杠时,Flask会自动重定向到带斜杠的路径,但CORS预请求(OPTIONS)不允许重定向。

修改Flask初始化代码,关闭严格斜杠检查:

def create_app():
    # 添加 strict_slashes=False 关闭自动重定向
    app = Flask(__name__, strict_slashes=False)
    app.config.from_object(testConfig)
    CORS(app)
    # ... 其余代码不变

或者统一前后端路径:前端请求改为http://localhost:5000/livro/(带末尾斜杠),与后端@api.route("/")的定义匹配。

2. 优化CORS配置

全局CORS配置可以更明确,指定允许的源和支持凭据,避免覆盖问题:

def create_app():
    app = Flask(__name__, strict_slashes=False)
    app.config.from_object(testConfig)
    # 明确指定允许的前端源,支持OPTIONS方法和凭据
    CORS(app, origins="http://localhost:5173", supports_credentials=True)
    # ... 其余代码不变

也可以针对命名空间单独配置CORS,在livro_controller.py的类上添加装饰器:

@api.route("/")
@cross_origin(origins="http://localhost:5173")
class Livro(Resource):
    # ... 类内代码不变

3. 手动处理预请求

确保Flask-CORS正确处理OPTIONS请求,可在Livro类中手动添加OPTIONS方法支持:

@api.route("/")
class Livro(Resource):
    def options(self):
        # 直接返回200,让预请求通过
        return {'Allow': 'GET, POST, OPTIONS'}, 200
    # ... 其余post、get方法不变

验证步骤

  1. 重启Flask后端服务
  2. 重新发送POST请求,检查是否仍有CORS错误
  3. 若仍有问题,打开浏览器开发者工具的网络标签,查看OPTIONS请求的响应头,确认是否包含Access-Control-Allow-Origin等CORS相关头

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:55:56