Nginx+Socket.ioにおけるエラーの原因と対応+α

938
NO IMAGE

現象

ある時からGrowiに次のようなエラーが連続で出ていました。

対応&解決法

  1. growiの問題かと思い、ネットで検索してみました。
    どうやら、growiではなく、リバースプロキシの設定に問題がありそうです。
  2. 似たような問題に対処している方がいたので、Nginxへその通りの設定をしてみたところ、問題の現象は収まりました。
location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_bypass $http_upgrade;
    proxy_set_header Host $host;
    proxy_pass http://{IPアドレス}:{ポート番号};
}

location /socket.io/ {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_bypass $http_upgrade;
    proxy_set_header Host $host;
    proxy_pass http://{IPアドレス}:{ポート番号};
}

めでたしめでたし

もう少し続けてみる

↑のまま終わると面白くないので、勉強がてら、もう少し調査しました。

この現象は、解決法を示してくれた人の記事の中でも言われていますが、問題は

WebSocket接続のハンドシェイク時に HTTP/1.1 101 (Switching Procotols) というステータスコードと Hop-by-Hopヘッダ を使用してWebSocket通信への切り替えを行う仕様に Nginx v1.3.13 から変更されたらしい。

にあったようです。

Hop-by-Hopヘッダとは、キャッシュからの応答の構築を目的として、キャッシュまたは非キャッシュプロキシの動作を定義するHTTPヘッダの一つです。

Hop-by-hopヘッダー:単一のトランスポートレベルの接続でのみ意味を持ち、キャッシュに保存されたり、プロキシで転送されたりしません。

Nginxの変更理由

クライアントとサーバー間の接続を HTTP/1.1 から WebSocket に変更するには、HTTP/1.1 で利用可能なプロトコルスイッチメカニズムを使用します。

"Upgrade "や "Connection "などのホップバイホップのヘッダは、クライアントからプロキシサーバには渡されないため、プロキシサーバがクライアントのプロトコルをWebSocketに切り替える意図を知るためには、これらのヘッダを明示的に渡す必要があります。

プロキシサーバーからクライアントのプロトコルをwebsocket通信に切り替えるための対応が今回の対応の意味でした。

雑記

HTTPの歴史も調べてみると面白そうだなと思いました。