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プラグイン使用)

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

1
2
3
4
5
6
7
8
# サービス作成
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 でログ出力(標準出力へ)

1
2
3
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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フェーズに以下のコードを挿入しています。それぞれの意味をコメントで説明します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- リクエストから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())
1
2
-- レスポンスの内容をログに追加
kong.log.set_serialize_value('response.body', kong.service.response.get_body())

リクエスト送信

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

1
2
3
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"が追加されています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "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も確認できています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
...
  "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の前処理をスマートに自動化できますよ!