Apache で 307 リダイレクトを設定する方法|Redirect・RedirectMatch・mod_rewrite
Apache HTTP Server でリダイレクトを設定する方法は、一つではありません。mod_alias の Redirect、正規表現を使う RedirectMatch、そして mod_rewrite の RewriteRule。どれも「別の URL へ案内する」という目的は同じですが、番号の指定のしかたと得意な場面が違います。
とくに 307 については、Redirect に temp と書いても 302 が返ってきて、「307 はどう書くのか」と悩む場面が目立ちます。この記事では、Apache の公式文書の記載に沿って、307 を返す書き方と、それぞれの特徴、つまずきやすい点を整理します。確認日は 2026 年 10 月 9 日です。
Redirect
Redirect 307 /old URL と、数値で番号を指定します。
RedirectMatch
正規表現で、複数のパスをまとめて転送できます。
mod_rewrite
[R=307,L] で番号を指定します。条件分岐が得意です。
確認
apachectl configtest で構文を検査し、curl -I で応答を見ます。
キーワードに 307 が無いという落とし穴
mod_alias の Redirect には、番号の代わりに使えるキーワードがあります。公式文書の一覧は次のとおりです。
| キーワード | 返される番号 |
|---|---|
permanent |
301(恒久的な転送) |
temp |
302(一時的な転送。既定) |
seeother |
303(See Other) |
gone |
410(削除済み。転送先 URL は書かない) |
見てのとおり、307 や 308 に対応するキーワードはありません。さらに、番号を省略すると、一時的な転送として 302 が返されます。「一時的な転送だから 307 になるはず」と思い込んで Redirect temp と書いても、実際には 302 になります。メソッドを保ちたい意図で設定した場合は、気づかないうちに仕様と食い違うことになります。
もう一つの落とし穴は、.htaccess で使えるかどうかです。公式文書によれば、Redirect の Override は FileInfo です。サーバー全体の設定で AllowOverride が許可されていないと、.htaccess に書いても無視されるか、エラーになります。共用のサーバーを使っている場合は、事前に確認が必要です。
数値で番号を指定する
では、307 はどう書くのでしょうか。公式文書には、キーワードの代わりに数値のステータスコードを指定できると書かれています。条件は次の 3 つです。
- 300〜399 の範囲のコードを指定する場合は、転送先 URL が必須です。
- それ以外の範囲のコードを指定する場合は、転送先 URL を書いてはいけません。
- コードは、Apache が知っている有効な HTTP ステータスコードでなければなりません。
Apache のソースコード(httpd.h)では、307 と 308 は HTTP_TEMPORARY_REDIRECT、HTTP_PERMANENT_REDIRECT として定義されています。したがって、数値で指定できます。
# 一時的な転送(メソッドを保つ)
Redirect 307 "/old-page" "https://example.com/new-page"
# 恒久的な転送(メソッドを保つ)
Redirect 308 "/old-page" "https://example.com/new-page"
Redirect の挙動の特徴
公式文書に書かれている Redirect の性質のうち、実務で影響が大きいものを挙げます。
パスの一致は「完全なセグメント」単位
「完全なパスのセグメントだけが一致する」と文書にあります。Redirect 307 /old ... と書いた場合、/old と /old/page は対象になりますが、/older は対象になりません。
追加のパスと引数は引き継がれる
転送先の URL の後ろに、一致した部分より後ろのパスと、GET の引数が自動で付け足されます。たとえば Redirect 307 /service http://foo2.example.com/service と設定した場合、/service/foo.pl?q=23&a=42 は http://foo2.example.com/service/foo.pl?q=23&a=42 に転送されます。パスの付け足しを意識して転送先を書かないと、/new/new/... のように二重になることがあります。
優先順位
Redirect は、Alias や ScriptAlias より、書いた順序に関わらず優先されます。
POST についての注記
公式文書には「POST は破棄される」という注記があります。POST を保つ目的で使う場合は、実際の環境で動作を確認してください。本サイトでは、この点の挙動を公式文書以外では確かめていないため、断定を避けています。
正規表現で複数を一括転送する RedirectMatch
「/blog/ 配下をまとめて新しい場所へ」のように、パターンで転送したい場合は RedirectMatch を使います。公式文書では、Redirect に相当し、単純な前方一致の代わりに正規表現を使うものと説明されています。構文は次のとおりです。
RedirectMatch [status] regex URL
status には Redirect と同じキーワードや数値が使えます。正規表現の括弧で取り出した部分は、転送先の URL に $1 のように埋め込めます。公式文書も、パス全体に一致させるために、正規表現を ^ と $ で挟むよう推奨しています。
# /blog/ 以下を、別ドメインの同じパスへ一時転送(メソッドを保つ)
RedirectMatch 307 "^/blog/(.*)$" "https://blog.example.com/$1"
RedirectPermanent と RedirectTemp という略記もあります。ただし、これらは Redirect permanent と Redirect temp と等価で、返るのは 301 と 302 です。307 や 308 は、数値で指定する書き方を使ってください。
mod_rewrite で 307 を返す
条件によって転送したい場合は、mod_rewrite の RewriteRule を使います。公式文書によれば、R フラグは、有効な HTTP ステータスコードをすべて指定できます。指定がなければ 302 が使われます。
RewriteEngine On
RewriteRule "^/old/(.*)$" "https://example.com/new/$1" [R=307,L]
書き方のポイントは次のとおりです。
R フラグは L とセットで使う
公式文書は、R を単独で使うと、http://ホスト名 を URL パスの前に付けたものを次のルールに渡すため、「Invalid URI in request」という警告が出ることがあるとして、[R,L] の組み合わせを推奨しています。307 でも同様に [R=307,L] と書きます。
不明な番号は 500 になる
文書には、HTTP の仕様に含まれない番号を指定すると、500 エラーになり、エラーログに記録されるとあります。数値は正確に書きます。
クエリ文字列の扱い
公式文書によれば、置換後の文字列に ? が含まれていない場合、元のクエリ文字列はそのまま引き継がれます。? を含めると、その後ろが新しいクエリになり、元のクエリは付きません。元のクエリを残したまま新しいクエリを加えるには QSA、クエリを消すには QSD を使います。
# クエリをそのまま引き継ぐ(何もしなくてよい)
RewriteRule "^/old$" "https://example.com/new" [R=307,L]
# クエリを消す
RewriteRule "^/old$" "https://example.com/new" [QSD,R=307,L]
.htaccess での注意点
.htaccess の中で RewriteRule を使うと、動作が少し変わります。公式文書の要点は次のとおりです。
RewriteEngine Onに加え、OptionsでFollowSymLinksかSymLinksIfOwnerMatchが有効である必要があります。- 照合するパスから、
.htaccessがあるディレクトリまでが取り除かれます。そのため、パターンの先頭に/を付けると一致しません。^localpathの形で書きます。 - 相対的な置換先を使う場合は、
RewriteBaseが必要になることがあります。
# /var/www/html/app/.htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteBase /app/
# /app/old/page?x=1 → /app/new/page?x=1 (307)
RewriteRule ^old/(.*)$ new/$1 [R=307,L]
3 つの方法の使い分け
| 方法 | 向いている場面 | 307 の書き方 |
|---|---|---|
Redirect |
1 つのパスを固定の URL へ転送する | Redirect 307 パス URL |
RedirectMatch |
パターンで複数のパスをまとめる | RedirectMatch 307 正規表現 URL |
RewriteRule |
条件(ホスト名、環境変数など)で分岐する | [R=307,L] |
単純な転送なら Redirect で十分です。設定が増えたら RedirectMatch、条件が絡むなら RewriteRule と、必要に応じて切り替えます。ひとつの設定ファイルに Redirect と RewriteRule が混在すると、処理の順序が分かりにくくなり、意図しない転送が起きることがあります。どちらかに統一すると、見通しがよくなります。
設定の確認方法
設定を反映する前に、構文を確認します。
apachectl configtest
Syntax OK と表示されたら、設定を読み込み直します。
apachectl graceful
そのあとで、curl を使って実際の応答を確認します。
curl -I https://example.com/old-page
HTTP/1.1 307 Temporary Redirect
Location: https://example.com/new-page
番号が 302 になっている場合は、Redirect の番号の指定が抜けていないか、別の設定が先に処理していないかを確認してください。パスの二重化やクエリの欠落も、Location の値から読み取れます。
Apache で 307 を返すための要点
Redirectのキーワードに 307 は無い。数値でRedirect 307と書く。- 番号を省略すると 302 になります。意図するなら必ず番号を書きます。
- パターンで転送するなら
RedirectMatch、条件で分岐するならRewriteRuleの[R=307,L]を使います。 .htaccessでは、AllowOverrideとOptionsの許可が必要で、パターンの書き方も変わります。- 反映前に
apachectl configtest、反映後にcurl -Iで確認します。
同じ転送を nginx や PHP で書く場合は、nginx での設定、PHP での設定もあわせて確認してください。