ApacheのDirectoryMatchとLocationMatch
ApacheのDirectoryディレクティブやLocationディレクティブで正規表現を使いたいときは、DirectoryMatchやLocationMatchを使用しますが、今日ちょっと設定していて、なるほどと思ったのでメモ。
あと今日、はてダからはてなブログにインポートしてみたのでテスト投稿。
やりたいこと
とある階層にある、特定の画像ファイルがなかった場合(404の場合)、特定のエラー画像ページを出したい。
これは、DirectoryとErrorDocumentディレクティブの組み合わせで出来そうなものなんだけど、この「とある階層」ってのがちょっと厄介。
例えばドキュメントルートを/foo/barとした場合
/foo/bar/img/a/image1.jpg /foo/bar/img/a/b/image2.jpg /foo/bar/img/a/b/c/image3.jpg /foo/bar/img/a/b/c/d/image4.jpg
こんなふうに/foo/bar/img配下のどこかにあるjpgファイルのみErrorDocumentの対象にしたい。
DirectoryMatch
/foo/bar/img配下のどこかにある…のだから初めは↓のように設定した。
DocumentRoot "/foo/bar" <DirectoryMatch "/foo/bar/img/.*\.jpg$"> ErrorDocument 404 /baz/404.jpg </DirectoryMatch>
こうすると
http://aaaaaaaa/img/a/b/image2.jpg
→ これはファイルがあるので当然200で返る
http://aaaaaaaa/img/a/b/hogehogehoge.jpg
→ これはファイルがない、かつ正規表現にマッチするのでErrorDocumentで返る
http://aaaaaaaa/img/a/b/c/d/hogehogehoge.jpg
→ これも同じ。階層が深くなっても正規表現にマッチするのでErrorDocumentで返る
http://aaaaaaaa/img/baz/hogehogehoge.jpg
→ 問題はこれ。defaultの404ページなる
正規表現的には、.*で全マッチなので、/img/baz/hogehogehoge.jpgはマッチする。
だけど、ApacheのDirectoryディレクティブは、指定のディレクトリにマッチするかどうかなので、ディレクトリそのものがないこのパターンではDirectoryディレクティブが適用されない。
ファイルがない404とディレクトリがない404は違う。
LocationMatch
で結局Locatonを使って↓みたく書きなおした。
DocumentRoot "/foo/bar" <LocationMatch "/img/.*\.jpg$"> ErrorDocument 404 /baz/404.jpg </LocationMatch>
LocationならばURLマッチなので、
http://aaaaaaaa/img/baz/hogehogehoge.jpg
のようなURLもErrorDocumentで返る。
Locationは
(なぜか)普段あまり使わないのでたまに使うと便利だなーと思う。