一、什么是中間件
(一)概念
中間件是一個函數,它在它在每個請求被特定的路徑操作處理前,以及每個響應返回之前工作,所以:
- Request Middleware接收你應用程序的每一個請求
- 然后它可以對這個請求做一些操作,完成一些功能
- 處理完成后,Request Middleware將請求轉發給Application
- Response Middleware接收到Application的響應
- 然后可以對響應做一些操作,完成一些功能
- 處理完成后,Response Middleware將響應進行返回給客戶端
(二)使用
- 創建中間件
import time from fastapi import FastAPI, Request app = FastAPI() @app.middleware("http") async def add_process_time_header(request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(process_time) return response
上面創建了一個add_process_time_header的中間件,它的功能就是添加一個響應頭,並且響應頭的值就是處理這個響應的耗時時間。創建一個中間件你需要在
對應的函數頂部使用@app.middleware("http")裝飾器,然后中間件函數需要接收兩個參數:
- request
- callnext 這個函數將request傳遞給對應的路徑操作,然后得到響應的response
上述的中間件函數就是在調用callnext前后分別計算出時間,也就是響應開始和結束的時間,最后將響應再加一個自定義的響應頭,注意一般自定義的響應頭以"X-"為前綴,與內置的進行區分。
- 使用中間件
... @app.get("/items/") async def get_items(): items = [ {"name": "apple", "price": "1.12"}, {"name": "pear", "price": "3.14"} ] return items ...
中間件是針對全局的,相當於一個全局的鈎子,只要用同一個FastAPI實例,每一個請求都會走這個中間件。
二、常見中間件
(一)CORS Middleware
在使用前后台分離開發的過程中,跨域是避免不了的,所以該中間件針對的就是跨域資源共享。
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins = [ "http://127.0.0.1", "http://127.0.0.1:8000", ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"] ) @app.get("/items/") async def get_items(): items = [ {"name": "apple", "price": "1.12"}, {"name": "pear", "price": "3.14"} ] return items
這就添加了一個跨域的中間件,詳細參數可參考源碼:
class CORSMiddleware: def __init__( self, app: ASGIApp, allow_origins: typing.Sequence[str] = (), allow_methods: typing.Sequence[str] = ("GET",), allow_headers: typing.Sequence[str] = (), allow_credentials: bool = False, allow_origin_regex: str = None, expose_headers: typing.Sequence[str] = (), max_age: int = 600, ) -> None: ...
(二)HTTPSRedirectMiddleware
強制所有的請求必需是http或者wss協議。
from fastapi import FastAPI from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware app = FastAPI() app.add_middleware(HTTPSRedirectMiddleware) @app.get("/items/") async def get_items(): items = [ {"name": "apple", "price": "1.12"}, {"name": "pear", "price": "3.14"} ] return items
(三)TrustedHostMiddleware
強制所有的請求都設置了正確的Host頭部信息,為了防止HTTP Host的頭部攻擊。
from fastapi import FastAPI from fastapi.middleware.trustedhost import TrustedHostMiddleware app = FastAPI() app.add_middleware( TrustedHostMiddleware, allowed_hosts=["*.example.com"] ) @app.get("/items/") async def get_items(): items = [ {"name": "apple", "price": "1.12"}, {"name": "pear", "price": "3.14"} ] return items
(四)GZipMiddleware
當請求的請求頭中Accept-Encoding字段值包含“gzip”時,該中間件負責處理這個結果並進行響應。這個中間件將會處理標准以及流響應。
from fastapi import FastAPI from fastapi.middleware.gzip import GZipMiddleware app = FastAPI() app.add_middleware( GZipMiddleware, minimum_size=1000 ) @app.get("/items/") async def get_items(): items = [ {"name": "apple", "price": "1.12"}, {"name": "pear", "price": "3.14"} ] return items
如果不指定minimum_size的大小,將會使用其默認值500。