PubSubHubbubとWebSocketsとクライアントサイドのjavascript

ここのところwebのことからはさっぱりはなれてたのでTwitter / Ken Nishimura: PubSubHubbubがWebhookよりいい点って …をきっかけにクライアントサイドのjavascriptでなにかするという観点からPubSubHubbubとWebhookとWeb Socketについて調べた。

PubSubHubbub+ReverseHttp

Twitter / mala: @knsmr webhookは概念でpubsubhubbubは具体的なプロトコル仕様。

HTTP PubSub: Webhooks & PubSubHubbub – igvita.comの下の方にあるgoogle docsの資料と(関係ないけどこれflashだとおもったらiframe+HTMLでできてて驚いた)、仕様そのものDraft: PubSubHubbub Core 0.1 — Working Draftをざっと見るのがわかりやすかった。discovery, subscribe/unsubscribe, notification, distributionのプロトコルが規定されている。

subscriberになるにはpublisherからHTTPのリクエストを受け取ることがでる必要がある。通常firewallの中にいるブラウザは受け取ることができない。そこで出てくるのがReverseHttpでグローバルにあるサーバをsubscriberとして置き、通常firewallの裏にあるブラウザからそのサーバにcometなりweb socketなりで接続しておいてリアルタイムにnotificationを読み出せるようにしておく。

アホみたいな感じもするけどOpera Uniteも似たようなものでMSもTeredo serviceとしてやっている(ってSmart Clients: ReverseHTTP & WebSockets – igvita.comに書いてある)。

Opera Uniteの中身は全然知らなかったので調べた。通常firewallの裏側にあるPC上で動いているOperaをHTTPサーバとして機能させるために*.*.operaunite.comというサーバをproxyとしてリクエストを受け取る(ref. Opera、Webブラウザをサーバー化する「Opera Unite」を公開 -INTERNET Watch)。operaunite.comとoperaの間の通信方法は調べてないです。ここでTCPSocketなのかな。結果opera uniteのwidget(jsで記述)でHTTPリクエストをハンドルできる(ref.Unite API Overview)。
nokia端末向けのmobile web server*.mymobilesite.net経由で繋いでるのも似たようなもの。たしかにクレイジーな気がするだけで実績のあるやり方。

Web Socket

The Web Sockets APIがブラウザのjavascriptエンジンがサポートすべきWeb Socketの仕様で、Web Socketサーバとの通信プロトコル(少なくとも現状では素のApacheにはWeb Socketのリクエストをうまくハンドルできない)の詳細はIETF draftのThe Web Socket protocolに書かれている。

プロトコルの概要をつかむにはComet Daily » Blog Archive » Independence Day: HTML5 WebSocket Liberates Comet From Hacksが一番わかりやすかった。

できることを挙げると以下のようなことができる。

  • コネクションを閉じないことを除いて基本的にHTTPと同じ
  • 平文で通信するデフォルトポート81のws://とSSLで通信するデフォルトポート816のwss://とがある
  • firewall/proxyを通過できる
  • サーバで許可されていればクロスオリジン通信が可能(HTTP access controlではなくWeb Scoketの仕様に同等のものが含まれている)
  • HTTPのcookieを利用可能
  • バイナリデータも扱える

逆にできないことはThe Web Sockets API

This interface does not allow for raw access to the underlying network. For example, this interface could not be used to implement an IRC client without proxying messages through a custom server.

と書かれているようにIRCのクライアントのようなもの(というよりかはWeb Scoketで利用することを前提としていない全てのプロトコル)はWeb Socketでは実現できない。

それはなぜか。Web Socketは基本的にはHTTPと同じようなやり取りをする。つまりはじめにクライアントからリクエストを送りサーバがそれに対してレスポンスを返す。HTTPとの違いはレスポンスを返した後コネクションが切断されるのに対してWebSocketでは切断されずに全二重双方向通信に使うことができるところ。このはじめのリクエスト/レスポンスのやり取りはhandshakeと呼ばれていてる。

draftによれば、このhandshakeはクライアントが


GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com:81
Origin: http://example.com
WebSocket-Protocol: sample

というリクエストを送り、それを受け取ったWebScoketサーバが


HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample

というレスポンスを返すことで行われる。

このhandshakeは必ず必要なので、このWeb Socketのhandshakeを理解できないサーバとはWeb Socketで通信することはできない。つまり既存のプロトコルと自由にソケット通信することはできない(ただ既存のサーバの側でWeb Socketに対応することは可能だと思う)。

TCPSocket(Network Communication API)であれば可能だがOperaでしか実装されていない。

サーバ側の対応状況

現状ではApacheでWeb Socketのリクエストをハンドルすることができない(理由は追ってません)。
mozillaのbugzillaではBug 472529 ? Support for Web sockets’ HTML5 Draft Recommendation (websocket)にだめみたいと書かれており、WebKitのbugzillaでもBug 27490 – Web Sockets Test Infrastructure Part 1/3: Serverにmod_pythonを使ったweb socketサーバを作ってテストを動かすと書いてある。

apacheのbugzillaでもBug 47485 ? HTML5 Websocket implementationにモジュールとして作ればいいんじゃないの、と書かれているので(ApacheでWeb Socketをサポートすることについて微妙にもめてて野次馬的に面白かったんですけどそこは割愛)Web Socketをサポートしたければそういうサーバを用意する必要があります。

現状ではWebSocket実装Kaazing – html5-developers-jp | Google グループで紹介されているKaazingというものがあるようです。

使用シナリオ

  • cometの代替手段として(ブラウザ上で動作するゲームのようなものやチャットなどのレスポンス改善)
  • ウェブアプリケーション全般のインタラクティビティ改善

など。

HTML5のbbとして入っているBackground Browser Taskとの組み合わせがよさそうと思ったらbbはHTML5の仕様からなくなってた…. (X)HTML5 Tracking
chromiumのほうでも動きがないのでなくなったのかも。

まとめ

クライアントサイドで考えるとPubSubHubbub(+ReverseHttp)はWeb Socketまでのつなぎ。ただデスクトップの世界ではIEがWeb Socketをサポートするのは期待できないのでWeb Socketを利用できる場面はfirefoxやchromeの拡張機能などに限られる。モバイルであればWebKit rules!なので数ヶ月後にはchromiumにWeb Socketが載ってそれはWebKitにフィードバックされるので1年くらい経てばWeb Socketを使ったアプリケーションを普通に使えるようになるかもしれない(ただ#ifdef ENABLE_WEB_SOCKETSつきなのでイコールsafariがサポートという訳ではない)。

あとデスクトップのクライアントサイドであってもOpera uniteのように自前でoperaunite.comのようなReverseHttpを持つことでPubSubHubbubを直接受け取ることができるようになる。

サーバサイドでは全く拡張性がなく使用目的が限られるXMLRPC pingの代替としてPubSubHubbubは汎用的に使える。

Web Socketは何でも通信できる神機能ソケットではないが、いままでcometのようなハックを駆使する必要があったものをシンプルに作ることができるようになる(これもIEのことがあるのでモバイルの世界限定の話)。


About this entry