Giga-Usagiはどうやってテナントを特定しているか
簡単なまとめ
Section titled “簡単なまとめ”- X-Giga-Hostname または Host ヘッダーの値
- lib/Giga/Config.pm で組み込まれた設定値
- 例えばdevhostなら
(メディア名)-branch-${DEVHOST_SUBDOMAIN}.${DEVHOST_DOMAIN} (メディア名)の部分は lib/Giga/Media/Repository.pm から取り出す- DEVHOST_SUBDOMAIN はコンテナ構築時にブランチ名を設定する
- DEVHOST_DOMAIN は調べていないけど環境ごとに固定のはず
- 例えばdevhostなら
リクエストが届いたとき、ミドルウェアで lib/Giga/Middleware/DetermineNamespace.pm の call が実行される。ここで lib/Giga/Routes.pm の determine_namespace を呼び出す。引数の hostname と path は以下の通り。
my ($hostname) = split ':', $env->{HTTP_X_GIGA_HOSTNAME} || $env->{HTTP_HOST} || '';my $path = $env->{PATH_INFO};determine_namespace は以下の値を返すのだが参照先が多く分岐も多いので少し難しい。
- hostname: 対象メディアの完全修飾ドメイン名
- media: gardo や playground のようなメディア名
- namespace: Media::CanonicalMediaName のような文字列
- static: だいたい media と同じ値
最初の実行時に、 lib/Giga/Media/Repository.pm からメディアの一覧を参照して、すべてのテナントを扱うルールを生成する。ホスト名を組み立てるのは以下のコード。
my $media_host = URI->new(Giga::Web::Util->root_uri_by_name($media->name))->host;ここで root_uri_by_name はメディア名からホスト名を構築するのだが、ここで lib/Giga/Web/Util.pm の root_uri_by_name がコンフィグ(lib/Giga/Config.pm)の中から root-uri.(media) となっているパラメータの存在を調べる。root-uri. ではじまるパラメータは環境ごとに用意されており、例えば本番なら lib/Giga/Config.pm の production_root_uris を、開発なら devhost_root_uris などを参照する。このキーが定義されていれば、それは完全なドメインとなっているので、存在していれば hostname は決まる。
上記のキーが定義されていない場合、root_uri_by_name は root-uri.pattern を探す。これはメディア名をドメイン名の一部で使った動的な値を構築するために使う。一部省略するが、例えばdevhost環境なら以下のような設定。
sub devhost_root_uris { my $domain = $ENV{DEVHOST_DOMAIN} || 'devhost.gigaviewer.com'; my $branch = $ENV{DEVHOST_SUBDOMAIN} || '' my $subdomain = lc "$branch"; { # これはroot_uri_by_nameでsprintf $pattern, $domain_nameされる # $domain_nameはcanonicalizeされたメディア名 'root-uri.pattern' => "https://\%s-branch-$subdomain.$domain" };}DEVHOST_SUBDOMAIN は ecspresso でコンテナを構築するときにブランチ名を割り当てる。具体的には devhost/mirage-ecs/ecspresso/backend.jsonnet で設定している。
そうしておいて、hostname にマッチしたオブジェクトを返す。どれもマッチしなければエラーになる。
for my $rule (@$rules) { if ($hostname eq $rule->{hostname}) { ... }}die "Unexpected hostname: $hostname";基本は同じ処理をするけれど、参照するコンフィグのパラメータ等が異なる。