Heroku×Railsで独自ドメインに rack-rewrite でリダイレクトさせる

Herokuで独自ドメインを設定しても`xxx.herokuapp.com`でアクセスできてしまう。これを解決する定番の方法は[rack-rewrite](https://github.com/jtrupiano/rack-rewrite)というGemを使うこと。玄人の方はこのGemを使わずに独自でコードを書くらしいが一旦定番の方法でやった。ちなみに`.htaccess`はHerokuでは使えない

## rack-rewrite を bundle install
https://github.com/jtrupiano/rack-rewrite

まずは毎度おなじみのGemのインストール。
Gemfileに`gem 'rack-rewrite'`を追記し、ターミナルでプロジェクトのディレクトリに移動し`bundle install`する。

## 最終的なコード

下記で本アプリへのすべてのアクセスが恒久的に`https://mynewdomain.com`に飛ぶ（SSL化している前提）。`xxx.herokuapp.com`だけでなくhttpでもwwwありでも全部飛ばしてくれるようだ。

```config.ru

# This file is used by Rack-based servers to start the application.

require_relative 'config/environment' # ←元からあるコード

gem 'rack-rewrite', '~> 1.5.0'
require 'rack/rewrite'

if ENV['RACK_ENV'] == 'production'
    use Rack::Rewrite do
        r301 %r{.*}, 'https://mynewdomain.com$&', :if => Proc.new {|rack_env|
           rack_env['SERVER_NAME'] != 'mynewdomain.com'
        }
    end
end

run Rails.application # ←元からあるコード。これより上に書かないといけないはず
```


## Heroku×Railsにおけるrack-rewriteの基本

```config.rb
gem 'rack-rewrite', '~> 1.5.0' # ここはいるっぽい
require 'rack/rewrite' # ここはいるっぽい

use Rack::Rewrite do
  # ↓ ここにリライトルールやリダイレクトルールを書く
  rewrite   '/wiki/John_Trupiano',  '/john'
  r301      '/wiki/Yair_Flicker',   '/yair'
  r302      '/wiki/Greg_Jastrab',   '/greg'
  r301      %r{/wiki/(\w+)_\w+},    '/$1'
  # ↑ ここにリライトルールやリダイレクトルールを書く
end
```

しかし`rewrite`や`r301`のコードは相対パスのリダイレクトしかできないよう。今回はREAD.MEの CNAME alternative の項目にある書き方を使う。

> CNAME alternative
In the event that you do not control your DNS, you can leverage Rack::Rewrite to redirect to a canonical domain. In the following rule we utilize the $& substitution operator to capture the entire request URI.

> ```config.ru
r301 %r{.*}, 'http://mynewdomain.com$&', :if => Proc.new {|rack_env|
   rack_env['SERVER_NAME'] != 'mynewdomain.com'
}
```

なのでHeroku環境で`xxx.herokuapp.com`→`mynewdomain.com`に301リダイレクトさせるコードはこう！

```config.rb
gem 'rack-rewrite', '~> 1.5.0'
require 'rack/rewrite'

use Rack::Rewrite do
    r301 %r{.*}, 'http://mynewdomain.com$&', :if => Proc.new {|rack_env|
       rack_env['SERVER_NAME'] != 'mynewdomain.com'
    }
end
```

### ちょっと難しい余談
CNAMEというのは Canonical NAME の略で、一般的にDNSのCNAMEレコードとして有名な用語。カノニカルURL（正規URL）を別ドメインに指定するときに本来はDNS設定からCNAMEレコードを設定するが、Herokuでは我々ユーザーはそこをいじれないから`config.ru`で設定する方法だよ、という意味で`CNAME alternative`という項目名になっているようだ。

## localhostではリダイレクトしないようにする

しかし上記のままでは`localhost:3000`でアクセスしてもリダイレクトされてしまうらしく、if文でproduction環境のときだけ発動するようにする。よって最終的にこうなる。

```config.ru
gem 'rack-rewrite', '~> 1.5.0'
require 'rack/rewrite'

if ENV['RACK_ENV'] == 'production'
    use Rack::Rewrite do
        r301 %r{.*}, 'http://mynewdomain.com$&', :if => Proc.new {|rack_env|
           rack_env['SERVER_NAME'] != 'mynewdomain.com'
        }
    end
end
```

ドメインの末尾に`$&`が付いてるのは、例えば`https://xxx.herokuapp.com/about`でアクセスしてきたときに`https://mynewdomain.com/about`に飛ばしてやるための変数？的なアレらしい。

## rack-rewriteのREAD.MEの日本語訳
https://gist.github.com/udzura/972903

## SSLリダイレクトはこちら
http→httpsのリダイレクトだけをやりたい場合はこちら（本Qiitaのコードを使っていれば下記を設定せずともhttpsに飛ばしてくれるはず）。
https://qiita.com/maztak/items/0e682084db275c931c13

##参考
- https://blog.ruedap.com/2011/05/17/ruby-heroku-domain-redirect-rack-rewrite