HTTPからのリダイレクト
両方で見えている状態は、中途半端
いまサイトは 80 番でも 443 番でも同じ内容を返します。訪問者は http:// でも https:// でも開けてしまいます。
これは望ましくありません。理由は3つです。
- 暗号化されない経路が残っている。フォームに書いた内容は平文で流れる
- 同じ内容が2つの URL で見える。検索エンジンから見ると重複したページになる
- どちらで見ているのかを訪問者が意識できない
アドレス欄に example.com とだけ打つと、ブラウザはまず http:// で繋ぎに行きます。だから 80 番を閉じるのではなく、来た人を 443 番へ案内するという形にします。
案内は 301 で返す
server {
listen 80;
server_name mysite.local;
return 301 https://$host$request_uri;
}return は、そこで処理を打ち切って指定の応答を返す指定です。301 は「このページは恒久的にこちらへ移りました」を意味するステータスコードです。
似たものに 302 があり、こちらは一時的な移動を意味します。HTTPS への案内は当分変わらないので 301 を使います。ブラウザや検索エンジンは 301 を記憶して、次からは最初から新しいほうを見に行きます。逆に言うと、間違えて 301 を返すと訪問者の手元に長く残ります。試している間は 302 にしておく、という慎重なやり方もあります。
変数で行き先を組み立てる
https://$host$request_uri の2つは nginx が用意している変数です。
$host— 訪問者が指定したホスト名$request_uri—/works/index.html?page=2のような、パスと問い合わせをまとめたもの
この2つを繋ぐことで、訪問者が見ようとしていたページにそのまま案内できます。行き先を https://mysite.local/ と直に書いてしまうと、深いページを開こうとした人まで全員トップページに飛ばされます。よくある失敗で、しかも動いてはいるので気づきにくい種類のものです。
server ブロックを2つに分ける
ここまで1つの server ブロックに listen 80 と listen 443 ssl を並べていました。転送を入れるなら、分けます。
server {
listen 80;
server_name mysite.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mysite.local;
ssl_certificate /etc/ssl/certs/mysite.crt;
ssl_certificate_key /etc/ssl/private/mysite.key;
root /var/www/mysite;
index index.html;
...
}1つ目は案内だけをする、中身を持たないブロックです。root も location も要りません。3章で書いた location や error_page は、すべて 443 番のほうへ移します。
分ける理由は、同じブロックに両方を書くと「暗号化なしで来たときだけ転送する」という条件分岐が必要になり、書き方が回りくどくなるからです。番号ごとにブロックを分けたほうが、何をするブロックなのかが読んで分かります。
転送されたことを確かめる
curl -sI http://localhost/
# HTTP/1.1 301 Moved Permanently
# Location: https://localhost/-I はヘッダーだけを見る指定です。Location に行き先が入っています。
案内に従って最後まで追いかけたいときは、こう書きます。
curl -kL http://localhost/-L が、返ってきた Location を追いかける指定です。自己署名なので -k も要ります。これでトップページの中身が返れば、転送の連なりが最後まで通っていると分かります。
手を動かす
server ブロックを2つに分け、80 番に来た訪問者を 443 番の同じページへ案内します。深いパスでも行き先が保たれることまで確かめます。