しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Front Door の Rules Engine (Preview) を一通り試した

Build 2020 合わせでのリリースだと思いますが、Front Door にも Rules Engine が追加されました。

これまで Front Door ではホスト名とパスベースのルーティングは行えましたが、Rules Engine を使うことで HTTP ヘッダーやパラメータベースでのルーティングが可能になります。

バックエンドが同じ Azure CDN では Rules Engine は既に使えるようになっている関係上、Front Door に追加された Rules Engine も殆ど同じ機能を持っています。

ドキュメントを見比べた限りでは、Front Door 固有の機能を追加したぐらいという感じです。Front Door は Azure CDN の上位互換と言えるので、Azure CDN で行えることは Front Door でも問題なく行えます。

公式ドキュメントなどで実現できることに関しては書いてあるので、調べて分かった実現出来ないことを先にまとめておきます。GA までにはもうちょっと機能拡充が欲しいところです。

後は自分が必要になりそうなルールをメインに作成しつつ、ドキュメントを読んで挙動が良くわからなかった部分を中心に実際に試しています。

Rules Engine で出来ないこと

マッチした部分文字列を使った高度なルーティング

IIS の URL Rewrite のように正規表現を使って、部分文字列を取得した後に HTTP ヘッダーに付けるといった高度なルーティングは行えません。

例えばサブドメインを使ったマルチテナントのシチュエーションで、Front Door はワイルドカードで受けつつもサブドメイン部分を抽出して、バックエンドには HTTP ヘッダーなどで渡すといった処理は書けないです。なのでバックエンド側で X-Forwarded-Host を解析する必要があります。

正規表現まではいかなくても、一応 Azure CDN の Rules Engine や Front Door のルーティングルールでは一部ワイルドカードを使ったマッチが可能でしたが、Front Door の Rules Engine では有効化されていないようでした。仕組みは同じだと思うので、GA には有効になると期待しています。

バックエンドにリクエストせずにレスポンスを返す

アクセスさせたくない URL や IP アドレスなどの場合に、バックエンドへリクエストさせずに 403 や 404 といったエラーのレスポンスを返すような処理は書けません。

現時点では IP 制限を実装する場合はエラー用の URL やバックエンドを作成して、常にルーティングするようなルールを作成することになります。エラーページのカスタマイズが出来るのは利点かもしれません。

GA までには独自のレスポンスを返す機能が実装されてほしいところです。

バックエンドのレスポンスを条件にする

たまにありますが、拡張子がないリクエストパスの場合に Content-Type を見てキャッシュするかどうかを決めたい時があると思いますが、Front Door の Rules Engine はリクエスト時に条件が評価されるので、レスポンスの HTTP ヘッダーは条件に使えません。

css や jpg といった静的ファイルだけをキャッシュしたい場合には、ディレクトリや拡張子を決め打ちで行う必要があります。専用のドメインを Front Door に追加して、丸ごとキャッシュ対象にする方法もありです。

Rules Engine を使ってみた例

思いつくままにいくつか典型的なルールを作成して試してみました。

Rules Engine Configuration の変更は試した限りでは平均 2 分ぐらいで有効になるので、思ったよりも早いです。設定できるはずに制限はありますが、それなりに柔軟なルールを作成できます。

HTTPS へのリダイレクトを行う

リリースブログにも書いてあるように、HTTPS へのリダイレクトを Rules Engine を使って実現することが出来ます。HTTP の場合はアクションでデフォルトのルーティング設定をオーバーライドし、ホスト名やパスなどの情報を保持したまま HTTPS にリダイレクトさせます。

f:id:shiba-yan:20200513151650p:plain

ちなみに Azure CDN でも同じようにして HTTPS を強制することが出来ます。

作成した Rules Engine はルーティングの設定から選択します。1 つしか指定できないので、汎用的な Rules Engine を作成して使いまわすことは期待しない方が良さそうでした。

f:id:shiba-yan:20200513154833p:plain

これで Front Door の設定を保存すれば、2,3 分後には反映されて HTTPS へリダイレクトされます。

f:id:shiba-yan:20200513154845p:plain

非常に簡単でしたが、1 つのルーティングには 1 つの Rules Engine しか指定できないので、HTTPS への強制は以前に書いたようにルーティング側で解決した方が汎用的だと思いました。

この方法ならフロントエンドが増えても 1 つのルーティングで対応できるので、無駄にルールを増やす必要がなくなります。各 Rules Engine に個別に HTTPS 強制を入れるのは非常に冗長です。

レスポンスヘッダーを操作する

利用頻度が高そうなのが、バックエンドの HTTP レスポンスヘッダーへの操作です。キャッシュ用やセキュリティ関連のヘッダーの追加や、バックエンドから送信された不要なヘッダーの削除に使えます。

ただしドキュメントに書いていない制約として x-ms から始まるヘッダーは対象に出来ないようでした。追加しようとすると以下のようにエラーになります。

f:id:shiba-yan:20200516222054p:plain

追加はともかく、削除ぐらいはさせてほしいのですが、フィードバックするしかなさそうです。

ヘッダーを追加・上書きする

まずはレスポンスにヘッダーを追加してみます。サンプルに使っているバックエンドは Azure Storage なのでキャッシュ系のヘッダーが付いてこないため、それを補うルールを作成します。

今回はシンプルに特定のディレクトリ以下を対象に Cache-Control を追加します。

