Apacheの.htaccessで特定のディレクトリへのアクセスを別のURLへリダイレクトする

はじめに

前回の記事のApacheの.htaccessで特定のディレクトリ/ファイルへのアクセスを禁止すると似ているが、今回は別のURLへリダイレクトするようにする。
※部分的に別のサーバに移行する場合を想定して作る。

環境

Windows 11 Professional
Docker Desktop 4.36.0 (175267)
Apache/2.4.62 (Debian)

準備

Apacheの.htaccessで特定のディレクトリ/ファイルへのアクセスを禁止する#準備と同様になる。

public/.htaccessのみ異なるので記載する。

public/.htaccess

public/.htaccess
# mod_rewriteが有効である必要がある

## 特定のディレクトリへのアクセスをリダイレクトする
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^forbidden(/.*)?$ https://google.com [R=301,L]
</IfModule>

# 下記の場合、REQUEST_URI, QUERY_STRINGも引き継ぐ
#<IfModule mod_rewrite.c>
#    RewriteEngine On
#    RewriteRule ^forbidden(/.*)?$ https://google.com%{REQUEST_URI}?%{QUERY_STRING} [R=301,L]
#</IfModule>

リダイレクトについて

public以下のディレクトリ構造

├── public
    ├── access
    │   ├── example.txt
    │   ├── example2.txt
    │   └── test.log
    ├── forbidden
    │   ├── index.html
    │   └── test
    │       └── index.html
    ├── index.html
    └── notaccess
        └── index.html

リダイレクト表

パス結果理由
/index.htmlリダイレクトなし設定に該当しないためリダイレクトされない
/forbidden/index.htmlhttps://google.com にリダイレクトRewriteRule ^forbidden(/.*)?$ https://google.com [R=301,L] に一致
/forbidden/test/index.htmlhttps://google.com にリダイレクト/forbidden ディレクトリ配下であり、^forbidden(/.*)?$ に一致
/forbiddenhttps://google.com にリダイレクトディレクトリ自体のアクセスも ^forbidden(/.*)?$ に一致
/access/example.txtリダイレクトなし設定に該当しないためリダイレクトされない
/notaccess/index.htmlリダイレクトなし設定に該当しないためリダイレクトされない
/forbidden/test.loghttps://google.com にリダイレクト/forbidden 配下であり、RewriteRule に一致
/access/test.logリダイレクトなし設定に該当しないためリダイレクトされない

解説

  • リダイレクトされる条件:

    • RewriteRule ^forbidden(/.*)?$ https://google.com [R=301,L] は、パスが forbidden で始まるすべてのリクエスト(ディレクトリおよびその配下のファイル)にマッチする。

    • リクエストが一致した場合、https://google.com にリダイレクトされる。

  • リダイレクトされない条件:

    • /forbidden 以外のディレクトリやファイルは、この RewriteRule の条件に一致しないためリダイレクトされない。

REQUEST_URI, QUERY_STRINGを引き継ぐ際のリダイレクト表

コメントアウトしている下記を有効にした際のリダイレクト表

.htaccess
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^forbidden(/.*)?$ https://google.com%{REQUEST_URI}?%{QUERY_STRING} [R=301,L]
</IfModule>

この設定では、%{REQUEST_URI} を使って元のリクエスト URI をリダイレクト先の URL に含める。

リクエストパスリダイレクト先理由
/index.htmlリダイレクトなし設定に該当しないためリダイレクトされない
/forbidden/index.htmlhttps://google.com/forbidden/index.htmlRewriteRule ^forbidden(/.*)?$ に一致し、元の URI を引き継いでリダイレクトされる
/forbidden/test/index.htmlhttps://google.com/forbidden/test/index.html/forbidden 配下であり、%{REQUEST_URI} に基づいてリダイレクトされる
/forbidden/test.loghttps://google.com/forbidden/test.log同上
/forbidden/https://google.com/forbidden/ディレクトリ自体のリクエストも引き継がれる
/access/example.txtリダイレクトなし設定に該当しないためリダイレクトされない
/notaccess/index.htmlリダイレクトなし設定に該当しないためリダイレクトされない

解説

  1. %{REQUEST_URI} の役割:

    • REQUEST_URI 変数は、元のリクエストされたパス(クエリ文字列を含む)を表す。

    • これをリダイレクト先に含めることで、元のリクエストパスを新しい URL に引き継ぐ。

  2. クエリ文字列の扱い:

    • ?%{QUERY_STRING} をリダイレクト先に追加することで、元のリクエストに含まれるクエリ文字列が引き継がれる。

    • クエリ文字列がない場合は ? は付加されない。

  3. リダイレクトの動作:

    • /forbidden/ 以下のパスとクエリ文字列が、https://google.com に含まれてリダイレクトされる。

    • 他のパスにはリダイレクトが適用されない。

テスト

.htaccessのテストには以下のWebサイトを使うとよい。

Fill in the url that you're applying the rules to. に テストしたいURLを入れる。
Paste your .htaccess rules into the form.htaccessを入れる。

今回は、https://localhost/forbidden/?id=123 を入れた。

htaccess-01

Output url には、RewriteRuleで書き換えられたURLが出力される。

参考

おわりに

一部のディレクトリのみ別サーバに移動するということがあったため実践してみた。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。