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]

https://github.com/Worlize/WebSocket-Node/wiki/Documentatio