FastAPI 从0到1(中间件和跨域篇)筛选
在该章节,主要针对 FastAPI 中的中间件和只要去开发一个接口就能遇到的跨域问题进行细节描述
中间件
中间件我们在以往的篇幅中讲过其中的具体逻辑,主要在 Django 框架中进行的讲解,快速通道
下面我们将对 fastAPI 框架讲解如何将中间件嵌套其中
在 FastAPI 中,其框架内部有装饰器,要创建中间件可以在函数的顶部使用装饰器 @app.middleware(“http”).
中间件参数如下:
- request
- 一个函数call_next,它将接收request,作为参数
用装饰器去装饰的这个函数将 request 传递给相应的路径操作,然后它将返回由相应的路径操作生成的 response.然后你可以在返回 response 前进一步修改它.
简单来说:在执行 await call_next(request) 之前,也就是用户通过浏览器请求进来之前进行的操作,而 await call_next(request) 之后就是视图函数做了一系列的逻辑、数据处理后响应回去的最后一步
等同与在Django中间件中的 process_request 和 process_response 函数的结合,其架构图如下:
上代码:
from fastapi import FastAPI, Form, File, UploadFile, Request
from typing import List
from uvicorn import run
app = FastAPI()
@app.middleware("http")
async def add_header(request: Request, call_next):
# 请求代码块
print("start request....")
response = await call_next(request)
# 响应代码块
response.headers["author"] = "beipiaoqiang"
print("start response ...")
return response
# 简单使用
@app.get('/')
def index(request:Request):
print("start index....")
print('视图函数')
return templates.TemplateResponse(
'index.html',
{
'request': request,
'user': '北漂强',
'e_name': 'beipiaoqiang',
"books": ["三国演义", "水浒传", "西游记", "红楼梦"],
"booksDict": {
"三国演义": {"price": 100, "publish": "桃子出版社"},
"聊斋志异": {"price": 200, "publish": "橘子出版社"},
}
})
start request....
start index....
视图函数
start response ...
上面的代码被我简化了一下,可以帮助你更清楚的去理解中间件,其访问这个视图后打印出如上数据,可以清楚的看到,请求过来后先去中间件做一次处理,然后去找路由执行视图函数,在然后响应才进行对返回的 response 进行处理。关于中间件我们就讲这么多,如果还是很不理解,可以去看我之前的文章,这里需要注意的几点有:
- 可以定义多个中间件,其运行是从上到下去运行,开发时要注意中间件的定义顺序
- 如果你使用了 yield 关键字依赖, 依赖中的退出代码将在执行中间件后执行.
- 如果有任何后台任务(稍后记录), 它们将在执行中间件后运行.
CORS 跨域
1 什么是跨域?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
- 协议类似: http、https
- 域名类似:www.example.com、127.0.0.1
- 端口类似:www.exmaple.com:80、127.0.0.1:8000
2 跨域复现
我们直接写一个 ajax 请求,去请求我们当前的后端接口,其代码和响应如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<button>button</button>
<script>
$("button").click(function () {
$.ajax({
url: "http://127.0.0.1:8080/",
success: function (res) {
$("p").html(res.message)
},
})
})
</script>
</body>
</html>
从图上可以清楚的看到是 CORS 错误(跨域),这是为什么?因为他们不同源,如何解决?添加对应的头部信息
3 解决跨域问题
在 FastAPI 中,我们可以自己写一个中间件去解决,当然在框架中也已经帮我们实现好了这个中间件,直接注册到框架中即可,我们一个一个来讲解
1 自定义中间件解决 CORS
@app.middleware("http")
async def add_header(request: Request, call_next):
# 请求代码块
response = await call_next(request)
# 响应代码块
response.headers["Access-Control-Allow-Origin"] = "*"
return response
我们还拿之前注册的这个中间件来说,我们可以在数据响应回去给前端时,添加一个响应头:response.headers[“Access-Control-Allow-Origin”] = “*”,其中 * 代表所有url 都可以返回,也可以将 * 换成具体的 URL 路径,则只能在该路径下通过 CORS
2 内部封装的中间件解决 CORS
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:63342"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET"],
allow_headers=["*"],
)
代码如上,我们可以导入其 CORSMiddleware 模块,将其注册到我们的 app 中,相当于手写的中间件,可以进入其内部查看该中间件的实现及各种参数,这里就不一一的讲解,其结果和我们手写的是一样的,只不过他内部定义的中间件考虑的很多,更周到。
好了,今天我们就到这里!有啥问题大家可以评论区交流
乾坤未定,你我皆牛马