すべてのプロダクト
Search
ドキュメントセンター

Microservices Engine:Lua プラグインの使用

最終更新日:Jun 21, 2026

Lua は軽量で高効率なスクリプト言語です。ゲートウェイ開発において、Lua は API ゲートウェイ、メッセージゲートウェイ、リバースプロキシなど、さまざまなゲートウェイプログラムの記述と実行に使用できます。開発者は Lua を使用して、リクエストルーティング、フィルタリング、認証のためのスクリプトを記述し、カスタマイズされた処理を実行できます。Lua は、NGINX や Envoy などのプロキシに組み込んで、リクエストとレスポンスの処理、ログ出力、その他のカスタマイズされた操作を行うことができます。このトピックでは、Lua を Envoy プロキシに組み込んでリクエストとレスポンスを処理し、そのヘッダーとボディをログに記録する方法について説明します。

制限事項

  • お使いの Microservices Engine (MSE) クラウドネイティブゲートウェイのバージョンは 1.2.11 以降である必要があります。

  • セキュリティ上の理由から、MSE では、デフォルトで以下の Lua ライブラリと関数が無効になっています。

    • debug.debug

    • debug.getfenv

    • debug.getregistry

    • dofile

    • io

    • loadfile

    • os.execute

    • os.getenv

    • os.remove

    • os.rename

    • os.tmpname

ルーティングルールの設定

  1. MSE コンソールにログオンし、上部のナビゲーションバーでリージョンを選択します。

  2. 左側のナビゲーション ウィンドウで、Cloud-Native Gateway > ゲートウェイリスト を選択します。 [ゲートウェイ] ページで、ゲートウェイの名前をクリックします。

  3. [ゲートウェイの詳細] ページの左側のナビゲーションウィンドウで、Plug-in Marketplace をクリックします。

  4. All Plug-ins タブで、Custom タブをクリックし、次に [lua] リソースカードをクリックします。

  5. Plug-in Configuration タブで、ルールレベルを選択し、次のように設定します。

    説明

    ゲートウェイが受信したすべてのリクエストは、ルートレベルのプラグインルール → ドメインレベルのプラグインルール → インスタンスレベルのプラグインルールという優先順位でプラグインルールにマッチします。

    ルートレベルのプラグインルール

    1. Add Rule をクリックします。表示されたページで、ルールを有効にしてターゲットルートを選択し、[ルールを設定] エディターに Lua スクリプトを入力します。

    2. OK をクリックします。

    ドメインレベルのプラグインルール

    1. Add Rule をクリックします。表示されたページで、ルールを有効にし、ターゲットドメインを選択してから、[ルールの設定] エディターに Lua スクリプトを入力します。

      重要

      アスタリスク (*) を含むドメイン名は、Lua プラグインルールではサポートされていません。

    2. OK をクリックします。

    インスタンスレベルのプラグインルール

    Lua プラグインには、デフォルトでインスタンスレベルのプラグインルールが設定されています。ルールを編集するには、まず編集ロックを解除する必要があります。

    1. スイッチをオンにして、[ルール設定] エディターに Lua スクリプトを入力します。

    2. 保存 をクリックします。

API リファレンス

クラウドネイティブゲートウェイが提供する Lua API の詳細については、「Lua」をご参照ください。

次のメソッドで JSON を使用できます。

  • JSON データのシリアル化:local json_str = json.encode(obj)

  • JSON データのデシリアル化:local obj = json.decode(json_str)

シリアル化またはデシリアル化中にエラーが発生した場合、Lua はエラー関数を呼び出してエラーを返し、現在のプロセスを終了します。

一般的なユースケース

