しばやん雑記

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

Windows Azure Web サイトでメンテナンス画面を表示する方法を考えてみた

日本データセンターの稼働で色々と移行の準備を行っているのですが、どうしても SQL Database 周りを考えると一時的にメンテナンスモードにする必要が出てきたので、どの URL でアクセスしてきてもメンテナンス中画面を表示する方法を考えました。

URL Rewrite を使う

既存のコードは変更したくないので URL Rewrite を使って書き換えを行います。条件としては環境変数を参照したかったのですが、サーバ変数しか見れないので諦めてファイルの有無で書き換わるようにしました。

<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Maintenance" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="true"/>
          <conditions>
            <add input="{APPL_PHYSICAL_PATH}maintenance.txt" matchType="IsFile" />
          </conditions>
          <action type="Rewrite" url="maintenance.html" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

これで maintenance.txt が存在している場合には maintenance.html へ書き換えが行われます。

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

URL Rewrite と SSI を使う

メンテナンス中かどうかを判別するためのファイルですが、空っぽだと何となくもったいない感じがしたので、Server Side Include を使って内容を埋め込むようにしてみます。

URL Rewrite のルールは書き換え先のファイル名だけを maintenance.shtml と変更しておきます。Web サイトでは shtml / shtm などの拡張子の場合だけ SSI のモジュールが動作するようになっているからです。

もちろんファイル名も shtml に変更する必要があります。とりあえず SSI とか覚えてる人少ないと思うのでコードを出します。

<!DOCTYPE html>
<html>
<head>
    <title>Maintenance</title>
</head>
<body>
    <h1>Maintenance</h1>
    <p>
        <!--#include virtual="maintenance.txt" -->
    </p>
</body>
</html>

#include や #exec とかありましたね。CGI 時代っぽくて凄く懐かしいです。

maintenance.txt にはメンテナンス中画面で表示したい内容を書いておくだけです。

We'll be back soon.

内容に特に意味はありません。とりあえずこれで実行すると SSI でテキストが埋め込まれるので、メッセージ付きで表示されます。

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

HttpModule と環境変数を使う

とりあえず URL Rewrite を使った方法で要件は満たせたんですが、やはり Web サイトを使う場合はファイルの有無ではなくて、管理ポータルからオンオフを行いたいと思ったので、環境変数の値を見て応答を変える HttpModule を作成しました。

割と手抜き実装なので参考程度に捉えておいてください。

public class MaintenanceModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (sender, e) =>
        {
            var flag = Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_MAINTENANCE");

            if (flag != "1")
            {
                return;
            }

            var application = (HttpApplication)sender;

            application.Context.Response.ContentType = "text/html";
            application.Context.Response.WriteFile("maintenance.html");
            application.Context.Response.End();
        };
    }

    public void Dispose()
    {
    }
}

やっていることは大したことないんですが、管理ポータルのアプリケーション設定から登録した値は頭に "APPSETTING_" が付いたキー名でも取れるので、今回はそっちを参照することにしました。

後は管理ポータルから WEBSITE_MAINTENANCE=1 という感じでキーを追加するだけです。

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

画面的には同じなので省略しますが、これでファイルの操作を行わずに管理ポータルからオンオフできるようになりました。

最後になりますが、Web サイトのメンテナンスを行うために管理ポータルからサイト自体を停止するのは、バックエンドで動いている Kudu も停止するのであまりお勧めできません。