読者です 読者をやめる 読者になる 読者になる

しばやん雑記

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

URL Rewrite でサブディレクトリへの書き換えを行うコツ

Windows Azure Web サイトなどで PHP を使ったアプリケーションを開発する際に、割と問題になるのがドキュメントルートです。

PHP や Ruby などのフレームワークは public というディレクトリ内が HTTP から見えるという想定で作られています。つまり、public をドキュメントルートとして設定する必要がある訳です。

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

この画像の場合、fuel ディレクトリは HTTP からアクセス出来てはいけないので、こういったフォルダ構成になっているわけです。

以前に書いた FuelPHP を WebMatrix で使う記事では URL Rewrite を使って、静的ファイルだと思われるものを決め打ちで public ディレクトリへリライトしてきました。

WebMatrix と FuelPHP を使って Web アプリ開発をしてみた - しばやん雑記

たいていの場合はこのルールだけで問題なく動作すると思います。しかし、決め打ちだと対応できないケース、しにくいケースが存在します。

というか、Ruby on Rails で開発された Radiant CMS がそのケースでした。Radiant CMS はスタイルシートや JavaScript を DB に保存しているので、アプリケーション側で処理する必要があるからです。

こういう時には REQUEST_FILENAME を使ってファイルの有無を確認し、書き換えを行うテンプレ的コードがありますが、サブディレクトリへの書き換えを行う場合には、それを適用することは出来ません。*1

<rule name="FastCGI" stopProcessing="true">
    <match url="^(.*)$" ignoreCase="true" />
    <conditions>
        <!-- REQUEST_FILENAME は物理パス + リクエスト URL なので死ぬ -->
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
    </conditions>
    <action type="Rewrite" url="dispatch.fcgi" />
</rule>

なので、どうしようかとなる訳ですが、インターネットを彷徨っていると以下の情報が見つかりました。

asp.net - IIS Rewrite root folder to different subfolders - Stack Overflow

conditions には割と柔軟に指定が出来るみたいですね。この記事を応用してルールを作成してみました。

<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Static Resource" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="true"/>
          <conditions>
            <add input="{APPL_PHYSICAL_PATH}public\{R:1}" matchType="IsFile" ignoreCase="true" />
          </conditions>
          <action type="Rewrite" url="public/{R:1}" appendQueryString="true"/>
        </rule>
        <rule name="FastCGI" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="true"/>
          <action type="Rewrite" url="dispatch.fcgi/{R:1}" appendQueryString="true"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

まず、最初のルールでリクエストされた URL の実体が public 以下に存在しているのかを確認して、存在していたら実体へ書き換えを行います。当然ながらこの段階で静的ファイルは全て処理できるはずですね。

なので、次の FastCGI への書き換えを行う部分は無条件で通るようにしてあります。

このルールを使って、他にも色々と試行錯誤した結果、Radiant CMS を無事に Windows Azure Web サイトで動かすことが出来たのでした。

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

旧式のハンドラを使っていましたが、Windows 向けに修正した fcgi で問題なく動いてくれました。

*1:ディレクトリが違うんだから当然である