FastAPI 中间件 CORSMiddleware :配置跨域资源共享 CORS 中间件
推荐阅读 📚🎓🧑🏫
[1] 一起学Python 专栏:深入探讨 Python 编程,涵盖基础与进阶内容,以及 NumPy、Pandas、Matplotlib、Docker、Linux 等实用技术。
在现代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 代码,而后端处于与前端不同的「源」的情况。
三 什么是源
源由协议(http
、https
)、域(myapp.com
、localhost
)和端口(80
、443
、8080
)组成。不同的源:http://localhost
、https://localhost
、http://localhost:8080
。
四 跨域请求
跨域请求发生在前端和后端之间,前端和后端的 源 不完全相同。根据浏览器的同源策略,只有当协议、域名和端口完全相同,浏览器才允许直接通信。在这个场景中,前端运行在 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
导入CORSMiddleware
。CORSMiddleware
支持的参数:
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 预检请求
带有 Origin
和 Access-Control-Request-Method
请求头的 OPTIONS
请求。中间件会拦截并返回带有 CORS headers 的 200
或 400
响应。带有 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"}
九 源码地址
十 参考
[1] FastAPI 文档
[2] 跨源资源共享(CORS)