ドメイン名変更時のリダイレクトを Rails のルーティングで設定する
結論
Ruby on Rails アプリケーションで old.example.net
へアクセスがあった場合に、パスを維持したまま new.example.com
へ 301 リダイレクトしたければ、routes.rb
の先頭に以下を追加すればよい。
constraints host: 'old.example.net' do
get '/(*path)', to: redirect { |path_params,| "https://new.example.com/#{path_params[:path]}" }
end
背景
Heroku の無料プランで個人開発 Rails アプリを herokuapp.com
のドメインを利用して動かしている。Heroku 無料プラン廃止のリリース を受け、将来スムーズに別のインフラへ移せるよう、カスタムドメインへ移行することにした。
自分でコントロールできるのであれば、移行前 URL から移行先 URL へのリダイレクトはアプリケーションよりも前段で行いたいところである。しかし、https://reinteractive.com/posts/504-how-to-redirect-a-rails-application-to-a-new-domain-name より、
カスタムドメインを設定しても、アプリの Heroku ドメインは常にアクティブなまま維持されます。ユーザーがカスタムドメインのみ使用するようにする場合は、アプリから HTTP ステータスコード 301 Moved Permanently を送信して、Web ブラウザにカスタムドメインの使用を指示する必要があります。
とのことなので、Heroku ではアプリケーションでリダイレクトする必要があった。
検討
ググった結果、Rails ガイドの「Rails のルーティング」と合わせて以下の記事を参考にした。
なぜ get '*path'
や redirect('https://new.example.com/%{path}')
といった書き方ができないかはこちらを参照してほしい。
他に、rack-rewrite gem を使う方法も数多く紹介されていた。より前段の Rack で処理する方がオーバーヘッドを減らせるので、トラフィックの多いアプリケーションなどではこちらの方法がよいだろう。しかし、依存が増える点、かつ、処理が追いにくく記述も複雑になる点から、シンプルな routes.rb
に書く方法を採用することにした。
ApplicationController
の before_action
フィルタで処理する方法も見かけたが、routes.rb
で処理した方がシンプルかつオーバーヘッドも少ない。
ちなみに、裏SF創作講座というサービスで実際にこのコードを使用している。
Discussion