2023年8月30日水曜日

fastapiでヘッダのアクション名に応じてコールするルーティングを変更する方法

fastapiでヘッダのアクション名に応じてコールするルーティングを変更する方法

概要

前回の続きです
ヘッダの情報に合わせて適切なルーティングをコールするようにしてみました

環境

  • Python 3.11.3
  • fastapi 0.100.1
  • pydantic 2.1.1

サンプルコード

from typing import Self

from fastapi import Depends, FastAPI, Form, Request
from pydantic import BaseModel, field_validator

app = FastAPI()


async def get_action(request: Request) -> str:
    action = request.headers.get("Action", "default")
    return action


class UserForm(BaseModel):
    username: str
    password: str

    @classmethod
    def as_form(cls, username: str = Form(...), password: str = Form(...)) -> Self:
        return cls(username=username, password=password)

    @field_validator("username")
    def validate_username(cls, v):
        if v != "hawksnowlog":
            raise ValueError("Invalid username.")
        return v


@app.get("/")
async def root(request: Request, action: str = Depends(get_action)):
    form_data = await request.form()
    if action == "Hoge":
        # FormData は immutableDict なのでアンパックできる
        return await hoge(action, UserForm(**form_data))  # type: ignore
    return action


@app.post("/hoge")
async def hoge(
    action: str = Depends(get_action), form_data: UserForm = Depends(UserForm.as_form)
):
    return action, form_data.username

動作確認

  • pipenv run uvicorn app:app --reload

POST で送信できる

  • curl -XPOST -H "Action: Hoge" localhost:8000/hoge -H "content-type: application/x-www-form-urlencoded" -d "username=hawksnowlog&password=pass"

GET からも送信できる

  • curl -XGET -H "Action: Hoge" localhost:8000 -H "content-type: application/x-www-form-urlencoded" -d "username=hawksnowlog&password=pass"

どちらも username のバリデーションが動作していることも確認できると思います

最後に

同一パスに対する異なる処理を書きたい場合には使えるテクニックかなと思います

0 件のコメント:

コメントを投稿