Windows Azure Web サイトなどで PHP を使ったアプリケーションを開発する際に、割と問題になるのがドキュメントルートです。
PHP や Ruby などのフレームワークは public というディレクトリ内が HTTP から見えるという想定で作られています。つまり、public をドキュメントルートとして設定する必要がある訳です。
この画像の場合、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 サイトで動かすことが出来たのでした。
旧式のハンドラを使っていましたが、Windows 向けに修正した fcgi で問題なく動いてくれました。
*1:ディレクトリが違うんだから当然である