fastapi/docs/zh/docs/tutorial/middleware.md

96 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 中间件 { #middleware }
你可以向 **FastAPI** 应用添加中间件。
“中间件”是一个函数,它会在每个特定的*路径操作*处理每个**请求**之前运行,也会在返回每个**响应**之前运行。
* 它接收你的应用的每一个**请求**。
* 然后它可以对这个**请求**做一些事情或者执行任何需要的代码。
* 然后它将这个**请求**传递给应用程序的其他部分(某个*路径操作*)处理。
* 之后它获取应用程序生成的**响应**(由某个*路径操作*产生)。
* 它可以对该**响应**做一些事情或者执行任何需要的代码。
* 然后它返回这个**响应**。
/// note | 技术细节
如果你有使用 `yield` 的依赖,依赖中的退出代码会在中间件之后运行。
如果有任何后台任务(会在[后台任务](background-tasks.md){.internal-link target=_blank}一节中介绍,你稍后会看到),它们会在所有中间件之后运行。
///
## 创建中间件 { #create-a-middleware }
要创建中间件,你可以在函数的顶部使用装饰器 `@app.middleware("http")`
中间件函数会接收:
* `request`
* 一个函数 `call_next`,它会把 `request` 作为参数接收。
* 这个函数会把 `request` 传递给相应的*路径操作*。
* 然后它返回由相应*路径操作*生成的 `response`
* 在返回之前,你可以进一步修改 `response`
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
/// tip
请记住可以<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">使用 `X-` 前缀</a>添加专有自定义请求头。
但是如果你有希望让浏览器中的客户端可见的自定义请求头,你需要把它们加到你的 CORS 配置([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})的 `expose_headers` 参数中,参见 <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette 的 CORS 文档</a>
///
/// note | 技术细节
你也可以使用 `from starlette.requests import Request`
**FastAPI** 为了开发者方便提供了该对象,但它直接来自 Starlette。
///
### 在 `response` 之前与之后 { #before-and-after-the-response }
你可以在任何*路径操作*接收 `request` 之前,添加要与该 `request` 一起运行的代码。
也可以在生成 `response` 之后、返回之前添加代码。
例如,你可以添加一个自定义请求头 `X-Process-Time`,其值为处理请求并生成响应所花费的秒数:
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
/// tip
这里我们使用 <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> 而不是 `time.time()`,因为在这类场景中它可能更精确。🤓
///
## 多个中间件的执行顺序 { #multiple-middleware-execution-order }
当你使用 `@app.middleware()` 装饰器或 `app.add_middleware()` 方法添加多个中间件时,每个新中间件都会包裹应用,形成一个栈。最后添加的中间件是“最外层”的,最先添加的是“最内层”的。
在请求路径上,最外层的中间件先运行。
在响应路径上,它最后运行。
例如:
```Python
app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)
```
这会产生如下执行顺序:
* 请求MiddlewareB → MiddlewareA → 路由
* 响应:路由 → MiddlewareA → MiddlewareB
这种栈式行为确保中间件按可预测且可控的顺序执行。
## 其他中间件 { #other-middlewares }
你可以稍后在[高级用户指南:高级中间件](../advanced/middleware.md){.internal-link target=_blank}中阅读更多关于其他中间件的内容。
你将在下一节中了解如何使用中间件处理 <abbr title="Cross-Origin Resource Sharing - 跨域资源共享">CORS</abbr>