6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[FastAPI] 知っておくと超便利!!!ミドルウェアを使用したエラーハンドリング

Posted at

この記事を読んでできること

  • エラーハンドリングができる
  • 同じような例外処理を各APIに書かなくても済む(可読性・保守性の向上)

概要

StarletteのBaseHTTPMiddlewareを使用して共通した複数の例外処理の機能を受け持つようにする

記述しないこと

  • FastAPIについて
  • 例外処理について

使用技術

  • Python 3.10.4
  • fastapi 0.78.0
  • Starlette 0.19.1

ミドルウェアの処理の流れ

  1. アプリケーションに届いたリクエストをミドルウェアが受け取る
  2. そのリクエストに対して何らかのコードを実行する
  3. アプリケーションの残りの部分にリクエストを渡して (path operation によって) 処理させる
  4. ミドルウェアはアプリケーション (の path operation) によって生成されたレスポンスを受け取る
  5. そのレスポンスに対して何らかのコードを実行する
  6. レスポンスを返す

実装例

main.py
from fastapi import FastAPI
from middleware import ErrorHandlingMiddleware


app = FastAPI()

app.add_middleware(ErrorHandlingMiddleware)

アプリケーションにミドルウェアを呼び込むにはapp.add_middleware()を追記する

error.py
class InvalidInputError(Exception):
    """APIにて受付番号が発行されなかった場合のカスタムエラー"""

    pass

自作エラーの設定

middleware.py
from fastapi import Request, Response, status
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

from error import InvalidInputError


class ErrorHandlingMiddleware(BaseHTTPMiddleware):
    """エラーハンドリングをするミドルウェア
    API内で発生したエラーをキャッチして処理を施す
    Args:
        BaseHTTPMiddleware : リクエスト/レスポンスインタフェースに対するASGIミドルウェアを記述するための抽象クラス
    """

    async def dispatch(self, request: Request, call_next) -> Response:
        try:
            response: Response = await call_next(request)

        except InvalidInputError as e:
            response = JSONResponse(
                {"msg": "InvalidInputError:受付番号が発行されませんでした。送信内容をもう一度確認してください。"},
                status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        except TypeError as e:
            response = JSONResponse(
                {"msg": "TypeError:内容を確認してもう一度データ挿入をしてください。"},
                status.HTTP_404_NOT_FOUND,
            )
        except TimeoutError as e:
            response = JSONResponse(
                {"msg": "TimeoutError:タイムアウトエラーが発生しました。"},
                status.HTTP_408_REQUEST_TIMEOUT,
            )
        except RuntimeError as e:
            response = JSONResponse(
                {"msg": "RuntimeError:ランタイムエラーが発生しました。"},
                status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        except Exception as e:
            response = JSONResponse(
                {"msg": "Exception:基底クラスエラーが発生しました。"},
                status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        return response
  • APIで発生したエラーは最終的にこのミドルウェアでキャッチしてエラーメッセージを返すことができる
  • 自作エラーも使用することができる
  • エラー以外にも共通する処理であればなんでもできる

まとめ

ミドルウェアってすごい便利だね

参考

6
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?