カスタムロジックの実装
注 :この章は、Luaに精通していることを前提と しています。
Kong Gatewayプラグインを使うと、Kong Gatewayでプロキシされる
リクエスト/レスポンスまたはTCPストリーム接続のライフサイクルにおいて、
いくつかのエントリポイントでカスタムロジックを(Luaに)注入できます。そのためには、ファイル
kong.plugins.<plugin_name id="sl-md0000000">.handler
は、1つ以上のあらかじめ決められた
名前の関数のテーブルを返さなければなりません。この関数はトラフィックを
処理するときに、様々なフェーズでKong Gatewayによって呼び出されます。
最初に取るパラメータは常にself
です。init_worker
とconfigure
を除く
すべての関数は、プラグイン構成を含むテーブルという第2のパラメータを
受け取ることができます。configure
は特定のプラグインに関するすべての構成の配列を
受け取ります。
モジュール
kong.plugins.<plugin_name id="sl-md0000000">.handler
使用可能なコンテキスト
handler.lua
ファイルで次のいずれかの関数を定義すると、Kong Gateway の実行ライフサイクルのさまざまなエントリポイントにカスタムロジックが実装されます。
-
HTTPモジュール は、HTTP/HTTPSリクエスト用に記述されるプラグインで使用されます | Function name | Kong Phase | Nginx Directives | Request Protocol | Description
|——-|——-|——-|——-|——- |
|
init_worker
|init_worker
|init_worker_by_*
| * | Executed upon every Nginx worker process’s startup. |configure
|init_worker
/timer
|init_worker_by_*
| * | Executed every time the Kong plugin iterator is rebuilt (after changes to configure plugins). |certificate
|certificate
|ssl_certificate_by_*
|https
,grpcs
,wss
| Executed during the SSL certificate serving phase of the SSL handshake. |rewrite
|rewrite
|rewrite_by_*
| * | Executed for every request upon its reception from a client as a rewrite phase handler.
In this phase, neither theService
nor theConsumer
have been identified, hence this handler will only be executed if the plugin was configured as a global plugin. |access
|access
|access_by_*
|http(s)
,grpc(s)
,ws(s)
| Executed for every request from a client and before it is being proxied to the upstream service. |response
|response
|header_filter_by_*
,body_filter_by_*
|http(s)
,grpc(s)
| Replaces bothheader_filter()
andbody_filter()
. Executed after the whole response has been received from the upstream service, but before sending any part of it to the client. |header_filter
|header_filter
|header_filter_by_*
|http(s)
,grpc(s)
| Executed when all response headers bytes have been received from the upstream service. |body_filter
|body_filter
|body_filter_by_*
|http(s)
,grpc(s)
| Executed for each chunk of the response body received from the upstream service. Since the response is streamed back to the client, it can exceed the buffer size and be streamed chunk by chunk. This function can be called multiple times if the response is large. See the lua-nginx-module documentation for more details. |ws_handshake
|ws_handshake
|access_by_*
|ws(s)
| Executed for every request to a WebSocket service just before completing the WebSocket handshake. |ws_client_frame
|ws_client_frame
|content_by_*
|ws(s)
| Executed for each WebSocket message received from the client. |ws_upstream_frame
|ws_upstream_frame
|content_by_*
|ws(s)
| Executed for each WebSocket message received from the upstream service. |log
|log
|log_by_*
|http(s)
,grpc(s)
| Executed when the last response byte has been sent to the client. |ws_close
|ws_close
|log_by_*
|ws(s)
| Executed after the WebSocket connection has been terminated.
注: モジュールが
response
関数を実装している場合、kong.service.request.enable_buffering()
関数が呼び出されているため、Kong Gatewayは自動的に「バッファリングされたプロキシ」モードをアクティブにします。現在のNginxの制限により、これはHTTP/2またはgRPCアップストリームでは機能しません。
予期しない動作変更を減らすため、プラグインが response
と header_filter
または body_filter
の両方を実装している場合、Kong Gateway は起動しません。
- ストリームモジュール は、TCPおよびUDPストリーム接続用に記述されたプラグインに使用されます
機能名 | Kong Phase | Nginx Directives | 説明 |
---|---|---|---|
init_worker |
init_worker |
init_worker_by_* |
すべてのNginxワーカープロセスの起動時に実行されます。 |
configure |
init_worker /timer
|
init_worker_by_* |
Kongプラグインイテレータが再構築されるたびに(プラグイン構成の変更後に)実行されます。 |
preread |
preread |
preread_by_* |
接続ごとに 1 回実行されます。 |
log |
log |
log_by_* |
接続が閉じられた後、接続ごとに 1 回実行されます。 |
certificate |
certificate |
ssl_certificate_by_* |
SSLハンドシェイクのSSL証明書提供フェーズ中に実行されます。 |
init_worker
と configure
を除くすべての関数は、Kong Gateway の呼び出し時に指定されたパラメータ(プラグインの構成)を受け取ります。このパラメータは Lua テーブルであり、プラグインのスキーマ(schema.lua
モジュールに記述)に従ってユーザーが定義した値が含まれます。プラグインのスキーマについて、次の章で詳しく説明します。configure
は、特定のプラグインで有効になっているすべてのプラグイン構成の配列で呼び出されます(プラグインのアクティブな構成がない場合は、nil
が渡されます)。init_worker
と configure
はリクエストまたはフレームの外側で実行されますが、残りのフェーズは受信したリクエストやフレームにバインドされます。
UDP ストリームには実際の接続がないことに注意してください。Kong Gateway は
同一の起点、宛先のホストとポートを持つ全パケットを単一接続
とみなします。パケットがない状態が設定可能な時間経過すると、接続は
閉じられたとみなされ、 log
関数が実行されます。
configure
ハンドラはKong 3.5で追加され、3.4 LTSにバックポートされました。現在、この新しいフェーズに対するフィードバックを求めており、その署名が将来変更される可能性がわずかにあります。
handler.luaの仕様書
Kong Gateway はリクエストを フェーズ で処理します。プラグインは、リクエストがプロキシされている間に各フェーズが実行されるときに、Kong Gateway によってアクティブ化されるコードです。
フェーズでできることは限定されています。たとえば、init_worker
フェーズは config
パラメータにアクセスできません。これは、kong が各ワーカーを初期化しているときにその情報が利用できないためです。一方、configure
にはプラグインのすべてのアクティブな構成が渡されます(設定されていない場合はnil
)。
プラグインの handler.lua
は、各フェーズで実行する必要がある関数を含むテーブルを返す必要があります。
Kong Gateway HTTP およびストリーム トラフィックを処理できます。フェーズには、
HTTPトラフィックを処理するときのみ実行されるもの、ストリームを処理するときに実行されるもの、
また、init_worker
やlog
などのように、両種のトラフィックによって呼び出されるものがあります。
関数に加えて、プラグインは次の2つのフィールドを定義する必要があります。
-
VERSION
情報フィールドであり、 Kong Gatewayによって直接使用されるものではありません。通常の場合、 プラグインのRockspecバージョンで定義されているバージョン(存在する場合)と一致します。 -
PRIORITY
各フェーズを実行する前にプラグインをソートするために使用されます。 優先度の高いプラグインが最初に実行されます。このフィールドの詳細については、下記の プラグイン実行の順序を参照してください。
次のサンプルファイル、handler.lua
は、HTTPとストリームトラフィックの両方で使用可能なすべてのフェーズでカスタム関数を定義します。このファイルには、フェーズが呼び出されるたびにログにメッセージを記述する以外の機能はありません。
注
プラグインはすべてのフェーズに機能を提供する必要はありません。
local CustomHandler = {
VERSION = "1.0.0",
PRIORITY = 10,
}
function CustomHandler:init_worker()
-- Implement logic for the init_worker phase here (http/stream)
kong.log("init_worker")
end
function CustomHandler:configure(configs)
-- Implement logic for the configure phase here
--(called whenever there is change to any of the plugins)
kong.log("configure")
end
function CustomHandler:preread(config)
-- Implement logic for the preread phase here (stream)
kong.log("preread")
end
function CustomHandler:certificate(config)
-- Implement logic for the certificate phase here (http/stream)
kong.log("certificate")
end
function CustomHandler:rewrite(config)
-- Implement logic for the rewrite phase here (http)
kong.log("rewrite")
end
function CustomHandler:access(config)
-- Implement logic for the access phase here (http)
kong.log("access")
end
function CustomHandler:ws_handshake(config)
-- Implement logic for the WebSocket handshake here
kong.log("ws_handshake")
end
function CustomHandler:header_filter(config)
-- Implement logic for the header_filter phase here (http)
kong.log("header_filter")
end
function CustomHandler:ws_client_frame(config)
-- Implement logic for WebSocket client messages here
kong.log("ws_client_frame")
end
function CustomHandler:ws_upstream_frame(config)
-- Implement logic for WebSocket upstream messages here
kong.log("ws_upstream_frame")
end
function CustomHandler:body_filter(config)
-- Implement logic for the body_filter phase here (http)
kong.log("body_filter")
end
function CustomHandler:log(config)
-- Implement logic for the log phase here (http/stream)
kong.log("log")
end
function CustomHandler:ws_close(config)
-- Implement logic for WebSocket post-connection here
kong.log("ws_close")
end
-- return the created table, so that Kong can execute it
return CustomHandler
上記の例では、最初のパラメータとしてself
を取る関数に関して、Luaの:
短縮構文を使用していることに注意してください。access
関数の同等な非省略形バージョンは次のようになります。
function CustomHandler.access(self, config)
-- Implement logic for the access phase here (http)
kong.log("access")
end
プラグインのロジックをすべてhandler.lua
ファイル内で定義する必要はありません。
これは複数のLuaファイル( モジュール とも呼ばれます)に分割できます。
handler.lua
モジュールはrequire
を使用して、プラグインに他のモジュールを含めることができます。
たとえば、次のプラグインは機能を3つのファイルに分割します。
access.lua
とbody_filter.lua
は関数を返します。これらはhandler.lua
と
同じフォルダー内にあり、プラグインの構築に必要で、使用します。
-- handler.lua
local access = require "kong.plugins.my-custom-plugin.access"
local body_filter = require "kong.plugins.my-custom-plugin.body_filter"
local CustomHandler = {
VERSION = "1.0.0",
PRIORITY = 10
}
CustomHandler.access = access
CustomHandler.body_filter = body_filter
return CustomHandler
-- access.lua
return function(self, config)
kong.log("access phase")
end
-- body_filter.lua
return function(self, config)
kong.log("body_filter phase")
end
実際のハンドラーコードの例については、Key-Authプラグインのソースコード を参照してください。
BasePlugin モジュールからの移行
BasePlugin
モジュールは非推奨となり、
Kong Gateway から削除されました。このモジュールを使用する古いプラグインがある場合は、次のセクションを置き換えます。
-- DEPRECATED --
local BasePlugin = require "kong.plugins.base_plugin"
local CustomHandler = BasePlugin:extend()
CustomHandler.VERSION = "1.0.0"
CustomHandler.PRIORITY = 10
現在の同等のもの:
local CustomHandler = {
VERSION = "1.0.0",
PRIORITY = 10,
}
:new()
メソッドを追加したり、任意のCustomHandler.super.XXX:(self)
メソッドを呼び出したりする必要はありません。
WebSocketプラグイン開発
ハンドラ関数
ws
またはwss
プロトコルを使用するサービスへのハンドラ関数のリクエストは、通常のhttpリクエストとは異なるパスをプロキシ経由で経由します。したがって、それらのプラグインを開発する際に考慮しなければならない動作にはいくつかの違いがあります。
次のハンドラはWebSocketサービスでは実行 されません 。
access
response
header_filter
body_filter
log
以下のハンドラは WebSocket サービスに 固有の ハンドラです。
ws_handshake
ws_client_frame
ws_upstream_frame
ws_close
以下のハンドラは、WebSocket サービス と 非 WebSocket サービスの両方で実行されます。
-
init_worker
*configure
*certificate
(TLS/SSLリクエストのみ) rewrite
これらの違いがあっても、WebSocketサービスと非WebSocketサービスの両方をサポートするプラグインを開発することは可能です。以下に例を示します。
-- handler.lua
--
-- I am a plugin that implements both WebSocket and non-WebSocket handlers.
--
-- I can be enabled for ws/wss services, http/https/grpc/grpcs services, or
-- even as global plugin.
local MultiProtoHandler = {
VERSION = "0.1.0",
PRIORITY = 1000,
}
function MultiProtoHandler:access()
kong.ctx.plugin.request_type = "non-WebSocket"
end
function MultiProtoHandler:ws_handshake()
kong.ctx.plugin.request_type = "WebSocket"
end
function MultiProtoHandler:log()
kong.log("finishing ", kong.ctx.plugin.request_type, " request")
end
-- the `ws_close` handler for this plugin does not implement any WebSocket-specific
-- business logic, so it can simply be aliased to the `log` handler
MultiProtoHandler.ws_close = MultiProtoHandler.log
return MultiProtoHandler
上記のように、 log
ハンドラーとws_close
ハンドラーは互いに並行しています。多くの場合、
追加コードを書かずに一方を他方に
エイリアス化することができます。この点に関してはaccess
とws_handshake
ハンドラも非常に
よく似ています。注目すべき違いは、それぞれの文脈においてどのPDK機能が利用可能か、
または利用できないかという点です。たとえば、 kong.request.get_body()
PDK関数は
access
ハンドラでは基本的にこの種のリクエストのと互換性がないため
使用しないでください。
非WebSocketサービスへのWebSocketリクエスト
WebSocketトラフィックは、http/httpsサービス経由でプロキシされる場合には非WebSocketリクエストとして扱われます。
そのため、httpハンドラ(access
、header_filter
など)が実行され、WebSocketハンドラ(ws_handshake
、ws_close
など)は実行 されません 。
プラグイン開発キット
これらのフェーズで実装されるロジックは、リクエスト/応答オブジェクトやコアコンポーネントと相互作用しなければならない可能性が高いです(例:キャッシュやデータベースにアクセスするなど)。Kong Gatewayは、このようなプラグイン開発キット(または「PDK」)を提供します。 それは、プラグインが様々なゲートウェイ操作を実行するために使用できるLua関数および変数のセットと、Kong Gateway の将来のリリースとの互換性が保証されているためです。
Kong Gatewayとやりとりする必要があるロジックを実装しようとしている場合 (例えば、リクエストヘッダーの取得、プラグインからのレスポンスの生成、 いくつかのエラーまたはデバッグ情報のロギングなど)については、プラグイン開発キットリファレンスにご相談ください。
プラグインの実行順序
一部のプラグインは、一部の操作を実行するために他のプラグインの実行に依存する場合があります。たとえば、コンシューマの ID に依存するプラグインは、認証プラグインの 後 に実行する必要があります。これを考慮し、Kong Gateway はプラグインの実行間の 優先順位 を定義して、順序が尊重されるようにします。
プラグインの優先順位は、返されたハンドラテーブルで番号を受け入れるプロパティを 経由して、設定することができます。
CustomHandler.PRIORITY = 10
優先度が高ければ高いほど、他のプラグインのフェーズに対して、お使いのプラグインのフェーズがより早く実行されます
( :access()
、:log()
など)。
Kong プラグイン
Kong Gateway にバンドルされているすべてのプラグインには静的優先順位があります。
これは、ordering
オプションを使用して動的に調整できます。詳細については、プラグインの動的順序付けを参照してください。