見出し画像

Djangoでミドルウェアを自作する #457

久しぶりの投稿になってしまいました。
腰の手術で入院していたことに加え、この度エンジニアとして転職することが決まり、次の現場で使われているGO言語のキャッチアップに時間を使っていたためです。

次はGOのアウトプットをしていこうと思ってましたが、現職でとても良い学びがあり、堪らずにDjangoでアウトプットしています。

Webミドルウェアとは

ミドルウェアという言葉はコンピュータサイエンスの様々な文脈で使われますが、ここで自作するのは一般的なミドルウェアではなく、Webミドルウェアと分類されるものです。

一般的なミドルウェアは、オペレーティングシステムとエンドユーザーアプリケーションの間に位置するソフトウェアやサービスの層です。異なるアプリケーション間でのデータ通信を容易にしたり、複数のプログラムで共通の機能を提供したりします。

対してWebミドルウェアは、WebアプリケーションまたはWebサーバー内部で動作するコンポーネントであり、リクエストとレスポンスの処理過程において特定のタスクを実行します。

Djangoのミドルウェアは、Webサーバーからのリクエストが最終的なViewに到達する前後で、セキュリティチェック、セッション管理、リクエストの前処理、レスポンスの後処理などを行います。

ミドルウェアへのパスを設定する

ミドルウェアの定義に入る前に、settings.pyMIDDLEWAREでパスを設定します。デフォルトで設定されているミドルウェアの下に追加します。

[settings.py]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'yourapp.middleware.sample_middleware.YourMiddleware',  <- ここに追加
]

ダミーですが、YourMiddlewareというミドルウェアを追加しています。

また、デフォルトではセキュリティチェックやセッション管理のミドルウェアが設定されているのが分かりますね。

ミドルウェアを定義する

ソースコードにmiddlewareディレクトリを作成し、その配下にsample_middleware.pyを作成します。

以下をベースにすればお好みの処理を実装できると思います。

[sample_middleware.py]
 
class YourMiddleware:
  def __init__(self, get_response):  # 起動時に一度だけ呼ばれ、ここでget_responseを受け取ることで、各ミドルウェアは次に何を呼び出すべきか(次のミドルウェアか、あるいは全てのミドルウェアが終了した後のビュー)を知る
    self.get_response = get_response

  def __call__(self, request):  # Djangoがリクエストを受け取るたびに呼び出され、ここでget_response(request)を実行して次の処理(次のミドルウェアやビュー)へリクエストを渡す
    # ここにリクエストに対する前処理を書ける
    response = self.get_response(request) # 次のミドルウェアまたはビューを呼び出し
    # ここにリクエストに対する後処理を書ける

    return response

  def process_view(self, request, view_func, view_args, view_kwargs):  # ビューが呼び出される直前に実行される
    # viewに対する前処理はここに定義する(リクエストのログを取るなど)
    # view_funcは呼び出されるview関数
    # view_argsとview_kwargsはview関数に渡される引数とキーワード引数

なお、記載しているget_response引数は、Djangoのリクエスト/レスポンス処理システムの中核的な部分です。get_responseは、次に呼び出すべきミドルウェアの__call__メソッドまたは最終的なビューを呼び出す関数への参照です。

get_responseの役割

Djangoのミドルウェアシステムは、リクエストが来たときに、設定されているミドルウェアのリストを順番に実行していきます。

各ミドルウェアの__init__は起動時に一度だけ呼ばれ、ここでget_responseを受け取ります。これにより、各ミドルウェアは次に何を呼び出すべきか(次のミドルウェアか、あるいは全てのミドルウェアが終了した後のビュー)を知ることができます。

つまり、get_responseはミドルウェアのチェーンまたは最終的なビューへのリンクとして機能します。


ここまでお読みいただきありがとうございました!!

この記事が気に入ったらサポートをしてみませんか?