しばやん雑記

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

URL Rewrite で環境変数の値を使うプロバイダーを書いてみた

Apache の mod_rewrite なら環境変数の値を使って条件が書けるのに、IIS の URL Rewrite ではサーバー変数の値しか使えなかったので、プロバイダーを書いて実現してみました。

ちなみに mod_rewrite なら以下のように書けます。

RewriteEngine On

RewriteCond %{ENV:FOOBAR} ^buchizo$
RewriteRule .* https://buchizo.wordpress.com/ [R=301,L]

%{ENV:名前} と書けば、その名前の環境変数が取れるようになっています。羨ましい感じですね。

URL Rewrite 用のカスタム書き換えプロバイダーの実装方法は IIS 公式サイトに載っています。

Developing a Custom Rewrite Provider for URL Rewrite Module | Microsoft Learn

今の時代に GAC へのインストールが必須だったり、ちょっといまいちな感じがします。といっても、これは URL Rewrite 側の制約なのでどうしようもない感じですね。*1

書き換えプロバイダーを作成する

基本的には IRewriteProvider と IProviderDescriptor を実装すればいいみたいです。環境変数を取るだけなので、作ったプロバイダーは実質 1 行で完成しました。

public class EnvProvider : IRewriteProvider, IProviderDescriptor
{
    public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext)
    {
    }

    public string Rewrite(string value)
    {
        return Environment.GetEnvironmentVariable(value);
    }

    public IEnumerable<SettingDescriptor> GetSettings()
    {
        yield break;
    }
}

Environment.GetEnvironmentVariable を呼ぶだけなので、標準の機能として欲しいと本当に思います。

作成した DLL は GAC にインストールする必要があるので、Visual Studio のビルド後に実行するコマンドとして、以下のスクリプトを入れておきます。

CALL "%VS120COMNTOOLS%\vsvars32.bat" > NULL
gacutil.exe /if "$(TargetPath)"

設定すると以下のようになります。実行タイミングはビルドが成功した時でいいと思います。

そして GAC にインストールするためには署名が必要になるので、オレオレ署名を作成しておきます。

これでビルドが成功すれば GAC に dll が都度インストールされるようになりますが、gacutil.exe は管理者権限が必要なので Visual Studio 自体を管理者として実行することにします。

URL Rewrite で使えるようにする

GAC にインストール後、IIS Manager から URL Rewrite の項目を開いてプロバイダーの追加を行います。

ここで指定する名前で Web.config というか URL Rewrite 内からの呼び出しを行うことになります。

作成したプロバイダーはいろんな場所で使えますが、分かりやすく書き換えの条件として使ってみることにします。サーバー変数と似てますが {ENV:名前} と書くことで、その名前の環境変数を参照できます。

PROCESSOR_ARCHITECTURE を見ている理由は特にありません。既存の環境変数を探しただけです。

設定後の Web.config を見ると、以下のように URL Rewrite の設定が追加されています。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="env variable" stopProcessing="true">
          <match url=".*" />
          <conditions>
            <add input="{ENV:PROCESSOR_ARCHITECTURE}" matchType="Pattern" pattern="AMD64" ignoreCase="true" negate="false" />
          </conditions>
          <action type="Redirect" url="https://buchizo.wordpress.com/" redirectType="Found" />
        </rule>
      </rules>
      <providers>
        <provider name="ENV" type="EnvProvider.EnvProvider, EnvProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=158f62c518ab860e" />
      </providers>
    </rewrite>
  </system.webServer>
</configuration>

これでサイトにアクセスすると x64 環境の場合はブチザッキに飛ばされるようになるはずです。Web Apps にインストール出来るようになれば、もう少し活用方法が出てくるので残念です。

*1:Azure Web Apps では GAC へのインストールが無理なので使えない