Traffine I/O

日本語

2022-07-06

FastAPIでデフォルトの422エラーをカスタマイズする方法

はじめに

この記事では、通常、クライアントのリクエストにおけるバリデーションエラーを示すデフォルトの422エラーをFastAPIでカスタマイズする方法を紹介します。主に以下の2つのタスクを説明します。

  • RequestValidationErrorのデフォルトの例外ハンドラをオーバーライドして、カスタムのレスポンスを定義
  • OpenAPIドキュメントを変更して、デフォルトの422エラーレスポンスを削除

FastAPIでのデフォルトの422エラーのカスタマイズ

以下では、FastAPIでデフォルトの422エラーをカスタマイズする手順について説明します。これには、RequestValidationErrorのデフォルトの例外ハンドラをオーバーライドし、カスタムのバリデーションエラーレスポンスを作成する必要があります。

デフォルトの例外ハンドラのオーバーライド

RequestValidationErrorのデフォルトの例外ハンドラをオーバーライドするには、以下の手順に従ってください。

  1. 必要なモジュールをインポートし、新しいFastAPIアプリケーションインスタンスを作成
python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError

app = FastAPI()
  1. カスタムの例外ハンドラ関数を定義

カスタムの例外ハンドラ関数はRequestオブジェクトと発生したRequestValidationError例外を受け取る必要があります。関数は、JSONResponseなどのカスタムレスポンスを返すようにする必要があります。

python
async def custom_request_validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=422,
        content={
            "error_code": "CUSTOM_VALIDATION_ERROR",
            "message": "One or more request parameters failed validation",
            "detail": exc.errors(),
        },
    )
  1. カスタムの例外ハンドラをFastAPIアプリケーションインスタンスに登録
python
app.exception_handler(RequestValidationError)(custom_request_validation_exception_handler)

カスタムのバリデーションエラーレスポンスの作成

カスタムのバリデーションエラーレスポンスを作成するには、以下の手順に従ってください。

  1. Pydanticを使用してカスタムのレスポンスモデルを定義

カスタムのレスポンスモデルは、カスタムエラーレスポンスで返すフィールドを含める必要があります。

python
from pydantic import BaseModel

class CustomValidationError(BaseModel):
    error_code: str
    message: str
    detail: List[Dict[str, Any]]
  1. カスタムの例外ハンドラ関数を更新して、カスタムのレスポンスモデルを使用するようにする
python
async def custom_request_validation_exception_handler(request: Request, exc: RequestValidationError):
    custom_error = CustomValidationError(
        error_code="CUSTOM_VALIDATION_ERROR",
        message="One or more request parameters failed validation",
        detail=exc.errors(),
    )
    return JSONResponse(status_code=422, content=custom_error.dict())

これらの手順に従うことで、FastAPIでデフォルトの422エラーをカスタマイズすることができます。RequestValidationErrorが発生した場合には、カスタムのエラーレスポンスが返されます。

OpenAPIドキュメントからデフォルトの422エラーを削除

FastAPIは自動的にAPIのためのOpenAPIドキュメントを生成します。このドキュメントには、エンドポイントからの可能なレスポンスに関する情報が含まれます。デフォルトでは、OpenAPIドキュメントには、バリデーションエラーが発生する可能性を示すために、全てのエンドポイントに対して422エラーレスポンスが含まれます。

一部の場合では、OpenAPIドキュメントからこのデフォルトの422エラーを削除したい場合があります。これは、app.openapi()メソッドをカスタマイズすることで行うことができます。以下にその方法を示します。

  1. FastAPIアプリケーションインスタンスを定義した後、app.openapi()メソッドをオーバーライド
python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title="Custom schema",
        version="2.5.0",
        description="This is a very custom OpenAPI schema",
        routes=app.routes,
    )
    openapi_schema["paths"].pop("/openapi.json")
    app.openapi_schema = openapi_schema
    return app.openapi_schema

app.openapi = custom_openapi

上記のコードでは、custom_openapi()関数は既存のOpenAPIスキーマが存在する場合はそれを取得し、存在しない場合は新しいスキーマを生成します。openapi_schema["paths"].pop("/openapi.json")の行は、スキーマからOpenAPI JSONルートを削除します。

  1. custom_openapi()関数を更新して、OpenAPIスキーマからデフォルトの422エラーを削除
python
def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title="Custom schema",
        version="2.5.0",
        description="This is a very custom OpenAPI schema",
        routes=app.routes,
    )
    for path, path_dict in openapi_schema["paths"].items():
        for method, method_dict in path_dict.items():
            method_dict.pop("responses", {}).pop("422", None)
    app.openapi_schema = openapi_schema
    return app.openapi_schema

上記の更新されたcustom_openapi()関数では、OpenAPIスキーマ内の全てのパスとメソッドをイテレートし、レスポンスに422が存在する場合にそれを削除します。

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!