WordPress が黙って行っていた転送を、止める前に洗い出す方法
「x-redirect-by: WordPress」は、WordPress が PHP の中で転送した時に付く応答の見出しです。.htaccess に転送の行が無いのに古い URL が転送されていたら、正体は WordPress 自身。止めると全部消えるので、curl で見分けて .htaccess に書き直した手順です。

「x-redirect-by: WordPress」とは、WordPress が PHP の中で転送(リダイレクト)した時に、応答に付ける見出しです。.htaccess に転送の行が無いのに古い URL が転送されていたら、転送しているのは WordPress 自身で、WordPress を止めた瞬間にすべて消えます。curl で見出しを確かめて洗い出し、止める前に .htaccess の RewriteRule に書き直しました。
会社のサイトを WordPress から静的なサイトへ移す準備をしていた時のことです。古い URL の転送の一覧を作っていて、おかしなことに気づきました。
アプリのプライバシーポリシーの古い URL(/talklens/privacy/ など)を開くと、ちゃんと新しい /privacy/ へ転送されます。ところが、サーバーの .htaccess を見ても、転送の行は1つもありません。書いてあったのは、WordPress が自動で書く「ファイルが無ければ index.php へ渡す」という数行だけでした。
転送していたのは、WordPress 自身でした。ということは、WordPress を止めた瞬間に、この転送はすべて消えます。この記事は、そうした「WordPress が黙って行っていた転送」を、止める前に洗い出して .htaccess に書き直した記録です。
転送の持ち主を見分ける:x-redirect-by
転送が .htaccess(サーバー)から来ているのか、WordPress から来ているのかは、応答の見出しで見分けられます。WordPress が PHP の中で転送する時は、「x-redirect-by: WordPress」という見出しを付けて返します。
curl -sI https://あなたのドメイン/talklens/privacy/ | grep -iE '^(HTTP|location|x-redirect-by)'ここで x-redirect-by: WordPress が出たら、その転送は WordPress がしています。.htaccess の RewriteRule による転送には、この見出しは付きません。

WordPress がしていた転送は4種類あった
調べていくと、WordPress が黙って行っていた転送は、大きく4種類ありました。どれも、WordPress の設定画面で自分で作った覚えのないものです。

1. www 付きから www なしへの転送
https://www.ドメイン/ を開くと、www なしのアドレスへ転送されていました。WordPress は、設定にある「サイトのアドレス」と違うホスト名で開かれると、設定のアドレスへ転送します。サーバーの設定ではなかったので、WordPress を止めると www 付きのアドレスはそのまま新しいサイトを表示し、同じページが2つの住所で見える状態になります。
2. 似た名前のページへの自動の転送
存在しない URL を開かれた時、WordPress は「名前の似たページ」を探して、見つかればそこへ転送します。/talklens/privacy/ が /privacy/ へ転送されていたのは、これでした。私たちが意図して作った転送ではありませんが、アプリの中のリンクには、こうした古い URL を向いているもの(Shade Preview の /shade-preview/privacy/)があり、結果として大事な転送になっていました。
3. ?p= の短い URL
WordPress のページには、?p=番号 という短い URL もあります。ページの番号は、ページの HTML の中にある shortlink(短いリンク)にも書かれています。短い URL で開くと、WordPress がそのページの URL へ転送します。
4. URL の書き方のゆれ
末尾の / が無い URL などを、WordPress が正しい形へそろえて転送することもあります。静的なサイトでは、フォルダの URL の末尾に / を付ける転送を、自分で書く必要があります。

洗い出しの手順

