Nginxのクッキーのプレフィックスを着脱するngx_http_cookie_prefixerを実装した

概要

Nginxは非常に柔軟性が高く、多くの機能をモジュールとして組み込むことができます。今回は、特定のプレフィックスを持つクッキーを操作するためのカスタムNginxモジュール ngx_http_cookie_prefixer を開発しました。

モジュールの機能

このモジュールは、リクエストとレスポンスの両方でクッキーを操作する機能を提供します。具体的には、リクエストヘッダーから指定されたプレフィックスを持つクッキーを見つけ、そのプレフィックスを削除します。さらに、レスポンスヘッダーに同じプレフィックスを付加することもできます。

使い方

モジュールの使用方法は非常に簡単です。以下の設定をNginxの設定ファイルに追加するだけです。

http {
    include       mime.types;
    server {
        listen       127.0.0.1:1234;
        server_name  localhost;
        location / {
            proxy_detach_cookie_prefix example_prefix_;
            proxy_pass http://localhost:10080;
        }
    }
}

この設定では、proxy_detach_cookie_prefix ディレクティブを使用して、example_prefix_ というプレフィックスを持つクッキーを操作します。

まずhttpbinにそのままリクエストを送ると、example_prefix_ はついたままです。

% curl -s -b'name=example_prefix_a; value=1' -b'name=not_match_prefix_b; value=2;' http://httpbin.org/get -L
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    # cookieのprefixがついている。
    "Cookie": "name=example_prefix_a; value=1;name=not_match_prefix_b; value=2;",
    "Host": "httpbin.org",
    "User-Agent": "curl/8.1.2",
    "X-Amzn-Trace-Id": "Root=1-657a8e1d-101ad6fe25e3bfa03e0248e1"
  },
  "origin": "114.178.98.146",
  "url": "http://httpbin.org/get"
}

このモジュールを利用すると、下記のようにprefixが削除されます。

% curl -s -b'name=example_prefix_a; value=1' -b'name=not_match_prefix_b; value=2;' http://localhost:1234/get -L
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Connection": "close",
    # こんな感じでname=aになる
    "Cookie": "name=a; value=1;name=not_match_prefix_b; value=2;",
    "Host": "localhost:10080",
    "User-Agent": "curl/8.1.2"
  },
  "origin": "172.17.0.1",
  "url": "http://localhost:10080/get"
}

リクエストヘッダだけでなく、レスポンスも同じように削除されます。

% curl http://httpbin.org/cookies/set/a/example --head
HTTP/1.1 302 FOUND
Date: Thu, 14 Dec 2023 05:12:41 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 223
Connection: keep-alive
Server: gunicorn/19.9.0
Location: /cookies
Set-Cookie: a=example; Path=/ # aのまま
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
% curl http://localhost:1234/cookies/set/a/example --head
HTTP/1.1 302 FOUND
Server: nginx/1.25.3
Date: Thu, 14 Dec 2023 05:13:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 223
Connection: keep-alive
Location: /cookies
Set-Cookie: example_prefix_a=example; Path=/ # example_prefix_aになっている
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

開発の背景

自社ではマルチテナントかつ、ユーザー自身がコンテンツを提供するサービスを提供しており、クッキーのプレフィックスを付与することで、利用するクッキーを制御したい狙いがあり、開発しました。元々この処理はngx_mrubyで実現していましたが、残った機能がこれだけだったので、小さいモジュールにしたという背景です。

モジュールの詳細

モジュールのコア機能は、リクエストとレスポンスのクッキーを解析し、指定されたプレフィックスに基づいて操作を行うことです。内部的には、ngx_strncasecmpngx_strnstr などのNginx API関数を利用して、効率的かつ安全に文字列処理を行っています。

まとめ

ngx_http_cookie_prefixer モジュールは、クッキーのプレフィックス操作を簡単かつ効率的に行うための強力なツールです。Nginxの拡張性を利用して、特定のニーズに合わせたカスタム処理を実装することができる素晴らしい例だと思います!!1