FastAPI 中间件 CORSMiddleware :配置跨域资源共享 CORS 中间件

FastAPI 中间件 CORSMiddleware :配置跨域资源共享 CORS 中间件


推荐阅读 📚🎓🧑‍🏫

[1] 一起学Python 专栏:深入探讨 Python 编程,涵盖基础与进阶内容,以及 NumPyPandasMatplotlibDockerLinux 等实用技术。


在现代Web应用中,前端和后端通常会运行在不同的源(协议、域名、端口)上,这就可能引发跨域资源共享(CORS)问题。跨域资源共享(CORS)是浏览器安全机制的一部分,用于解决前端和后端不在同一源下时的通信问题。FastAPI通过CORSMiddleware提供简单而强大的跨域支持。本文介绍了如何在FastAPI中配置CORS,以允许特定的前端源访问后端API,确保跨域请求能够正常工作。通过示例代码,展示了如何设置允许的源、HTTP方法、请求头及凭证支持。了解CORS的配置不仅能解决跨域问题,还能提高Web应用的安全性和灵活性。

以下示例中使用的 Python 版本为 Python 3.10.15,FastAPI 版本为 0.115.4

一 示例代码

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost.tiangolo.com",
    "https://localhost.tiangolo.com",
    "http://localhost",
    "http://localhost:8080",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
async def main():
    return {"message": "Hello World"}

运行代码文件 mi02.py 来启动应用:

$ uvicorn mi02:app --reload

SwaggerUI 中可以查看在线文档:http://127.0.0.1:8000/docs

二 什么是跨源资源共享(CORS)

CORS 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。

三 什么是源

源由协议(httphttps)、域(myapp.comlocalhost)和端口(804438080)组成。不同的源:http://localhosthttps://localhosthttp://localhost:8080

四 跨域请求

Frontend (http://localhost:8080) Backend (http://localhost) 发起 HTTP OPTIONS 请求 返回 CORS 相关的 headers(允许 http://localhost:8080) 发起实际的 HTTP 请求(如 GET 或 POST) 返回请求响应 后端的 "允许的源" 列表必须包含 http://localhost:8080 Frontend (http://localhost:8080) Backend (http://localhost)

跨域请求发生在前端和后端之间,前端和后端的 不完全相同。根据浏览器的同源策略,只有当协议、域名和端口完全相同,浏览器才允许直接通信。在这个场景中,前端运行在 http://localhost:8080,而后端在 http://localhost(端口为 80),因此这被视为不同的源,即使它们的域名相同。由于使用了不同的端口,浏览器认为它们是不同的源,因此会触发 跨域资源共享(CORS) 机制。

五 通配符

后端的 “允许的源” 列表可以使用 "*" 通配符,表示允许所有源。但这种方式不适用于涉及凭据(如 Cookies 或 Bearer 令牌)的请求。建议显式指定允许的

六 使用 CORSMiddleware

from fastapi.middleware.cors import CORSMiddleware

# 定义允许的跨域源列表
origins = [
    "http://localhost.tiangolo.com",  # 允许的源(http协议)
    "https://localhost.tiangolo.com", # 允许的源(https协议)
    "http://localhost",              # 允许的源(localhost,没有指定端口)
    "http://localhost:8080",         # 允许的源(localhost,指定端口8080)
]

# 将 CORSMiddleware 添加为中间件,配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,           # 允许的源列表
    allow_credentials=True,         # 启用跨域请求时支持 cookies
    allow_methods=["*"],            # 允许所有 HTTP 方法
    allow_headers=["*"],            # 允许所有请求头
)

可以使用 from starlette.middleware.cors import CORSMiddleware 导入CORSMiddlewareCORSMiddleware 支持的参数:

  • allow_origins:允许的源列表,如 ['https://example.org'],或 ['*'] 允许所有源。
  • allow_origin_regex:正则表达式,匹配的源允许跨域请求。
  • allow_methods:允许的 HTTP 方法,默认为 ['GET'],或使用 ['*'] 允许所有方法。
  • allow_headers:允许的请求头,默认为 [],或使用 ['*'] 允许所有头部。
  • allow_credentials:是否支持 cookies,默认 False。启用时,allow_origins 不能为 ['*']
  • expose_headers:允许浏览器访问的响应头,默认为 []
  • max_age:浏览器缓存 CORS 响应的最长时间(秒),默认为 600

七 CORS 预检请求

带有 OriginAccess-Control-Request-Method 请求头的 OPTIONS 请求。中间件会拦截并返回带有 CORS headers 的 200400 响应。带有 Origin 请求头的请求,中间件会正常传递请求,并在响应中包含 CORS headers。举例:

# 请求
OPTIONS / HTTP/1.1
Accept: */*
Accept-Encoding: deflate, gzip
User-Agent: your-user-agent
Host: 127.0.0.1

# 响应
HTTP/1.1 405 Method Not Allowed
access-control-allow-credentials: true
allow: GET
content-length: 31
content-type: application/json
date: Thu, 13 Feb 2025 02:23:34 GMT
server: uvicorn

{"detail":"Method Not Allowed"}

八 完整代码示例

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost.tiangolo.com",
    "https://localhost.tiangolo.com",
    "http://localhost",
    "http://localhost:8080",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
async def main():
    return {"message": "Hello World"}

九 源码地址

详情见:GitHub FastApiProj

十 参考

[1] FastAPI 文档

[2] 跨源资源共享(CORS)

[3] Starlette’s CORS docs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码不忘补水

感谢有你,让我的创作更有价值!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值