1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KongのServerless機能を使って、リクエスト処理をもっとスマートに

Posted at

Pre-function Plugin 解説と実用サンプル

Kong Gatewayは多機能なAPIゲートウェイですが、ちょっとした処理をサーバレス関数として内蔵できることをご存知でしょうか?

今回は、Luaスクリプトを使ってリクエストのBodyからUUIDを抽出し、Headerに追記&ログ出力するという実用的なサンプルをご紹介します。


Pre-function Pluginとは?

公式ドキュメントにある通り、pre-functionプラグインはリクエストをAPIに送信する前にLuaで処理を記述できる柔軟な機能です。

用途は多彩で:

  • 条件分岐によるフィルタリング
  • ヘッダー/ボディのカスタマイズ
  • 軽量ログやモニタリング処理
  • メンテナンス用の簡易ブロック処理

など、プラグイン化するほどじゃないけど、ちょっと処理したいというニーズにぴったりです。


実用例

今回は、リクエストボディにあるUUIDを抽出してヘッダーとログに追記する機能をServer Less機能で実現します。

image.png

処理の流れ

  1. リクエストBodyからUUIDを抽出(JSONパース)
  2. UUIDがあれば x-uuid ヘッダーに追記
  3. 抽出結果をログに出力(File Logプラグイン使用)

前提準備:サービスとルートを作成

# サービス作成
curl -i -X POST http://localhost:8001/services \
  --data name=mock-service \
  --data url=http://httpbin.org/anything

# ルート作成
curl -i -X POST http://localhost:8001/services/mock-service/routes \
  --data 'paths[]=/uuid-test'

File Log Plugin でログ出力(標準出力へ)

curl -i -X POST http://localhost:8001/services/mock-service/plugins \
  --data "name=file-log" \
  --data "config.path=/dev/stdout"

Pre-functionの設定

Nginxのフェーズ毎に、カスタムコードを実行することができます。フェーズに関する詳細内容は、以下をご参考ください。
https://nginx.org/en/docs/dev/development_guide.html#http_phases

curl -i -X POST http://localhost:8001/services/mock-service/plugins \
  --data "name=pre-function" \
  --data "config.access[1]=
  local body, err, mimetype = kong.request.get_body()
  if body.uuid ~= nil then
      kong.service.request.add_header('uuid', body.uuid)
  end
  kong.service.request.enable_buffering()
  kong.log.set_serialize_value('request.body', kong.request.get_body())" \
  --data "config.log[1]=
  kong.log.set_serialize_value('response.body', kong.service.response.get_body())"

上記のコードでは、accessフェーズとlogフェーズに以下のコードを挿入しています。それぞれの意味をコメントで説明します。

-- リクエストからBodyを抽出
local body, err, mimetype = kong.request.get_body()

-- Bodyにあるuuidの存在を確認し、もしあったらHeaderに追加
if body.uuid ~= nil then
  kong.service.request.add_header('uuid', body.uuid)
end

-- Bodyの内容をログに追加 
kong.service.request.enable_buffering()
kong.log.set_serialize_value('request.body', kong.request.get_body())
-- レスポンスの内容をログに追加
kong.log.set_serialize_value('response.body', kong.service.response.get_body())

リクエスト送信

uuidをBodyに設定してリクエストを送信します。

curl -i -X POST http://localhost:8000/uuid-test \
  -H "Content-Type: application/json" \
  -d '{"uuid": "123e4567-e89b-12d3-a456-426614174000"}'

すると、APIに到達した時、Headerに"Uuid": "123e4567-e89b-12d3-a456-426614174000"が追加されています。

{
  "args": {}, 
  "data": "{\"uuid\": \"123e4567-e89b-12d3-a456-426614174000\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "48", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "Kong-Request-Id": "acfa1af0-c53e-4129-8b89-8a16be923e35", 
    "User-Agent": "curl/8.7.1", 
    "Uuid": "123e4567-e89b-12d3-a456-426614174000", 
    "X-Amzn-Trace-Id": "Root=1-67fe09a9-7b1c7cf96bbcc28938e75a7f", 
    "X-Forwarded-Host": "localhost", 
    "X-Forwarded-Path": "/uuid-test", 
    "X-Forwarded-Prefix": "/uuid-test", 
    "X-Kong-Request-Id": "ebfdfe72b011c1100130e00f026bfb65"
  }, 
  "json": {
    "uuid": "123e4567-e89b-12d3-a456-426614174000"
  }, 
  "method": "POST", 
  "origin": "192.168.97.1, 133.201.15.64", 
  "url": "http://localhost/anything"
}

ログから、リクエストとレスポンスの詳細が表示されていて、Headerだけではなく、Bodyも確認できています。

{
...
  "request": {
    "uri": "/uuid-test",
    "size": 187,
    "method": "POST",
    "querystring": {},
    "body": {
      "uuid": "123e4567-e89b-12d3-a456-426614174000"
    },
    "url": "http://localhost:8000/uuid-test",
    "headers": {
      "content-length": "48",
      "user-agent": "curl/8.7.1",
      "content-type": "application/json",
      "host": "localhost:8000",
      "accept": "*/*",
      "kong-request-id": "acfa1af0-c53e-4129-8b89-8a16be923e35",
      "uuid": "123e4567-e89b-12d3-a456-426614174000"
    },
    "id": "ebfdfe72b011c1100130e00f026bfb65"
  },
...
  "response": {
    "body": {
      "origin": "192.168.97.1, 133.201.15.64",
      "data": "{\"uuid\": \"123e4567-e89b-12d3-a456-426614174000\"}",
      "json": {
        "uuid": "123e4567-e89b-12d3-a456-426614174000"
      },
      "form": {},
      "method": "POST",
      "url": "http://localhost/anything",
      "files": {},
      "args": {},
      "headers": {
        "X-Forwarded-Host": "localhost",
        "Content-Type": "application/json",
        "Kong-Request-Id": "acfa1af0-c53e-4129-8b89-8a16be923e35",
        "Uuid": "123e4567-e89b-12d3-a456-426614174000",
        "X-Amzn-Trace-Id": "Root=1-67fe09a9-7b1c7cf96bbcc28938e75a7f",
        "Accept": "*/*",
        "Host": "httpbin.org",
        "X-Kong-Request-Id": "ebfdfe72b011c1100130e00f026bfb65",
        "User-Agent": "curl/8.7.1",
        "X-Forwarded-Prefix": "/uuid-test",
        "X-Forwarded-Path": "/uuid-test",
        "Content-Length": "48"
      }
    },
    "size": 1207,
    "status": 200,
    "headers": {
      "via": "1.1 kong/3.10.0.0-enterprise-edition",
      "x-kong-proxy-latency": "68",
      "content-type": "application/json",
      "x-kong-upstream-latency": "352",
      "server": "gunicorn/19.9.0",
      "content-length": "825",
      "x-kong-request-id": "ebfdfe72b011c1100130e00f026bfb65",
      "date": "Tue, 15 Apr 2025 07:24:25 GMT",
      "access-control-allow-origin": "*",
      "access-control-allow-credentials": "true",
      "connection": "close"
    }
  },
...
}

まとめ

Kongのpre-functionとfile-logプラグインを組み合わせることで、外部サービスを呼ばずともAPIリクエスト内容の加工と可視化が実現できます。

Kongは単なるゲートウェイ以上に、「軽量なエッジ処理エンジン」として活用できます。Luaスクリプトをうまく使えば、REST APIの前処理をスマートに自動化できますよ!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?