WebSocket URIの謎
疑問
RFC6455ではwebsocketのURIスキームが定められている。これは通常のURIと同じ形式で、たとえばこんな風に記述される。
ws://example.com:3000/foo
ところでWebSocketという言葉の印象から判断すると、これはソケットであるからホストアドレスとポート番号さえ指定すれば、接続先は一意に決まってしまいそうな気がする。そうするとこのURIの最後にくっついているpath部分"/foo"は何に使うのだろうか?
調査
JavaScriptでコードを書いてみる。クライアンからサーバへの接続リクエストはこのようになる。
var ws = new WebSocket("ws://example.com:3000/foo");
この接続リクエストを受けるサーバは、こんな風になる。コードは省略しているが、このWebSocketServerオブジェクトは3000番のポートでlistenしている。
webSocketServer.on('request', function (req) { console.log("Request resource: " + req.resource);
クライアントから接続要求があると、WebSocketServerオブジェクトの requestイベントのハンドラにはWebSocketRequestオブジェクトが渡ってくる。WebSocketRequestのresourceプロパティにクライアントが指定したURIのpath部分が入ってる。HTTPからWebSocketへ昇格するときのHTTPヘッダのやりとりを観察すると以下のようになっている.
クライアントからのリクエスト GET /foo HTTP/1.1 Host: localhost:3000 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Sec-WebSocket-Version: 13 Origin: http://localhost:3000 Sec-WebSocket-Key: VSDuTDuniJF2SmiyhVPenA== Connection: keep-alive, Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket サーバからのレスポンス HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: 7TcssaQZrihZ2PPVX4P5Yd3sQfI= Origin: http://localhost:3000
結論
クライアントからの接続リクエストのHTTPのハンドシェイクのGETメソッドの引数としてpathが渡っている.つまりWebSocketのサーバーは,これをみていろいろ挙動を変えられるということになる.WebSocketとは,ソケットという名前から(原始的なソケットという)誤った印象を持ってしまいそうだが,メッセージのフレームをちゃんと管理してくれるとか,アプリケーションを作る上で便利な機能がそろっているのであった.
[参考URL]