twicliでUser Streaming APIを利用する

twicliでUser Streaming APIを利用できるようにするプラグイン stream.js を実験的に公開しました。
これを導入することで、 タイムラインを数分ごとの更新ではなく、リアルタイムで追いかけることができるようになります。
実験的ということで、不安定だったり、突然使えなくなったりする可能性があります。

利用にはWebSocketに対応したブラウザが必要です。(Firefox11、Chrome16, Safari6, Opera12, IE10以降など)

追加の手順

  1. twicliで+タブから「設定」を開く
  2. プラグインの欄に「stream.js」という行を追加
  3. 「保存」をクリック
  4. twicliをリロード


プラグインを外すときは、同じ手順でstream.jsの行を削除します。

実装についての覚え書き

TwitterのStreaming APIは、HTTP 1.1のchunked encodingを使って、1回のリクエストに対してセッションを張りっぱなしで次々にJSONデータを流すという仕様のため、クロスドメインアクセスに制約のあるブラウザ上のJavaScriptでは直接結果を受け取って処理することができません。(レスポンスヘッダに"Access-Control-Allow-Origin: *"などを付加してくれていれば、HTML5のXHR over CORSで取り扱えるはずなのですが、残念ながら付加されていません。)


そこでstream.jsプラグインでは、Streaming APIをWebSocketに変換して中継するサーバを用意し、そこを経由してアクセスを実現しています。中継サーバにはOpenShift Online (Red Hat社がインターネット上で提供しているPaaS環境)の無料枠を利用しています。


中継サーバのコードはGitHubにあります。 https://github.com/NeoCat/twgateway/


Twitter APIOAuth認証処理(アクセス先URLをsecret_tokenで署名)は全てtwicli内部で実行しています。署名済みのURLをWebSocket経由でサーバに送ると、サーバはその先にアクセスし、APIからのデータを受信するごとにWebSocket経由でtwicliに返します。要するにサーバ側は純粋にプロトコルを変換するだけのものということです。


さて、OpenShiftでは多様なプラットフォーム(言語やライブラリ)を利用できますが、今回はRuby 1.9を利用しました。理由は過去にStreaming APIを利用する中継サーバをRubyで書いていたので、これをWebSocketに対応させれば良いやくらいに考えていたからです。しかし、今から思えばNode.jsを利用した方が簡単だったかも。というのは、OpenShiftのrubyカートリッジのWebサーバ絡みで罠があったためです。


OpenShiftのRubyでWebSocketを利用する方法は、下記のサイトなどに情報があります。


要するに、OpenShiftのRubyカートリッジでは、標準でWebサーバとしてApache+Passengerが起動するようになっていますが、デプロイ時にこれを終了させ、同じポート番号でWebSocketに対応したサーバであるPumaを起動するという処理を入れておく必要があるということです。何とも強引。。

これは、.openshift/action_hooks 内にスクリプトを書いておくことで実現可能です。

https://github.com/NeoCat/twgateway/tree/master/.openshift/action_hooks


元のサイトの記述通りだと、コードを更新して git commit でデプロイする際にサーバがうまく置き換わらないことがあったため、フックの実行タイミングを変えたりしています。


あと、意外とStreamingに上手く対応できるHTTPライブラリがなく、結局curb(curl for ruby)ライブラリを使ったのですが、マルチスレッド対応が甘いようで、WebSocket切断時の対処がちょっと怪しい。。*1

*1:が、これを直すくらいなら全部Node.jsで書き直した方が良さそうだと思っています。。