「404が出ない」「404画面なのに200」「トップだけ表示されない」を構造的に理解する。
はじめに
本記事では、一般的なレンタルサーバー(例:Xserver、さくらインターネット、ロリポップ など)において「公開ルート直下に .htaccess を置き、実体はサブディレクトリに配置する」構成で発生するトラブルを構造的に整理します。
扱う内容は Apache(mod_rewrite / ErrorDocument)の挙動に依存するため、同様の構成を取る多くの環境で再現可能です。
前提構成(よくある運用)
- 公開ルート直下に
.htaccessの設置 - 実際のサイトデータは
{document_root}/act3inc.com/ディレクトリに配置 - URLは
https://act3inc.com/のまま運用する構成(URLは変えず、内部的にサブディレクトリへマッピング)
※ 本記事内の {document_root} は説明用のプレースホルダです。Apache の DocumentRoot(公開ディレクトリ)を指します。なお、.htaccess の条件式では Apache の変数 %{DOCUMENT_ROOT} を使用します。
症状(よくある発生例)
- 存在しない URL にアクセスしても 404 にならない
- 404 ページの見た目は表示されるが、HTTP ステータスは 200(いわゆる「ソフト404」)
- トップページ(
/)だけ表示されない - 他のページは表示される
先に結論:ErrorDocument は「404を発生させる仕組み」ではない
ErrorDocument は 404 が発生したあとに表示するページを指定するだけで、404 そのものを発生させる仕組みではありません。
原因①:すべてを内部マッピングし、結果として 404 が発生しない構造
典型的に、次のような catch-all の内部マッピングがある構造の場合、
RewriteRule ^(.*)$ /act3inc.com/$1 [L]
存在しないURLも {document_root}/act3inc.com/ 側に渡されます。
ここで /act3inc.com 側に「index.html / index.php で受け口がある」「CMS/SPAが常に200を返す」等があると、Apache視点ではリクエストを“処理できてしまう”ため、404 が発生しません(= ErrorDocument 404 も呼ばれません)。
原因②:トップページだけ表示されない(REQUEST_FILENAME -d の構造的な問題)
多くの .htaccess テンプレートにある「既存ファイル/既存ディレクトリはそのまま処理する」構造は便利ですが、
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
/ の場合、%{REQUEST_FILENAME} は公開ルートの物理ディレクトリを指すため -d が真となり、処理がそこで停止します。
その結果、トップページだけ内部マッピングに到達できず「トップだけ表示されない」現象が発生します。
対処:ルートを最優先にし、マッピング前に“実体チェック”して、無ければ 404 を発生させる
ポイントは次の3点です。
- ルート(
^$)を最優先で新サイトへ流すようにする - サブディレクトリ側に実体がある場合だけ内部マッピングする
- 実体がない場合は 明示的に 404 を返すようにする
構成例(.htaccess)
index.html は構成に合わせて index.php などに変更してください。
RewriteEngine On
# 1) ループ防止(新サイト配下は触らない)
RewriteCond %{REQUEST_URI} ^/act3inc\.com/ [NC]
RewriteRule ^ - [L]
# 2) ルートは最優先で新サイトへ(ここが重要)
RewriteRule ^$ /act3inc.com/index.html [L]
# 3) 既存ファイル/既存ディレクトリはそのまま(ただしルートは除外)
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# 4) 新サイト側に実体がある場合のみ内部マッピング(URLは変えない)
RewriteCond %{DOCUMENT_ROOT}/act3inc.com/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/act3inc.com/$1 -d
RewriteRule ^(.*)$ /act3inc.com/$1 [L]
# 5) 実体がなければ 404 を返す(ErrorDocument が表示される)
RewriteRule ^ - [R=404,L]
ErrorDocument 404 /act3inc.com/404/index.html
動作確認のポイント
ブラウザ表示だけでは判定できないため、必ず HTTPステータスを確認してください。
- 存在しないURLが 404 となっているか
- 404画面が表示されていても HTTPステータスが200になっていないか
Chrome DevTools の Network タブや curl -I などで確認することを推奨します。