プラグインログでの完全なリクエストとレスポンス情報の表示

  1. ルーティングルールを設定する際に、次の Lua コードを使用します。

    サンプルコードでは、次の content type のリクエストボディとレスポンスボディのみが表示されます。ボディサイズは 1,024 バイト (1 KB) を超えることはできません。

    • application/x-www-form-urlencoded

    • application/json

    • text/plain

    local maxBodySize = 1024
    function check_content_readable(type)
      if type == nil then
        return false
      end
      if string.find(type, "application/x-www-form-urlencoded",1,true) or string.find(type, "application/json",1,true) or string.find(type, "text/plain",1,true) then
         return true
      end
      return false
    end
    function envoy_on_request(request_handle)
      local headers = request_handle:headers()
      local headersStr = ""
      local contentType
      for key, value in pairs(headers) do
        if key == "content-type" then
           contentType = value
        end
        headersStr = headersStr  .. key .. "=" .. value .. ", "
      end
      request_handle:streamInfo():dynamicMetadata():set("envoy.lua","request_headers",headersStr)
      local requestBody = ""
      if check_content_readable(contentType) then
        for chunk in request_handle:bodyChunks() do
          if (chunk:length() > 0) then
            requestBody = requestBody .. chunk:getBytes(0, chunk:length())
          end
          if (#requestBody > maxBodySize) then
             requestBody = requestBody .. "<truncated>"
             break
          end
        end
      end
      request_handle:streamInfo():dynamicMetadata():set("envoy.lua","request_body",string.gsub(requestBody,"\n","\\n"))
    end
    function envoy_on_response(response_handle)
      local headers = response_handle:headers()
      local headersStr = ""
      local contentType
      local contentEncoding = false
      for key, value in pairs(headers) do
        if key == "content-type" then
           contentType = value
        elseif key == "content-encoding" then
           contentEncoding = true
        end
        headersStr = headersStr .. key .. "=" .. value .. ", "
      end
      local responseBody = ""
      if check_content_readable(contentType) and not contentEncoding then
        for chunk in response_handle:bodyChunks() do
          if (chunk:length() > 0) then
            responseBody = responseBody .. chunk:getBytes(0, chunk:length())
          end
          if (#responseBody > maxBodySize) then
             responseBody = responseBody .. "<truncated>"
             break
          end
        end
      end
      local reqHeaders = ""
      local reqBody = ""
      local metadata = response_handle:streamInfo():dynamicMetadata():get("envoy.lua")
      if metadata ~= nil then
        local headers = response_handle:streamInfo():dynamicMetadata():get("envoy.lua")["request_headers"]
        if headers ~= nil then
          reqHeaders = headers
        end
        local body = response_handle:streamInfo():dynamicMetadata():get("envoy.lua")["request_body"]
        if body ~= nil then
          reqBody = body
        end
      end
      response_handle:logInfo("request Headers: [" .. reqHeaders .. "] request Body: [" .. string.gsub(reqBody,"\n","\\n") .. "] response Headers: [" .. headersStr .. "] response Body: [" .. string.gsub(responseBody,"\n","\\n") .. "]")
    end
  2. プラグインのログを表示します。

    この機能では、ゲートウェイプラグインのログ転送を有効にする必要があります。この機能が有効になっていない場合は、Immediately Enable Log Shipping をクリックします。ログ転送を有効にすると、ゲートウェイはプラグインログを Log Service (SLS) に転送し、そこで表示できます。アクセスログの x-request-id を使用して、Lua プラグインログで完全なリクエストとレスポンスの情報を検索できます。

    [プラグインログ] タブをクリックします。検索バーに、クエリステートメント (例:module:lua and cluster_id:<your-gateway-instance-ID>) を入力し、アクセスログの x-request-id の値をフィルターとして追加します。raw ログセクションのクエリ結果には、一致するリクエストの完全な HTTP リクエストヘッダー、リクエストボディ、レスポンスヘッダー、およびレスポンスボディが表示され、x-request-id フィールドがハイライトされます。

アクセスログでの完全なリクエストとレスポンス情報の表示

  1. ルーティングルールを設定する際に、次の Lua コードを使用します。

    ゲートウェイのアクセスログのパラメーターにカスタムの動的メタデータを設定できます。この場合、プラグインでメタデータを定義する必要があります。次のサンプルコードでは、リクエストヘッダー、リクエストボディ、レスポンスヘッダー、レスポンスボディに対応する 4 種類のメタデータ情報を定義します。

    • envoy.lua:request_headers

    • envoy.lua:request_body

    • envoy.lua:response_headers

    • envoy.lua:response_body

    local maxBodySize = 1024
    function check_content_readable(type)
      if type == nil then
        return false
      end
      if string.find(type, "application/x-www-form-urlencoded",1,true) or string.find(type, "application/json",1,true) or string.find(type, "text/plain",1,true) then
         return true
      end
      return false
    end
    function envoy_on_request(request_handle)
      local headers = request_handle:headers()
      local headersStr = ""
      local contentType
      for key, value in pairs(headers) do
        if key == "content-type" then
           contentType = value
        end
        headersStr = headersStr  .. key .. "=" .. value .. ", "
      end
      request_handle:streamInfo():dynamicMetadata():set("envoy.lua","request_headers",headersStr)
      local requestBody = ""
      if check_content_readable(contentType) then
        for chunk in request_handle:bodyChunks() do
          if (chunk:length() > 0) then
            requestBody = requestBody .. chunk:getBytes(0, chunk:length())
          end
          if (#requestBody > maxBodySize) then
             requestBody = requestBody .. "<truncated>"
             break
          end
        end
      end
      request_handle:streamInfo():dynamicMetadata():set("envoy.lua","request_body",string.gsub(requestBody,"\n","\\n"))
    end
    function envoy_on_response(response_handle)
      local headers = response_handle:headers()
      local headersStr = ""
      local contentType
      local contentEncoding = false
      for key, value in pairs(headers) do
        if key == "content-type" then
           contentType = value
        elseif key == "content-encoding" then
           contentEncoding = true
        end
        headersStr = headersStr .. key .. "=" .. value .. ", "
      end
      response_handle:streamInfo():dynamicMetadata():set("envoy.lua","response_headers",headersStr)
      local responseBody = ""
      if check_content_readable(contentType) and not contentEncoding then
        for chunk in response_handle:bodyChunks() do
          if (chunk:length() > 0) then
            responseBody = responseBody .. chunk:getBytes(0, chunk:length())
          end
          if (#responseBody > maxBodySize) then
             responseBody = responseBody .. "<truncated>"
             break
          end
        end
      end
      response_handle:streamInfo():dynamicMetadata():set("envoy.lua","response_body",string.gsub(responseBody,"\n","\\n"))
    end
  2. ログフォーマットを調整します。

    ゲートウェイインスタンスの左側のナビゲーションペインで、Parameters をクリックし、次に Default Format (Manual Input) をクリックします。アクセスログに情報を表示するには、対応するメタデータをカスタムログフィールドに追加します。

    4 つのカスタムログフィールドを追加します。リクエスト情報については、[フィールドタイプ] に [Request dynamic metadata] を選択し、フィールド値を envoy.lua:request_headersenvoy.lua:request_body に設定します。レスポンス情報については、[フィールドタイプ] に [Response dynamic metadata] を選択し、フィールド値を envoy.lua:response_headersenvoy.lua:response_body に設定します。