f:id:shiba-yan:20200517020407p:plain

非常に罠だと思ったのが Request Path を対象にした場合、マッチさせる値としては先頭に / を含まないものを指定する必要があります。

もちろん Contains を使う場合はその限りではないですが、大体はルートから指定すると思うので / を含めているとマッチせずに悩むことになります。

作成した Rules Engine をルーティングに設定すると、Cache-Control が返ってきます。

f:id:shiba-yan:20200517020321p:plain

Azure CDN や Front Door は自動で Cache-Control を付けてくれはしないので、必要であれば明示的に Rules Engine を使って実装する必要があります。

ヘッダーを削除する

今度は逆にレスポンスからヘッダーを削除します。Azure Storage の場合は x-ms-version などのヘッダーが返ってくるので削除したいですが、前述の理由により削除できないので ASP.NET MVC アプリケーションを使ってヘッダーを削除してみました。

ASP.NET MVC アプリケーションはデフォルトでは、以下のようなバージョンヘッダーを返します。

f:id:shiba-yan:20200513191504p:plain

本来ならアプリケーションの設定で削除すべきですが、今回は Rules Engine を使います。

アクションとしてレスポンスヘッダーの削除を選べば、後は削除したいヘッダー名を入力して終わりです。

f:id:shiba-yan:20200513191850p:plain

設定すると不必要だった各ヘッダーが消えていることが確認できるはずです。

f:id:shiba-yan:20200513191802p:plain

バックエンド側を弄れない場合の最後の手段として、Front Door 側での操作が行えるのは良い感じです。

デフォルトのキャッシュルールを上書きする

Front Door の Rules Engine でのメイン用途はデフォルトのルーティングルールの上書きです。各条件とバックエンドを組み合わせることで、柔軟なルーティングが可能になります。

A/B テストや Canary Release 時にヘッダーやクエリ文字列の値で、強制的に特定のバックエンドへのルーティングも行えますが、ここではキャッシュルールを設定してみます。Front Door は CDN ですが、明示的にキャッシュルールを有効にしないとキャッシュはされないのです。

ファイルパスによって変更する

良くある静的ファイルを CDN にキャッシュさせるルールを作成してみます。まずはパスベースでルールを組み立ててみますが、パスの指定については前述した通り先頭の / を省いています。

CachingEnabled にすると設定が追加で出てくるので、適当なものを選びます。キャッシュしないと HTTP 圧縮もされない仕様なので、地味にはまりそうな感じです。

f:id:shiba-yan:20200516200840p:plain

今回のテストサイトは VuePress で作っているので、ビルドの度にファイル名にハッシュが付いてユニークなものになります。なのでキャッシュ期間を非常に長く設定しています。

この Rules Engine を設定すると X-Cache ヘッダーが追加されて、キャッシュがヒットしたかどうかを返してくれます。キャッシュを有効にしないと付かないので判別に使えます。

f:id:shiba-yan:20200516201243p:plain

静的ファイルは専用のホストから配信するのが理想ではありますが、それはなかなかに難しいので Rules Engine を使って適切なキャッシュ設定を入れておきましょう。

拡張子によって変更する

先ほどとアクションは全く同じですが、条件が拡張子に変更になります。キャッシュ対象にしたいファイル種類は複数ありますが、Request File Extension ではマッチする値を複数指定できます。

f:id:shiba-yan:20200516201101p:plain

メッセージにあるように Enter で改行すれば複数の拡張子を入力できます。ちなみに先頭の . は削除してから指定します。警告などは全く出ないので、これもはまりそうです。

それ以外はファイルパスと同じなので説明と実行結果は省略します。

f:id:shiba-yan:20200516221413p:plain

Content-Type を使った判別は行えないので、キャッシュ戦略としてホストやディレクトリの分離や、拡張子を必須にするといった決めが必要になるでしょう。

Geo Filtering を追加する

Azure CDN には専用の設定が用意されていますが、Front Door では Rules Engine を使うことでアクセス元の地域によっての処理を用意することが出来ます。

良くある日本国内からのアクセスのみに限定するルールを作成してみました。Remote Address を選択すると、オペレーターとして地域を選択できるようになります。

f:id:shiba-yan:20200517003159p:plain

適当に West US に VM を作成してアクセスしてみると、設定したように 404 ページに飛ばされます。

f:id:shiba-yan:20200517003111p:plain

現状の Front Door のルーティングでは、URL Rewrite を行うと元々のパスをフォワーディング先に引き継いでしまうので、綺麗に動作させるためには専用のバックエンドを作成して、パスに関係なくエラーを返すようにした方が良さそうでした。

やはりバックエンド無しでレスポンスを返す機能が欲しくなってきます。

Rules Engine のデバッグ

Front Door の Rules Engine は設定後、実際に反映されるまでに 2,3 分かかるのと、条件式にマッチしたかどうか判別するのがそのままだと難しい場合もあるので、以下のようにレスポンスヘッダーを追加しておくとマッチしたかどうか簡単に区別がつきます。

f:id:shiba-yan:20200517011702p:plain

正しく条件にマッチしていた場合には、以下のようにレスポンスヘッダーが付いてきます。

f:id:shiba-yan:20200517011847p:plain

Diagnostic settings を有効にして、Front Door の各種ログを出力するようにしてみましたが、Rules Engine にマッチしたかどうかはログに出ていなかったので、現状は上のように工夫する必要がありそうです。