さくらサーバーのマルチドメイン環境下でmodRewriteが動かない場合の原因と対処法

2014年3月に契約したさくらサーバーでrewriteが動作せず、1週間以上悩みもだえる事になったのでメモしときます。

サーバーの設定

今使っているサーバーのマルチドメイン設定は下記の様になっています。
domain.sakura.ne.jp → / (デフォルトのルート 未使用)
domain1.com → /dir1 (Wordpressで使用中のこのブログ)
domain2.com → /dir2 (今回使いたいのはここ)

 

症状

/dir2ディレクトリに.htaccessファイルとhoge.phpを置いて、「domain2.com/hoge」へアクセスした時に「domain2.com/hoge.php」を表示させたいのですが、下記内容で404エラーとなってしまいます。

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

これは拡張子無しでファイルを表示させる王道的手法なので、根本的に間違っているとは思えず…。
ローカルに立てたサーバーだとこれで普通に動くし、他のサーバーでも問題なく動きます。動かないのはさくらサーバーだけ。なんでじゃー!?とイライラしながら色々やってるうちに不思議な事に気づきました。

 

RewriteRule ^a(.*)$ $1.php [L]

RewriteRuleをこう書くと「domain2.com/ahoge」へアクセスして「domain2.com/hoge.php」が正しく表示されるんです。
正規表現の先頭に、aが付くか付かないかの差しかありません。

 

RewriteRule ^sub/(.*)$ $1.php [L]

そして、RewriteRuleをこう書くと「domain2.com/sub/hoge」へアクセスして「domain2.com/hoge.php」が正しく表示されるんです。

正規表現でsub/という存在しないディレクトリが付くか付かないかの差しかありません。
「ahoge」や「sub/hoge」は確実に存在しないファイルですが、「hoge」だと拡張子有りの「hoge.php」が存在してしまうので、そのあたりが影響してRewriteCondとRewriteRuleのパターンがマッチしていないと判定されているような感じでした。

 

解決

さくらのサポートに問い合わせたところ、.htaccessの設定はサポート外ですとの冷たい反応。
その返信の最後に、ApacheのMultiviewsMatchの設定がAnyからNegotiatedOnlyに変更になった旨が添えられていました。
MultiviewsMatchが何なのか分からなかったので自分で調べてみると、コンテントネゴシエーションの設定らしく、これはサーバーへ不確実なリクエストを送った場合でもサーバー側で良い感じに解釈して適切なファイルをレスポンスしてくれる機能らしい。
要するに、リクエストしたファイルが見つからない場合、その名前に合う拡張子を勝手に探して付加したりするらしいんですよ。
これは関係ありそうじゃないか。
そう思って、何も考えずに .htaccessに1行追記しました。

 

MultiviewsMatch Any
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

…くぽっ!(曇り空が晴れる音)

これで問題なく動きました!

Anyにすると、登録されていないすべての拡張子のコンテントネゴシエーションが掛かるそうで、そうする事で解決する仕組みはよく分かりませんが…とりあえず動いたので良しとします

ちなみに、さくらサーバーのマルチドメインで.htaccessのRewriteを使う場合は、RewriteBase /をRewriteBase /dir2の様にしないと動かないと書かれているサイトがたくさんでてきますが、RewriteBase /じゃないと動きませんでした。

さくらの新しいサーバーはApacheのバージョンが変わっているらしく、いろいろ変更があるようです。
ご注意されたし!