Apache 2.4系で動作を確認した .htaccess の記述をまとめます。必要な項目だけをコピーして使用してください。各項目は独立しており、相互の関連性はありません。
コード内のドメイン名はすべて説明用の仮名です。実際に使用するドメインへ変更してください。
HTTPS化とURLの統一
HTTPS化
wwwの有無は維持したままHTTPSへ転送します。www付きとwww無しの両方を1つの記述で扱えます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^((?:www\.)?example\.com)(?::[0-9]+)?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
</IfModule>
HTTPS・wwwなしへ統一
HTTPSかつwww無しのURLへ統一します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^example\.com(?::[0-9]+)?$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]
</IfModule>
HTTPS・wwwありへ統一
HTTPSかつwww付きのURLへ統一します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com(?::[0-9]+)?$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
</IfModule>
index.htmlなしへ統一
/dir/index.html へのアクセスを /dir/ へ転送します。THE_REQUEST は常にルートからの完全なパスを含むため、設置階層を問わず動作します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/+(.*/)?index\.html(?:[?\s]) [NC]
RewriteRule ^ /%1 [R=301,L]
</IfModule>
index.phpなしへ統一
拡張子が異なるだけで、考え方はindex.htmlの場合と同じです。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/+(.*/)?index\.php(?:[?\s]) [NC]
RewriteRule ^ /%1 [R=301,L]
</IfModule>
リダイレクト
同一ドメイン内の転送では、転送先を new_page.html のような相対パスで書くと、301の転送先にサーバー内部のファイルパスが露出し、転送も機能しません。
そのため、転送先の直前に RewriteCond の行を置いています。この行が設置階層を算出し、その結果を %1 で受け取る仕組みです。ルート直下でもサブディレクトリでも同じ記述が使えます。
サイト全体
元のパスを維持したままサイト全体を転送します。/about/ は https://example.com/about/ へ転送されます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]
</IfModule>
ドメイン変更
www付きとwww無しの旧ドメインから、元のパスを維持して新ドメインへ転送します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?old-site\.com(?::[0-9]+)?$ [NC]
RewriteRule ^ https://new-site.com%{REQUEST_URI} [R=301,L]
</IfModule>
ページ単位(同一ドメイン)
特定のページを同じドメイン内の別ページへ転送します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI}::$0 ^(/.*?)(.*)::\2$
RewriteRule ^old_page\.html$ %1new_page.html [R=301,L]
</IfModule>
ページ単位(別ドメイン)
転送先が別ドメインの場合は、完全なURLを書くだけで済みます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^old_page\.html$ https://www.url.com/new_page.html [R=301,L]
</IfModule>
ディレクトリ単位(同一ドメイン)
配下のパスを維持したままディレクトリごと転送します。
- /old_dir/ は /new_dir/ へ転送
- /old_dir/page.html は /new_dir/page.html へ転送
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI}::$0 ^(/.*?)(.*)::\2$
RewriteRule ^old_dir(?:/(.*))?$ %1new_dir/$1 [R=301,L]
</IfModule>
ディレクトリ単位(別ドメイン)
配下のパスを維持したまま、別ドメインのディレクトリへ転送します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^old_dir(?:/(.*))?$ https://www.url.com/new_dir/$1 [R=301,L]
</IfModule>
特定ディレクトリ以下を1ページへ集約(同一ドメイン)
配下のパスは維持せず、すべて同じページへ集約します。/old_dir/ も /old_dir/page.html も /dir_or_page/ へ転送されます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI}::$0 ^(/.*?)(.*)::\2$
RewriteRule ^old_dir(?:/.*)?$ %1dir_or_page/ [R=301,L]
</IfModule>
特定ディレクトリ以下を1ページへ集約(別ドメイン)
配下のパスは維持せず、別ドメインの1ページへ集約します。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^old_dir(?:/.*)?$ https://www.url.com/dir_or_page/ [R=301,L]
</IfModule>
全アクセスを1ページへ集約(同一ドメイン)
そのサイトに来たアクセスをすべて、1つのページへ転送します。元のパスは維持しません。サイト閉鎖時のお知らせページへ集約する場合などに使用します。
転送先が同じサイト内にある場合は、転送先のページ自体を対象から外す必要があります。外さないとそのページが自分自身へ転送され続け、サイトが表示できなくなります。
転送先のパスを2箇所へ同じ内容で書きます。パスにドットが含まれる場合、1つ目の RewriteRule では \. と書いてください。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^dir_or_page/$ - [L]
RewriteCond %{REQUEST_URI}::$0 ^(/.*?)(.*)::\2$
RewriteRule ^(.*)$ %1dir_or_page/ [R=301,L]
</IfModule>
トップページへ転送する場合は、上のコードにある RewriteRule 2行を下記へ置き換え、RewriteCond の行は削除します。サブディレクトリに設置した場合も、転送先はサイト全体のトップページになります。
RewriteRule ^$ - [L]
RewriteRule ^ / [R=301,L]
全アクセスを1ページへ集約(別ドメイン)
そのサイトに来たアクセスをすべて、別ドメインの1ページへ転送します。元のパスは維持しません。転送先が別ドメインのため、除外の指定は不要です。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^ https://other-site.com/dir_or_page/ [R=301,L]
</IfModule>
エラーページ
エラーに対応するHTMLを返す
ステータスコードごとに任意のHTMLを表示します。必要な行だけを使用してください。
- 400 リクエストが不正
- 401 認証に失敗
- 403 アクセス権限がない
- 404 ページが存在しない
- 410 ページを恒久的に削除した
- 500 サーバー内部でエラーが発生
- 502 上位サーバーからの応答が不正
- 503 一時的に利用できない
ErrorDocument 400 /400.html
ErrorDocument 401 /401.html
ErrorDocument 403 /403.html
ErrorDocument 404 /404.html
ErrorDocument 410 /410.html
ErrorDocument 500 /500.html
ErrorDocument 502 /502.html
ErrorDocument 503 /503.html
削除したページに410 Goneを返す
404が「見つからない」であるのに対し、410は「恒久的に削除した」ことを明示します。上記の ErrorDocument 410 と併用すると任意のHTMLを表示できます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^old_page\.html$ - [G,L]
RewriteRule ^old_dir(?:/.*)?$ - [G,L]
</IfModule>
検索エンジンの制御
サイト全体をインデックスさせない
すべてのレスポンスに X-Robots-Tag を付与します。noindexを機能させるには、対象のページがrobots.txtでブロックされておらず、クローラーがアクセスできる状態である必要があります。ブロックされているとヘッダー自体が読まれず、インデックスが残る場合があります。
<IfModule mod_headers.c>
Header always set X-Robots-Tag "noindex"
</IfModule>
PDFをインデックスさせない
PDFのみを対象とします。(?i: の記述により、.pdfと.PDFの両方に対応します。
<IfModule mod_headers.c>
<FilesMatch "(?i:\.pdf)$">
Header always set X-Robots-Tag "noindex"
</FilesMatch>
</IfModule>
指定クローラーのアクセスを拒否
クロール自体を403で拒否します。取得させないため上記のnoindexも届かず、既に検索結果へ登録済みのページは残ります。検索結果から消すことが目的の場合はこの記述ではなくnoindexを使用してください。
User-Agentは送信側が自由に名乗れるため、拒否できるのは正しく名乗るクローラーのみです。名前を偽るボットは素通りします。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (?:Googlebot|Slurp|msnbot) [NC]
RewriteRule ^ - [F,L]
</IfModule>
アクセス制限とファイルの扱い
ドットで始まるファイルへのアクセス拒否
.envや.gitなど、ドットで始まるファイルとディレクトリへのアクセスを拒否します。/.git/config のようなディレクトリ配下も対象です。証明書の発行や更新で使用される .well-known は除外しています。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule (?:^|/)\.(?!well-known/) - [F,L]
</IfModule>
ディレクトリ一覧を表示しない
index.htmlなどのインデックスファイルが存在しないディレクトリで、ファイル一覧が表示されるのを防ぎます。
Options -Indexes
指定拡張子の強制ダウンロード
ブラウザ内で開かず、保存ダイアログを表示させます。対象の拡張子は用途に応じて増減してください。
<IfModule mod_headers.c>
<FilesMatch "(?i:\.(pdf|zip|csv))$">
Header set Content-Disposition "attachment"
</FilesMatch>
</IfModule>
その他の設定
SVGとSVGZのMIMEタイプ
SVGが正しく表示されない場合に指定します。SVGZを使用しない場合、2行目は不要です。
AddType image/svg+xml .svg .svgz
AddEncoding gzip .svgz
HTMLファイルでPHPを動かす
拡張子が.htmと.htmlのファイルでPHPを動作させます。ハンドラ名はサーバーのPHP実行方式によって異なるため、使用前に契約先の案内を確認してください。
AddHandler fcgid-script .htm .html
フロントコントローラー
実在しないファイルとディレクトリへのアクセスを、すべてindex.phpへ内部転送します。転送はサーバー内部で行われ、URLは変わりません。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
</IfModule>
メンテナンスモード
maintenance.htmlのみ通常表示し、その他のアクセスには503を返します。503は一時的な停止を意味するため、メンテナンス中に404や200を返す場合と比べて検索エンジンへの影響を抑えられます。
メンテナンスページがCSSや画像を読み込む場合、それらも503となって読み込めません。該当するファイルやディレクトリを除外条件へ追加してください。特定のIPから通常どおり閲覧したい場合は、IP条件のコメントを外して実際のIPへ変更します。
ErrorDocument 503 /maintenance.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
# RewriteCond %{REQUEST_URI} !^/maintenance/
# RewriteCond %{REMOTE_ADDR} !^192\.0\.2\.10$
RewriteRule ^ - [R=503,L]
</IfModule>

