こんにちは。アプリケーションエンジニアのid:tkzwtksです。もうあと数時間で2022年も終わりですが、皆様いかがお過ごしでしょうか。2023年という新しい年に心機一転、なにか新しいことを始めようと考えているという方も、それに向けて準備を進めている方もいらっしゃると思います。
新しいといえば(と言っても半年前ですが)、はてなのサービス開始から20周年のさまざまな出来事の一環として、6月にはてなのコーポレートサイトをリニューアルし、このタイミングでコーポレートサイトのドメインもhatenacorp.jp
からhatena.co.jp
へ変更されました。
今回はこのドメイン変更作業にて発生したリダイレクトについて、リダイレクトの一般的な話と実際にやったことをご紹介します。
リダイレクトパターン
一言で旧サイト(旧URL)から新サイト(新URL)へのリダイレクトと言っても、考えるべきことは少なくありません。リダイレクトするパターンとしてはざっくり以下が挙げられるでしょう。
- 新旧でドメインが変わるがパスは変わらない
- 新旧でドメインは変わらないがパスが変わる
- 新旧でドメインもパスも変わる
1のパターンでは、旧ドメインで受けたリクエストについて、ドメイン以外を維持したまま新しいドメインにリダイレクトするだけで良いので考慮することも少なく、処理としても難しくありません。2のパターンではドメインは変化がないものの、パスの変わり方によって考慮することが変わりますが、3よりは難しくないでしょう。3のパターンではURLが全く違うものになります。実装例としては、1のパターンと同様にリクエストのドメイン以外を維持したまま新しいドメインにリダイレクトして、リダイレクト先で新しいパスにもう一度リダイレクトするなどの方法が考えられます。
パスが変わる場合でも、以下のようにパターンがありそうです。
- A: パスの構造が少し変化する・一部が別の文字列に置き換わる
- 例1)
/genre/entry
->/genre/subgenre/entry
- 例2)
/genre/entry
->/category/entry
- 例1)
- B: 動的に決まっていたURLが別の動的に決まる文字列に変わる
- 例)
/entry/{id}
->/entry/{new_id}
# 動的に払い出されているidが新しいidに変わる
- 例)
Aのパターンではパスの一部を変更させるだけなので、変更するパターンだけ決めるだけでよく、リダイレクトのためのアプリケーションロジックは必要ありません。一方BのパターンはユーザーのアクションでURL中のIDが払い出されるようなサービスを想定しています。何らかの理由でIDが変わるような場合、その紐付けロジックが必要になるでしょう。
ここまでは、リダイレクト処理であり得るパターンを整理しました。
hatenacorp.jp から hatena.co.jp へ
ここからは実例として、hatenacorp.jp
からhatena.co.jp
へのリダイレクトを紹介します。と言っても新旧URL間で変更になるのはドメインだけでパスは維持するという、前項で挙げた最初のパターンでした。はてなのサービスの多くはリクエストをリバースプロキシで受けているため、旧ドメインのリバースプロキシでリダイレクト処理をしたらよいはずですが、コーポレートサイトは実はAWS Amplifyで動いており、リダイレクト処理を追加できそうなリバースプロキシは存在していません。この場合、リダイレクト処理のために取り得る選択肢は以下のようになると考えました。
- リダイレクト用のリバースプロキシなどを新規に立てて、
hatenacorp.jp
へのアクセスをそちらに向ける - リダイレクト用のアプリケーションを用意して、
hatenacorp.jp
へのアクセスをそちらに向ける
今回の事例では1番目の選択肢を選びました。ドメインだけではなくパスも変化し、且つ古いパスから動的に新しいパスが決まる(前項のBのようなパターン)のであれば2番目の選択肢を選ぶでしょう。また必要とはいえ、ただリダイレクトするだけのリバースプロキシを新規に立てて運用するのも、メンテナンスコストの観点からするとあまり嬉しくありません。そこで今回はAWSのApplication Load Balancer(ALB)をリダイレクタとして利用しています。ALBを立てるのは簡単で、ALBを利用することで、リバースプロキシそのもののアップデート等のメンテナンスからは解放され、基本的には放っておいていいはずです。また、アクセスログも記録できるため、実際に使われているかどうか、使われなくなってきているかの判断もしやすいと考えました。
AWS CDKを利用してリダイレクタを作る
ALBでリダイレクタを作るのにはAWS CDK を利用しました。大したものではないのでコンソールから作ってもよいですが、コードにしておくことでgit等で管理できるようになったり、他でも同じようなことをしたい時に使いまわせるなどのメリットがあります。以下が簡易なコードです。
export class Redirector extends Stack { constructor(scope: Construct, id: string) { super(scope, id) const alb = new ApplicationLoadBalancer(this, 'redirector', { vpc: Vpc.fromLookup(this, 'vpc', { vpcId: 'vpcid', }), internetFacing: true, loadBalancerName: 'redirector', }) const defaultAction = ListenerAction.fixedResponse(404, { contentType: 'text/plain', messageBody: 'not found', }) const action = ListenerAction.redirect({ host: 'hatena.co.jp', permanent: true, }) const conditions = [ListenerCondition.hostHeaders(['hatenacorp.jp'])] const listener = alb.addListener('listener', { certificates: [...], port: 443, open: true, defaultAction, }) listener.addAction('redirectAction', { priority: 20, conditions, action, }) } }
パスなどを維持したままリダイレクトするリダイレクタを作るコード自体がこれくらいで書けるのが良いですね。
もし移行先でもALBを使っていたりリバースプロキシが立っているのであれば、それらを使っても問題ありません。今回新しく立てたのは、移行先に移行元の知識を入れたくはないのと、しばらくしたら捨てることも考慮して、新規でALBを立てています。正直これらはどちらでもよいと思います。
hatena.co.jp への切り替え
事前にALBのリダイレクタを設定しておいたので、切り替え当日はDNS設定を切り替えるだけでした。初めは302 Found
の一時的なリダイレクトにしておいて、問題ないことが確認できたら301 Moved Permanently
の永続的なリダイレクトに切り替える方法を取りました。こうすることで、リダイレクト処理に何かしら問題があった場合でも、Google等の検索エンジンのインデックスに影響させずに済むはずです。全てのページについて問題なくリダイレクトされていることを確認したのちに、改めて301リダイレクトを設定し、切り替えを完了しました。
終わりに
リダイレクトのパターンをまとめ、リダイレクタの準備やリリース作業についてご紹介しました。また、このエントリではアプリケーションレイヤーでリダイレクトするやり方には触れませんでしたが、そういう処理が必要になった場合、今回の事例のようにリダイレクタを別に新規に作るのが、後々メンテナンスもやりやすくなるのではないかなと考えています。
余談ですが、現在 https://www.hatena.ne.jp ははてなのポータルサイトとして、はてなサービスでの注目エントリが一覧できるようになっていますが、はてなのコーポレートサイトも昔はwww.hatena.ne.jp
ドメインでサービスされていました。例えば2009年のインターンレポートサイトは https://www.hatena.ne.jp/company/intern2009/index.html というURLでしたが、2回のURL変更を経て、現在は https://hatena.co.jp/intern2009/index.html となっています。リニューアルによって過去のURLにアクセスできなくなるということが無いよう、リダイレクト処理を残しています。
Cool URIs don't change.という言葉があるように、将来のURLの変更ができるだけ発生しないように設計したいですが、やむなく変更せざるを得ない場合もあるでしょう。その場合にはリダイレクト処理が必要になるかもしれません。今回ご紹介した方法は低コストで維持できるリダイレクト処理だと考えています。必要になった時にこのエントリのことを思い出してもらえたら幸いです。
ということで、このエントリははてなエンジニア Advent Calendar 2022の31日目のエントリでした。そして2022年のHatena Developer Blogは、おそらくこれが最後のエントリになると思います。皆様良いお年をお迎えください。2023年もよろしくお願いします。