WebSocketのプロキシ

クライアントとサーバの間の接続を、HTTP/1.1からWebSocketに変えるには、HTTP/1.1で利用可能なprotocol switchメカニズムを使います。

しかしながら一つ微妙な考えがあります: "Upgrade"はhop-by-hop ヘッダであり、クライアントからプロキシされるサーバへは渡されないからです。フォワードプロキシを使って、クライアントはこの問題を回避するためにCONNECT メソッドを使うかもしれません。しかしこれはリバースプロキシの場合に動作しません。というのはクライアントはプロキシサーバに気づかずに、プロキシサーバでの特別な処理が必要になるからです。

バージョン 1.3.13から、プロキシされたサーバがコード101(Switching protocols)を返した場合に、nginxはクライアントとプロキシされたサーバの間でトンネルを設定することができる特別なモードの操作を実装しています。クライアントはリクエストの"Upgrade"ヘッダを経由してプロトコルを切り替えるように依頼します。

上で述べたように、"Upgrade" と "Connection" を含む hop-by-hopヘッダはクライアントからプロキシされるサーバへ渡されないため、プロキシされるサーバがクライアントのプロトコルをWebSocketへ切り替えたいという意向を知るためには、それらのヘッダが明示的に渡される必要があります:

location /chat/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

A more sophisticated example in which a value of the “Connection” header field in a request to the proxied server depends on the presence of the “Upgrade” field in the client request header:

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }

デフォルトでは、もしプロキシされたサーバが60秒以内に何もデータを転送しない場合、接続が閉じられるでしょう。このタイムアプト proxy_read_timeout ディレクティブを使って増やすことができます。もう一つの方法として、プロキシされたサーバはタイムアウトを再設定し接続がまだ生きているかを調べるために定期的にWebSocket pingフレームを送信するように設定することができます。

TOP
inserted by FC2 system