blog.hekt.org

WordPress の起動を最小限にする mod_rewrite ルール

たまに phpMyAdmin を狙ったスキャンとかがあって、そういうのに対してわざわざ WordPress を起動して動的な 404 ページを返してやるのもリソースの無駄だよなあ、と思ったので、できるだけ静的な 404 ページを出力するようにしました。

具体的には、mod_rewrite ルールを変更して書き換え対象となる URI を WordPress で使うものに限定しました。正規表現なのでけっこう簡単です。以下はパーマリンク設定が “数字ベース” の場合。(“投稿名” の場合はかなり厳しいですね……)

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]

# 個別記事
RewriteCond %{REQUEST_URI} ^/archives/[0-9]+/?$ [OR]
# タグ・カテゴリー
RewriteCond %{REQUEST_URI} ^/archives/(tag|category)/[^/]+/?$ [OR]
# 月別・年別アーカイブ
RewriteCond %{REQUEST_URI} ^/archives/date/[0-9]{4}(/[0-9]{2})?/?$ [OR]
# インデックスやタグ、カテゴリー、月別・年別の2ページ目以降 (後方一致)
RewriteCond %{REQUEST_URI} /page/[0-9]+/?$ [OR]
# 各種フィード (後方一致)
RewriteCond %{REQUEST_URI} /feed(/rss2?|/atom)?/?$

RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-d
RewriteRule . /index.php [L]
</IfModule>

# 静的なエラーページ
ErrorDocument 404 /404.html

RewriteCond は通常 AND で接続されますが、[OR] と明示することで OR で接続することもできます。この場合、明示された OR のほうが AND より強く、1 2 [OR] 3 41 and (2 or 3) and 4 という具合になります。

初期状態では %{REQEUST_FILENAME} となっているところが %{DOCUMENT_ROOT}/%{REQUEST_URI} になっているのは、僕の場合これらを <VirtualHost> ディレクティブの中に書いているからです。このような環境のとき、%{REQEUST_FILENAME}%{REQUEST_URI} と同じになります。参考:

REQUEST_FILENAME
[…] such as when used in virtual host context, the same value as REQUEST_URI.

ちなみに、僕がパーマリンク設定を “数字ベース” にしている理由は、僕が優柔不断で、記事を公開したあとも細かく変更したくなるタチだからです。パーマリンクがパーマリンクとしての用を成すためには僕に変更する余地を与えないことが大事なのです。

ただ、自動的に割り振られる番号だと記事を復元するときに問題があるというのをつい最近学んだところなので、そのうち変えるかも知れません。やるなら “/archives/YYYYMMDDhhmm” とかのタイムスタンプベースかなあ。