背景
- 前面講了可以自定義 Response,那么這里就講下請求對象 Request
- 可以通過 Request 來獲取一些數據
獲取請求基礎信息
@app.get("/base") async def get_base(*, request: Request): res = { # 客戶端連接的 host "host": request.client.host, # 客戶端連接的端口號 "port": request.client.port, # 請求方法 "method": request.method, # 請求路徑 "base_url": request.base_url, # request headers "headers": request.headers, # request cookies "cookies": request.cookies } return res
請求結果
{ "host": "127.0.0.1", "port": 54364, "method": "GET", "base_url": { "_url": "http://127.0.0.1:8080/" }, "headers": { "host": "127.0.0.1:8080", "connection": "keep-alive", "sec-ch-ua": "\"Chromium\";v=\"94\", \"Google Chrome\";v=\"94\", \";Not A Brand\";v=\"99\"", "accept": "application/json", "sec-ch-ua-mobile": "?0", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36", "sec-ch-ua-platform": "\"macOS\"", "sec-fetch-site": "same-origin", "sec-fetch-mode": "cors", "sec-fetch-dest": "empty", "referer": "http://127.0.0.1:8080/docs", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6", "cookie": "test_token=tokenABC" }, "cookies": { "test_token": "tokenABC" } }
可以看到 port 並不是 8080
request.url 對象
from fastapi import Query @app.get("/url/{item_id}") async def get_url(*, item_id: str, name: str = Query(...), request: Request): res = { # 請求 url "url": request.url, # 總的組成 "components": request.url.components, # 請求協議 "scheme": request.url.scheme, # 請求 host "hostname": request.url.hostname, # 請求端口 "url_port": request.url.port, # 請求 path "path": request.url.path, # 請求查詢參數 "query": request.url.query, "fragment": request.url.fragment, "password": request.url.password } return res
請求結果
{ "url": { "_url": "http://127.0.0.1:8080/url/123?name=456", "_components": [ "http", "127.0.0.1:8080", "/url/123", "name=456", "" ] }, "components": [ "http", "127.0.0.1:8080", "/url/123", "name=456", "" ], "scheme": "http", "hostname": "127.0.0.1", "url_port": 8080, "path": "/url/123", "query": "name=456", "fragment": "", "password": null }
request.url 是一個對象(URL 類),得到的是一個字典
獲取路徑參數、查詢參數
@app.get("/query_path/{item_id}") async def get_all(*, item_id: str, name: str = Query(...), request: Request): res = { # 獲取路徑參數 "path_params": request.path_params, "item_id": request.path_params.get("item_id"), # 獲取查詢參數 "query_params": request.query_params, "name": request.query_params["name"] } return res
請求結果
{ "path_params": { "item_id": "123" }, "item_id": "123", "query_params": { "name": "小菠蘿" }, "name": "小菠蘿" }
path_params、query_params返回的都是字典格式的數據
獲取表單數據
@app.post("/form") async def get_form(*, username: str = Form(...), oassword: str = Form(...), request: Request): res = { # 獲取表單數據 "form": await request.form() } return res
請求結果
{ "form": { "username": "name", "oassword": "***" } }
獲取 Request Body
class Item(BaseModel): id: str title: str @app.post("/body") async def get_body(item: Item, request: Request): res = { # 獲取 Request Body "body": await request.json(), "body_bytes": await request.body() } return res
請求結果
{ "body": { "id": "string", "title": "string" }, "body_bytes": "{\n \"id\": \"string\",\n \"title\": \"string\"\n}" }
.body() 返回值類型是 bytes
獲取 Request 存儲的附加信息
async def dep_state(request: Request): # 給 request 存儲附加數據 request.state.db = "Mysql+pymysql//username" @app.post("/state/", dependencies=[Depends(dep_state)]) async def get_state(request: Request): res = { "state": request.state, "db": request.state.db } return res
請求結果
{ "state": { "_state": { "db": "Mysql+pymysql//username" } }, "db": "Mysql+pymysql//username" }
獲取文件上傳信息
from fastapi import UploadFile, File, Form @app.post("/file") async def get_file(*, file: UploadFile = File(...), name: str = Form(...), request: Request): form_data = await request.form() res = { # 表單數據 "form": form_data, # 文件對象 UploadFile "file": form_data.get("file"), # 文件名 "filename": form_data.get("file").filename, # 文件類型 "content_type": form_data.get("file").content_type, # 文件內容 "file_content": await form_data.get("file").read() } return res
請求結果
{ "form": { "file": { "filename": "test.txt", "content_type": "text/plain", "file": {} }, "name": "表單name!!" }, "file": { "filename": "test.txt", "content_type": "text/plain", "file": {} }, "filename": "test.txt", "content_type": "text/plain", "file_content": "hello world" }
UploadFile 對象
- form_data.get("file") 返回的是一個 starlette.datastructures.UploadFile 對象
- filename、content_type 是對象實例屬性
- .read() 是實例方法,讀取文件
UploadFile 的其他異步方法
和 Python 普通的文件對象方法一樣,只不過都是 async 異步的
- write
- read
- seek
- close