# Middleware
リスナーではワーカー・プロセスのライフサイクルに機能を付加できますが、ミドルウェアではHTTPストリームのライフサイクルに機能を付加できます。
ミドルウェアを実行するには、_before_ハンドラを実行するか_after_を実行します。
# Attaching middleware
これはもう見慣れたものになっているはずです。必要なのは、 「リクエスト」 または 「レスポンス」 のどちらでミドルウェアを実行するかを宣言することだけです。
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
app.register_middleware(extract_user, "request")
ここでも、Sanic
アプリインスタンスには便利なデコレーターもある。
@app.middleware("request")
async def extract_user(request):
request.ctx.user = await extract_user_from_request(request)
レスポンス・ミドルウェアはrequest
とresponse
の両方の引数を受け取ります。
@app.middleware('response')
async def prevent_xss(request, response):
response.headers["x-xss-protection"] = "1; mode=block"
デコレーターをさらに短くすることができます。これは、オートコンプリート機能を備えたIDEがある場合に便利です。
@app.on_request
async def extract_user(request):
...
@app.on_response
async def prevent_xss(request, response):
...
# Modification
ミドルウェアは、_を返さない限り、指定されたリクエストまたはレスポンス・パラメータを変更できます。
# Order of execution
- Request middleware:
add_key
- Route handler:
index
- Response middleware:
prevent_xss
- Response middleware:
custom_banner
@app.middleware("request")
async def add_key(request):
# Arbitrary data may be stored in request context:
request.ctx.foo = "bar"
@app.middleware("response")
async def custom_banner(request, response):
response.headers["Server"] = "Fake-Server"
@app.middleware("response")
async def prevent_xss(request, response):
response.headers["x-xss-protection"] = "1; mode=block"
@app.get("/")
async def index(request):
return text(request.ctx.foo)
request.match_info
を変更できます。たとえば、ミドルウェアでa-slug
をa_slug
に変換するために使用できる便利な機能。
@app.on_request
def convert_slug_to_underscore(request: Request):
request._match_info["slug"] = request._match_info["slug"].replace("-", "_")
@app.get("/<slug:[a-z0-9]+(?:-[a-z0-9]+)*>")
async def handler(request, slug):
return text(slug)
$ curl localhost:9999/foo-bar-baz
foo_bar_baz
# Responding early
ミドルウェアがHTTPResponse
オブジェクトを返す場合、リクエストは処理を停止し、レスポンスが返されます。これがルートハンドラに到達する前のリクエストで発生した場合、ハンドラはnot呼び出されます。レスポンスを返すと、それ以降のミドルウェアの実行も妨げられます。
TIP
None
値を返すと、ミドルウェアハンドラの実行を停止して、リクエストを通常どおりに処理できます。これは、アーリー・リターンを使用して、そのミドルウェア・ハンドラー内の要求の処理を回避する場合に便利です。
@app.middleware("request")
async def halt_request(request):
return text("I halted the request")
@app.middleware("response")
async def halt_response(request, response):
return text("I halted the response")
# Order of execution
リクエスト・ミドルウェアは、宣言された順序で実行されます。レスポンス・ミドルウェアは、逆順で実行されます.
次の設定では、コンソールにこのメッセージが表示されます。
@app.middleware("request")
async def middleware_1(request):
print("middleware_1")
@app.middleware("request")
async def middleware_2(request):
print("middleware_2")
@app.middleware("response")
async def middleware_3(request, response):
print("middleware_3")
@app.middleware("response")
async def middleware_4(request, response):
print("middleware_4")
@app.get("/handler")
async def handler(request):
print("~ handler ~")
return text("Done.")
middleware_1
middleware_2
~ handler ~
middleware_4
middleware_3
[INFO][127.0.0.1:44788]: GET http://localhost:8000/handler 200 5