コンテンツにスキップ

ミドルウェア

Starletteには、アプリケーション全体に適用される動作を追加するためのいくつかのミドルウェアクラスが含まれています。これらは標準のAS GIミドルウェアクラスとして実装されており、Starletteまたは他のAS GIアプリケーションに適用できます。

ミドルウェアの使用

Starletteアプリケーションクラスを使用すると、常に例外ハンドラにラップされるような方法でAS GIミドルウェアを含めることができます。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからインポートします。HTTPSRedirectMiddleware
starlette.ミドルウェア. trustedhostからインポートTrustedHostMiddleware

ルート=.。。

#すべてのリクエストに'example.com'または
#'*.example.com'ホストヘッダーを指定し、HTTPのみのアクセスを厳密に強制します。
ミドルウェア=[
    ミドルウェア(
        TrustedHostMiddleware、
        割り当てられたホスト=['example.com','*.example.com'],
    ),
    ミドルウェア(HTTPSRedirectMiddleware)
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

デフォルトでは、各Starletteアプリケーションには自動的に2つのミドルウェアが含まれます。

  • ServerErrorMiddleware-アプリケーション例外がカスタム500ページを返すか、DEBUGモードでアプリケーションのトレース情報を表示できるようにします。これは常に最外層のミドルウェア層です。
  • ExceptionMiddleware-例外ハンドラを追加して、特定の種類の予期しない例外をハンドラ関数に関連付けることができます。たとえば、エンドポイント内で HTTPException(status_code=404) を起動すると、最終的にカスタム404ページが表示されます。

ミドルウェアは上から下に評価されるため、サンプルアプリケーションでは次のように実行されます。

  • ミドルウェア
    • ServerErrorMiddleware
    • TrustedHostMiddleware
    • HTTPSRedirectMiddleware
    • ExceptionMiddleware
  • ルーティング
  • エンドポイント

Starletteパッケージでは、次のミドルウェアを使用して実装できます。

CORSミドルウェア

外部に送信された応答に適切なCORSヘッダーを追加して、ブラウザからのクロスソースリクエストを許可します。

CORSMiddlewareの実装で使用されるデフォルトパラメータはデフォルトで制限されているため、ブラウザがクロスドメインコンテキストでそれらを使用できるように、特定のソース、メソッド、またはヘッダーを明示的に有効にする必要があります。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
CORSMiddlewareをインポートする

ルート=.。。

ミドルウェア=[
    ミドルウェア(CORSMiddleware, allow_origins=['*'])
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

次の議論が支持されました。

  • allow_origins-クロスソースリクエストを許可するソースのリスト。例えば ['https://example.org', 'https://www.example.org']。['*'] を使用して任意のソースを許可できます。
  • allow_origin_regex-クロスソースリクエストが許可されるべきソースをマッチングするための正規表現文字列。例:'https://.*\.example\.org'。
  • allow_methods-クロスソースリクエストで使用できるHTTPメソッドのリスト。デフォルトは ['GET'] です。['*'] を使用すると、すべての標準メソッドを許可できます。
  • allow_headers-クロスソースリクエストでサポートされるHTTPリクエストヘッダーのリスト。デフォルトは [] です。['*'] を使用すると、すべてのヘッダーを許可できます。 CORSリクエストの場合、Accept、Accept-Language、Content-Language、および Content-Type ヘッダーは常に許可されます。
  • allow_credentials-クロスソースリクエストをサポートするCookieを示します。デフォルトは False です。さらに、資格情報を許可するために、allow_origins、allow_methods、allow_headers を ['*'] に設定することはできません。これらはすべて明示的に指定する必要があります。
  • expose_headers-ブラウザがアクセスできるようにする任意の応答ヘッダーを示します。デフォルトは [] です。
  • max_age-ブラウザキャッシュのCORS応答の最大時間を秒単位で設定します。デフォルトは 600 です。

ミドルウェアは、2つの特定のタイプのHTTPリクエストに応答します

クロスドメインリソース共有(CORS)プリチェックリクエスト

これらは、Origin と Access-Control-Request-Method ヘッダーを持つ OPTIONS リクエストです。この場合、ミドルウェアは着信リクエストを傍受し、適切なCORSヘッダーを使用して応答し、情報目的で200または400の応答を行います。

シンプルなリクエスト

Origin ヘッダーを持つリクエスト。この場合、ミドルウェアは通常どおりリクエストを渡しますが、適切なCORSヘッダーをレスポンスに含めます。

セッションミドルウェア

署名されたCookieに基づくHTTPセッションを追加します。セッション情報は読み取り可能ですが、変更できません。

request.session 辞書インターフェイスを使用してセッションデータにアクセスまたは変更します。

次の議論が支持されました。

  • secret_key -ランダムな文字列である必要があります。
  • session_cookie -デフォルト値は「セッション」です。
  • max_age-セッションの有効期限(秒)。デフォルトは2週間です。None に設定すると、Cookieの有効期限はブラウザのセッションの有効期限と同じになります。
  • same_site-SameSiteフラグは、クロスサイトリクエスト時にブラウザがセッションCookieを送信するのを防ぎます。デフォルト値は 'lax' です。
  • path-セッションCookieに設定されたパス。デフォルトは '/' です。
  • https_only -セキュリティフラグ(HTTPSでのみ使用可能)を設定する必要があることを示します。デフォルトは False 。
  • domain ・サブドメインまたはクロスドメイン間でCookieを共有するために使用されるCookieドメイン。ブラウザは、Cookieが設定されているホストと同じホストにドメインをデフォルトで設定し、サブドメインを除外します(参照)。

    Starlette. applicationからStarletteをインポート ミドルウェアのインポート starletteからSession Middlewareをインポート

    ルート=.。。

    ミドルウェア=[ ミドルウェア(Session Middleware, secret_key=.。。, http_only=True) ]

    アプリ=Starlette(ルート=ルート、middleware=middleware)

HTTPSリダイレクトミドルウェア

すべての着信要求を強制するには https または wss 。任意の着信 http または ws の要求は、セキュリティシナリオにリダイレクトされます。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからインポートします。HTTPSRedirectMiddleware

ルート=.。。

ミドルウェア=[
    ミドルウェア(HTTPSRedirectMiddleware)
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

このミドルウェアクラスには、構成オプションはありません。

信頼できるホストミドルウェア

HTTPホストヘッダー攻撃を防ぐために、すべての着信リクエストに適切に設定された Host ヘッダーを強制します。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starlette.ミドルウェア. trustedhostからインポートTrustedHostMiddleware

ルート=.。。

ミドルウェア=[
    ミドルウェア(TrustedHostMiddleware、割り当てられたホスト=['example.com','*.example.com'])
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

次の議論が支持されました。

  • allowed_hosts-ホスト名として許可されるべきドメイン名のリスト。*.example.com のようなワイルドカードドメイン名は、サブドメインのマッチングに使用できます。任意のホスト名を許可するには、allowed_hosts=["*"] を使用するか、ミドルウェアを省略します。
  • www_redirect-Trueに設定すると、www以外のバージョンのホストを許可するリクエストは、wwwに対応するバージョンにリダイレクトされます。デフォルトは True です。

着信要求が正しく検証されない場合、400応答が送信されます。

GZipミドルウェア

Accept-Encoding ヘッダに "gzip" を含むリクエストに対するGZipレスポンスを処理します。

ミドルウェアは、標準応答とストリーム応答を処理します。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからGZipMiddlewareをインポート


ルート=.。。

ミドルウェア=[
    ミドルウェア(GZipMiddleware、最小サイズ=1000、圧縮レベル=9)
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

次の議論が支持されました。

  • minimum_size-この最小バイトサイズより小さいレスポンスの場合、GZip圧縮を行わないでください。デフォルトは 500 です。
  • compresslevel-GZip圧縮時に使用します。1から9までの整数です。デフォルト値は 9 です。値が低いほど圧縮速度は速くなりますが、ファイルサイズは大きくなります。値が高いほど圧縮速度は遅くなりますが、ファイルサイズは小さくなります。

ミドルウェアは、Content-Encoding が設定されているレスポンスをGZip圧縮せず、2回エンコードされないようにします。

BaseHTTPミドルウェア

リクエスト/レスポンスインターフェイス用のAS GIミドルウェアを記述できる抽象クラス。

使用状況

BaseHTTPMiddleware を使用してミドルウェアクラスを実装するには、async def dispatch(request, call_next) メソッドをオーバーライドする必要があります。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからBaseHTTPMiddlewareをインポート


クラスCustomHeaderMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request,call_next):
        response=await call_next(リクエスト)
        response. header['カスタム']='例'
        応答を返す

ルート=.。。

ミドルウェア=[
    ミドルウェア(CustomHeaderMiddleware)
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

ミドルウェアクラスに設定オプションを提供したい場合は、__init__ メソッドを書き換えて、最初の引数が app で、残りの引数が任意のキーワード引数であることを確認する必要があります。そうする場合は、app プロパティがインスタンスに設定されていることを確認してください。

クラスCustomHeaderMiddleware(BaseHTTPMiddleware):
    def__in it__(self, app,header_value='example'):
        super().__in it__(アプリ)
        self. header_value=ヘッダー値

    async def dispatch(self, request,call_next):
        response=await call_next(リクエスト)
        response. header['カスタム']=self.header_value
        応答を返す


ミドルウェア=[
    ミドルウェア(CustomHeaderMiddleware、header_value='Customized')
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

ミドルウェアクラスは、__init__ メソッドの外部で状態を変更しないでください。代わりに、ミドルウェアインスタンスの状態を変更するのではなく、任意の状態を dispatch メソッドのローカルに保持するか、明示的に渡す必要があります。

制限

現在、BaseHTTPMiddleware にはいくつかの既知の制限があります。

  • BaseHTTPMiddleware を使用すると、contextlib.ContextVar への変更が上向きに伝播するのを防ぎます。 つまり、エンドポイントに ContextVar の値を設定し、それをリレーから読み込もうとすると、エンドポイントに設定した値とは異なることがわかります(この動作の例については、このテストを参照してください)。

これらの制限を克服するには、次のように純粋なAS GIミドルウェアを使用します。

純粋なAS GIミドルウェア

AS GI仕様では、AS GIインターフェースを直接使用してAS GIミドルウェアを実装し、一連のAS GIアプリケーションとして、次のものを順番に呼び出すことができます。実際、Starletteに付属しているミドルウェアクラスはこのように実装されています。

この低レベルのアプローチは、動作の制御を強化し、フレームワークとサーバー間の相互運用性を強化します。また、BaseHTTPMiddleware の制限を克服します。

純粋なAS GIミドルウェアの作成

AS GIミドルウェアを作成する最も一般的な方法は、クラスを使用することです。

クラスASGIMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        待機self.app(スコープ、受信、送信)

上記のミドルウェアは最も基本的なAS GIミドルウェアです。コンストラクタに親AS GIアプリケーションを引数として受け取り、その親アプリケーションを呼び出す async __call__ メソッドを実装します。

asgi-cors のようないくつかの実装は、関数を使用して代替スタイルを使用します。

インポート関数ツール

def asgi_ミドルウェア():
    def asgi_デコレーター(アプリ):

        @funtools. wraps(アプリ)
        async def wrapped_app(scope,受信,送信):
            awaitアプリ(スコープ、受信、送信)

        returnラップされたアプリ

    return asgi_デコレータ

いずれにしても、AS GIミドルウェアは呼び出し可能なオブジェクトでなければならず、scope、receive、send の3つのパラメータを受け入れる必要があります。

  • scope は、接続に関する情報を保存する辞書です。 scope["type"] おそらく:
    • "http" HTTPリクエストに使用されます。
    • "websocket" WebSocket接続に使用されます。
    • "lifespan" AS GIのライフサイクルメッセージに使用されます。
  • receive と send は、AS GIサーバとAS GIイベントメッセージを交換するために使用できます。これについては、後述します。これらのメッセージのタイプと内容は、スコープのタイプによって異なります。詳細については、AS GI仕様を参照してください。

純粋なAS GIミドルウェアを使用する

純粋なAS GIミドルウェアは、他のミドルウェアと同様に使用できます。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート

from.ミドルウェアインポートASGIMiddleware

ルート=.。。

ミドルウェア=[
    ミドルウェア(ASGIMiddleware),
]

アプリ=Starlette(.。。,middleware=middleware)

ミドルウェアの使用も参照してください。

型コメント

ミドルウェアにコメントを追加するには、Starlette自体を使用するか、asgiref を使用するかの2つの方法があります。

  • Starletteの使用:ほとんどの一般的なユースケースに適用されます。

    starlette. typesからASGIApp、メッセージ、スコープ、受信、送信をインポート

    クラスASGIMiddleware: def__in it__(self, app:ASGIApp)->None: self.app=アプリ

    async def__call__(self, scope:スコープ,受信:受信,送信:送信)->なし:
        if scope["type"]!="http":
            return awaitself.app(スコープ、受信、送信)
    
        async def send_wrapper(message: Message)->None:
            #。。。何かをする
            メッセージを送る
    
        awaitself.app(scope,受信, send_wrapper)
    
  • は asgiref:を使用して、より厳格な型ヒントを実現します。

    ASGI 3 Application, ASGIReceiveCallable,ASGISendCallable,Scopeのインポート from asgiref. types ing import ASGIReceiveEvent,ASGISendEvent

    クラスASGIMiddleware: def__in it__(self, app:AS GI 3 Application)->None: self.app=アプリ

    async def__call__(self, scope:Scope,response:ASGIReceiveCallable,send:ASGISendCallable)->None:
        if scope["type"]!="http":
            待機self.app(スコープ、受信、送信)
            リターン
    
        async def send_wrapper(message: ASGISendEvent)->None:
            #。。。何かをする
            メッセージを送る
    
        return awaitself.app(スコープ、受信、送信_ラッパー)
    

共通モード

一部の要求のみを処理します

AS GIミドルウェアは、scope の内容に基づいて特定の動作を適用できます。

たとえば、HTTPリクエストのみを処理する場合は、次のように書くことができます

クラスASGIMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        if scope["type"]!="http":
            待機self.app(スコープ、受信、送信)
            リターン

        。。。#ここで何かしよう!

        待機self.app(スコープ、受信、送信)

同様に、WebSocketのミドルウェアのみが scope["type"] != "websocket" で保護されます。

ミドルウェアは、リクエストメソッド、URL、ヘッダーなどによってもパフォーマンスが異なる場合があります。

Starletteコンポーネントの再利用

Starletteは、AS GI scope、receive、および/または send パラメータを受け入れるいくつかのデータ構造を提供し、より高い抽象化レベルで作業できるようにします。このようなデータ構造には、Request、Headers、QueryParams、URL などがあります。

たとえば、Request をインスタンス化して、HTTPリクエストを簡単に確認できます。

インポートリクエスト

クラスASGIMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        if scope["type"]=="http":
            request=リクエスト(スコープ)
            。。。`request.method`、`request.url`、`request.headers` などを使用してください。

        待機self.app(スコープ、受信、送信)

応答を再利用することもできます。

熱心な応答を送信

接続を確認してください scope を使用すると、条件付きで異なるAS GIアプリケーションを呼び出すことができます。使用例としては、アプリケーションを呼び出さずにレスポンスを送信することが考えられます。

たとえば、このミドルウェアはディクショナリを使用して、要求されたパスに基づいて永続的なリダイレクトを実行します。ルートURLパターンをリファクタリングする必要がある場合は、これを使用してレガシーURLを継続的にサポートできます。

starletteからURLをインポート
starletteからRedirect Responseをインポート

class Redirect Middleware:リダイレクトミドルウェア
    def__in it__(self, app,path_マッピング:dict):
        self.app=アプリ
        パスマッピング

    async def__call__(self, scope,send,send):
        if scope["type"]!="http":
            待機self.app(スコープ、受信、送信)
            リターン

        url=URL(scope=scope)

        if url. path in self.path_マッピング:
            url=url. replace(path=self.path_map ing[url.path])
            response=Redirect Response(url, status_code=301)
            await応答(スコープ、受信、送信)
            リターン

        待機self.app(スコープ、受信、送信)

使用例は次のようになります。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート

ルート=.。。

リダイレクト={
    "/v 1/リソース/":"/v 2/リソース/",
    # ...
}

ミドルウェア=[
    ミドルウェア(Redirect Middleware, path_mapping=redirections),
]

アプリ=Starlette(ルート=ルート、middleware=middleware)

要求の確認または変更

リクエスト情報は、scope を操作することでアクセスまたは変更できます。このパターンの完全な例については、フロントエンドプロキシの背後でサービスを提供するときに scope をチェックして調整するUvicornの ProxyHeadersMiddleware を参照してください。

さらに、receive AS GI呼び出し可能オブジェクトをラップすると、http.request AS GIイベントメッセージを操作してHTTPリクエスト本文にアクセスまたは変更できます。

たとえば、このミドルウェアは、着信リクエストボディのサイズを計算して記録します

クラスLoggedRequestBodySizeMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        if scope["type"]!="http":
            待機self.app(スコープ、受信、送信)
            リターン

        ボディサイズ=0

        async def受信_ロギング_リクエスト_ボディ_サイズ():
            非ローカルボディサイズ

            メッセージ=受信を待つ()
            assert message["type"]=="http. request"

            body_size+=len(message. get("body",b""))

            if not message. get("more_body",False):
                print(f"リクエストボディのサイズは:{body_size}バイト")

            メッセージを返す

        awaitself.app(スコープ、受信_ロギング_リクエスト_ボディ_サイズ、送信)

同様に、WebSocketミドルウェアは websocket.receive AS GIイベントメッセージを操作して、着信WebSocketデータをチェックまたは変更できます。

HTTPリクエストの本文を変更する例については、msgpack-asgi を参照してください。

応答の確認または変更

send AS GI呼び出し可能オブジェクトをラップして、基盤となるアプリケーションが送信するHTTPレスポンスを確認または変更できるようにします。これを行うには、http.response.start または http.response.body AS GIイベントメッセージに応答します。

たとえば、このミドルウェアには、いくつかの固定された追加の応答ヘッダーが追加されます。

starletteからMutableHeadersをインポート

クラスExtraResponseHeadersMiddleware:
    def__in it__(self, app,header ers):
        self.app=アプリ
        self. headers=ヘッダー

    async def__call__(self, scope,send,send):
        if scope["type"]!="http":
            return awaitself.app(スコープ、受信、送信)

        async def send_with_extra_headers(message):
            if message["type"]=="http. response.start":
                headers=MutableHeaders(scope=message)
                for key, value in self.header:
                    header. append(キー,値)

            メッセージを送る

        awaitself.app(scope,受信, send_with_extra_header)

HTTPレスポンスをチェックし、構成可能なHTTPアクセスログ行を記録する例を示す asgi-logger も参照してください。

同様に、WebSocketミドルウェアは websocket.send AS GIイベントメッセージを操作して、送信されたWebSocketデータをチェックまたは変更できます。

レスポンス本文を変更する場合は、新しいレスポンス本文の長さに合わせてレスポンス Content-Length ヘッダーを更新する必要があることに注意してください。完全な例については、brotli-asgi を参照してください。

エンドポイントに情報を渡す

ベースアプリケーションやエンドポイントと情報を共有する必要がある場合は、scope ディクショナリに保存できます。これは慣習です。たとえば、Starletteはこの方法を使用してルート情報をエンドポイントと共有しますが、AS GI仕様の一部ではありません。 そうする場合は、競合を避けるために他のミドルウェアやアプリケーションが使用する可能性が低いキーを使用するようにしてください。

例えば、以下のようなミドルウェアが含まれている場合、エンドポイントは request.scope["asgi_transaction_id"] にアクセスできるようになります。

uuidをインポート

クラスTransactionIDMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        scope["asgi_trade_id"]=uuid. uuid 4()
        待機self.app(スコープ、受信、送信)

クリーンアップとエラー処理

アプリケーションを try/except/finally ブロックまたはコンテキストマネージャにラップして、クリーンアップ操作やエラー処理を実行できます。

たとえば、次のミドルウェアはメトリックを収集し、アプリケーションの例外を処理する可能性があります

インポート時間

クラスMonitoringMiddleware:
    def__in it__(self, app):
        self.app=アプリ

    async def__call__(self, scope,send,send):
        start=time. time()
        トライ:
            待機self.app(スコープ、受信、送信)
        excとして例外を除く:
            。。。#例外を処理する
            レイズ
        最後に:
            end=time. time()
            elapsed=終了-開始
            。。。#`elapsed` をメトリックとして監視バックエンドに送信する

このパターンの完全な例については、timing-asgi も参照してください。

潜在的な問題

AS GIミドルウェアはステートレスであるべきです

AS GIは同時リクエストを処理するように設計されているため、接続に固有の状態は __call__ 実装に限定する必要があります。そうしないと、通常、リクエスト間の変数の読み取り/書き込みの競合が発生し、エラーが発生する可能性が高くなります。

たとえば、応答に X-Mock ヘッダーがある場合、この操作は条件付きで応答本文を置き換えます

✅ やる

```python
from starlette.datastructures import Headers

class MockResponseBodyMiddleware:
    def __init__(self, app, content):
        self.app = app
        self.content = content

    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        # A flag that we will turn `True` if the HTTP response
        # has the 'X-Mock' header.
        # ✅: Scoped to this function.
        should_mock = False

        async def maybe_send_with_mock_content(message):
            nonlocal should_mock

            if message["type"] == "http.response.start":
                headers = Headers(raw=message["headers"])
                should_mock = headers.get("X-Mock") == "1"
                await send(message)

            elif message["type"] == "http.response.body":
                if should_mock:
                    message = {"type": "http.response.body", "body": self.content}
                await send(message)

        await self.app(scope, receive, maybe_send_with_mock_content)
```

❌ いいえ

```python hl_lines="7-8"
from starlette.datastructures import Headers

class MockResponseBodyMiddleware:
    def __init__(self, app, content):
        self.app = app
        self.content = content
        # ❌: This variable would be read and written across requests!
        self.should_mock = False

    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        async def maybe_send_with_mock_content(message):
            if message["type"] == "http.response.start":
                headers = Headers(raw=message["headers"])
                self.should_mock = headers.get("X-Mock") == "1"
                await send(message)

            elif message["type"] == "http.response.body":
                if self.should_mock:
                    message = {"type": "http.response.body", "body": self.content}
                await send(message)

        await self.app(scope, receive, maybe_send_with_mock_content)
```

この潜在的な問題を解決する完全な実装例については、GZipMiddleware も参照してください。

さらに読む

このドキュメントは、AS GIミドルウェアを作成する方法の良い基礎として十分である必要があります。

しかし、このトピックに関する優れた記事がたくさんあります。

他のフレームワークでミドルウェアを使用する

AS GIミドルウェアを他のAS GIアプリケーションの周りにラップするには、アプリケーションインスタンスをラップするためのより一般的なスキーマを使用する必要があります。

app=TrustedHostMiddleware(app、割り当てられたホスト=['example.com'])

これはStarletteアプリケーションインスタンスでも実行できますが、middleware=<List of Middleware instances> スタイルを使用することをお勧めします。

  • は、すべてが最も外側の ServerErrorMiddleware に包まれていることを確認します。
  • は最上位の app インスタンスを保持します。

ミドルウェアをルーティンググループに適用する

ミドルウェアを Mount インスタンスに追加することもできます。これにより、ミドルウェアを一連のルーティングまたはサブアプリケーションに適用できます。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからGZipMiddlewareをインポート
from starlette. routing importマウント,ルート


ルート=[
    マウント(
        "/",
        ルート=[
            ルート(
                "/example",
                エンドポイント=.。。、
            )
        ],
        ミドルウェア=[ミドルウェア(GZipMiddleware)]
    )
]

app=Starlette(ルート=ルート)

この方法で使用されるミドルウェアは、Starlette アプリケーションに適用されるミドルウェアのように例外処理ミドルウェアに包まれていないことに注意してください。 これは通常、Response のミドルウェアをチェックまたは修正するためにのみ機能するため、問題ではありません。それでも、このロジックをエラーレスポンスに適用したくない場合があります。ミドルウェアロジックを特定のルートでのみエラーレスポンスに適用したい場合は、いくつかのオプションがあります。

  • Mount に ExceptionMiddleware を追加します
  • ミドルウェアに try/except ブロックを追加し、そこからエラー応答を返します
  • はタグ付けと処理を2つのミドルウェアに分割します。1つは Mount に配置され、応答は処理が必要であるとマークされます(たとえば、scope["log-response"] = True を設定することによって)。もう1つは Starlette アプリケーションに適用されます。

Route/WebSocket クラスは、単一のルートにミドルウェアを適用できる middleware パラメーターも受け取ります。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからGZipMiddlewareをインポート
from starlette. routingインポートルート


ルート=[
    ルート(
        "/example",
        エンドポイント=.。。、
        ミドルウェア=[ミドルウェア(GZipMiddleware)]
    )
]

app=Starlette(ルート=ルート)

ミドルウェアを Router クラスに適用することもできます。

Starlette. applicationからStarletteをインポート
ミドルウェアのインポート
starletteからGZipMiddlewareをインポート
from starlette. routing importルート、ルーター


ルート=[
    Route("/example", endpoint=.。。)、
    Route("/an other", endpoint=.。。)、
]

router=ルータ(ルート=ルート、ミドルウェア=[ミドルウェア(GZipMiddleware)])

サードパーティ製ミドルウェア

asgi-auth-ギットハブ)

このミドルウェアは、任意のAS GIアプリケーションに認証を追加し、ユーザーがGitHubアカウントを使用して(OAuth経由で)ログインすることを要求します。アクセス権は、特定のユーザーまたは特定のGitHub組織またはチームのメンバーに制限できます。

asgi-csrfについて

CS RF攻撃から保護するためのミドルウェア。このミドルウェアは、Cookieが設定され、csrftokenの非表示フォームフィールドまたは x-csrftoken HTTPヘッダーと比較されるダブルコミットCookieパターンを実装します。

Authlibミドルウェア

Starletteセッションミドルウェアの直接的な代替品で、Authlibのjwtモジュールを使用しています。

Bugsnagミドルウェア

例外をBugsnagに記録するためのミドルウェアクラス。

CS RFミドルウェア

CS RF攻撃から保護するためのミドルウェア。このミドルウェアは、Cookieを設定し、それを x-csrftoken HTTPヘッダーと比較するダブルコミットCookieパターンを実装します。

初期のデータミドルウェア

TLSv 1.3の初期のデータ要求を検出および拒否するためのミドルウェアおよびデコレータ。

プロメテウスミドルウェア

進行中のリクエスト、時間など、リクエストとレスポンスに関連するPrometheusメトリックをキャプチャするためのミドルウェアクラス

プロキシヘッダーミドルウェア

Uvicornには、プロキシサーバーを使用するときに X-Forwarded-Proto と X-Forwarded-For ヘッダーからクライアントのIPアドレスを決定するためのミドルウェアクラスが含まれています。より複雑なプロキシ構成の場合は、このミドルウェアを調整する必要があります。

速度制限ミドルウェア

速度制限ミドルウェア。正規表現一致するURL、柔軟なルール、高度にカスタマイズ可能。非常に使いやすい。

RequestIdミドルウェア

リクエストIDを読み込んだり生成したりしてアプリケーションログにアタッチするためのミドルウェアクラス。

ロールバーミドルウェア

例外、エラー、ログメッセージをRollbarに記録するためのミドルウェアクラス。

StarletteOpentracing

OpenTracing.ioと互換性のあるトラッカーに追跡情報を送信し、分散アプリケーションの分析と監視に使用できるミドルウェアクラス。

セキュリティクッキーミドルウェア

Starletteアプリケーションに自動Cookie暗号化と復号化を追加するためのカスタマイズ可能なミドルウェアで、既存のCookieベースのミドルウェアをさらにサポートします。

タイミングミドルウェア

通過するリクエストごとにタイミング情報(CPU時間と壁掛け時計時間)を発行するためのミドルウェアクラス。これらのタイミングをstatsdインジケータとして発行する方法の例が含まれています。

WSGIMiddleware

WS GIアプリケーションをAS GIアプリケーションに変換するミドルウェアクラス。