開かれる可能性のある古い URL を集める
WordPress が作る wp-sitemap.xml に載っている URL、トップページのリンク、アプリの中から開くリンク(プライバシーポリシーやサポートのページ)を集めます。アプリのリンクは、アプリの設定画面やストアの情報から拾います。
1つずつ curl で開き、転送の持ち主を見る
集めた URL を、www 付き・http・末尾の / のあり無しの形でも開き、応答の番号、転送先、x-redirect-by の有無を記録します。
Macで実行for u in /talklens/privacy/ /kaitori-base/privacy/ /shade-preview/privacy/; do \ printf '%s ' "$u"; curl -s -o /dev/null -D - "https://あなたのドメイン$u" \ | grep -iE '^(location|x-redirect-by)' | tr -d '\r' | tr '\n' ' '; echo; done?p= の番号を調べる
外から短い URL で開かれていそうなページは、HTML の中の shortlink で番号を調べ、?p=番号 で開いて転送先を確かめます。
Macで実行curl -s https://あなたのドメイン/ページ/ | grep -o "rel=['\"]shortlink['\"][^>]*"行き先を決めて、一覧にする
古い URL ごとに、新しいサイトでの行き先を決めます。プライバシーポリシーの3つは、ただ /privacy/ へ送るのではなく、新しいページの中の各アプリの付録の位置(/privacy/#talklens など)へ送ることにしました。
.htaccess に書き直す
洗い出した転送を、新しい .htaccess に1つずつ書きました。前の記事に書いたとおり、この .htaccess は Mac の Apache で試してから使っています。


RewriteEngine On
# 1. www 付きを www なしへ
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# 2. アプリのプライバシーポリシーの古いURL を、付録の位置へ(NE は # をそのまま使うため)
RewriteRule ^talklens/privacy/?$ https://example.com/privacy/#talklens [R=301,NE,L]
# 3. 番号の分かっているページの短いURL を、そのページへ(?以降は消す)
RewriteCond %{QUERY_STRING} (^|&)(p|page_id)=268(&|$)
RewriteRule ^(index\.php)?$ https://example.com/talklens-support/ [R=301,QSD,L]
# ほかの ?p= などは、?以降を消したトップへ
RewriteCond %{QUERY_STRING} (^|&)(p|page_id|cat|author|m)=[0-9]
RewriteRule ^(index\.php)?$ https://example.com/ [R=301,QSD,L]
# 4. 実在するフォルダの URL に、末尾の / を付ける
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ https://example.com/$1/ [R=301,L]止めたあとに確かめる
WordPress を止めたあと、同じ URL をもう一度 curl で開きました。転送が同じ行き先へ返っていること、そして x-redirect-by: WordPress が出なくなったこと(転送の持ち主が .htaccess に移ったこと)を確かめます。

curl -s -o /dev/null -D - https://asteroid-technology.com/talklens/privacy/ | grep -iE '^(HTTP|location|x-redirect-by)'
HTTP/2 301
location: https://asteroid-technology.com/privacy/#talklens
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://www.asteroid-technology.com/
301 https://asteroid-technology.com/
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' 'https://asteroid-technology.com/?p=268'
301 https://asteroid-technology.com/talklens-support/まとめ
WordPress は、私たちが設定画面で作った覚えのない転送を、いくつも黙って行っていました。止める前にやることは、次の3つです。

- 開かれる可能性のある古い URL を集め、www・http・末尾の / のゆれも含めて curl で開く
- x-redirect-by: WordPress の見出しで、転送の持ち主を見分ける
- WordPress がしていた転送を、行き先を決め直して .htaccess に書き、止めたあとにもう一度開いて確かめる
移行の全体の流れは、こちらの記事にまとめています。
ホームページ制作WordPress から静的サイトへ、社名で検索1位を守ったまま移行した全手順会社のサイトを WordPress から静的サイト(HTML のファイルを置くだけのサイト)へ移した全手順です。社名で検索1位を守るための 301 リダイレクトの洗い出し、バックアップ、誰にも見せないリハーサル、表示を止めない切り替えの順番、すぐ戻せる作りまでを、実際の手順書から書きます。
この記事は、AI(Claude)の支援を受けて作成し、筆者が内容を確認しています。

