Skip to content

Giga-Usagiはどうやってテナントを特定しているか

  • X-Giga-Hostname または Host ヘッダーの値
  • lib/Giga/Config.pm で組み込まれた設定値
    • 例えばdevhostなら (メディア名)-branch-${DEVHOST_SUBDOMAIN}.${DEVHOST_DOMAIN}
    • (メディア名) の部分は lib/Giga/Media/Repository.pm から取り出す
    • DEVHOST_SUBDOMAIN はコンテナ構築時にブランチ名を設定する
    • DEVHOST_DOMAIN は調べていないけど環境ごとに固定のはず

リクエストが届いたとき、ミドルウェアで lib/Giga/Middleware/DetermineNamespace.pmcall が実行される。ここで lib/Giga/Routes.pmdetermine_namespace を呼び出す。引数の hostnamepath は以下の通り。

my ($hostname) = split ':',
$env->{HTTP_X_GIGA_HOSTNAME}
|| $env->{HTTP_HOST}
|| '';
my $path = $env->{PATH_INFO};

determine_namespace は以下の値を返すのだが参照先が多く分岐も多いので少し難しい。

  • hostname: 対象メディアの完全修飾ドメイン名
  • media: gardoplayground のようなメディア名
  • 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.pmroot_uri_by_name がコンフィグ(lib/Giga/Config.pm)の中から root-uri.(media) となっているパラメータの存在を調べる。root-uri. ではじまるパラメータは環境ごとに用意されており、例えば本番なら lib/Giga/Config.pmproduction_root_uris を、開発なら devhost_root_uris などを参照する。このキーが定義されていれば、それは完全なドメインとなっているので、存在していれば hostname は決まる。

上記のキーが定義されていない場合、root_uri_by_nameroot-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_SUBDOMAINecspresso でコンテナを構築するときにブランチ名を割り当てる。具体的には devhost/mirage-ecs/ecspresso/backend.jsonnet で設定している。

そうしておいて、hostname にマッチしたオブジェクトを返す。どれもマッチしなければエラーになる。

for my $rule (@$rules) {
if ($hostname eq $rule->{hostname}) { ... }
}
die "Unexpected hostname: $hostname";

基本は同じ処理をするけれど、参照するコンフィグのパラメータ等が異なる。