Twitter @Anywhere を斜め上に掘り下げる
Twitter @AnywhereというDeveloper向けの新サービスが出てた。このサービス、この自分的にはいろいろな理由によりちゃんとチェックしておく必要がある。ので久々にブログ書く。
Facebook Connect (JavaScript) を知ってる人は、それがTwitterでもできるようになった、と思ったらいい。つまりサーバレスでTwitterに接続してAPIをJavaScriptから利用できるようになった。今でもJSONPである程度APIの利用はできたが、JSONPとは違い認証が必要な操作、例えば書き込み系の操作もOK(ただしversion 1のAPIでは許されている操作はそれほどない)。
詳しくはこちらの記事とかをどうぞ。
Twitter 新 API のドキュメント「Getting Started with @Anywhere」日本語訳 - WebOS Goodies
さて、上記の記事などでは触れられてないけど、プレビュー版のAPIもあるようで、これだとfollow以外にもいろいろなリクエストが使えるようだ。
http://platform.twitter.com/js-api.html
http://ongmap.com/blog/?p=519
Twitter @AnywhereのJavaScriptのインクルードに渡すパラメータで"v=1"となってるところを"v=chirp_preview"とするだけでよい。ただ、すべてのAPIが使えるかというとそうではなく、結構バグが有るみたい。ということでもうすこししたらちゃんとしたのが出るだろうからみんな待ちましょうね。おしまい。
でも待てないので、中身を見てみる。
通信の方法は比較的シンプル*1で、Twitter Anywhereのスクリプトが読み込まれると自動的にそのページの中に隠しIFRAMEが作成され、その中にメッセージのレシーバとなるHTMLファイルが読み込まれている*2。これは https://api.twitter.com/xd_receiver.html というURLで提供されており、このHTMLからならAPIのエンドポイントは同一オリジンなのでXMLHttpRequestで呼び出しができる、という仕掛け。
あとは、Twitter @Anywhereを呼び出した親フレームの間とでデータ通信を行えばよいわけだが、最近のブラウザはすでにHTML5 Cross Document Messagingを実装しているので、これは実は簡単。実際にTwitter Anywhereでもwindow.postMessageを使っているのはイベントリスナをつければすぐわかる。具体的にはFirebugで以下を実行する
cd(frames[0].frames[0]); // https://api.twitter.com/xd_receiver.html window.addEventListener('message', function(message){ console.log(message.data) }, true); cd(window.parent); window.addEventListener('message', function(message){ console.log(message.data) }, true);
Dumpして得られたメッセージ内容
{"uuid":7,"method":"statuses/home_timeline","args":[{}],"token":"012345678-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN"}
{"uuid":7,"data":[{"in_reply_to_status_id":null,"created_at":"Sat Apr 17 11:12:35 +0000 2010", ... ]}
つまり、JavaScriptのAPIを使わずとも、この形式のメッセージをIFRAMEのターゲットにpostMessageで送信&帰ってくるイベントをListenすればよい。uuidというリクエストのつながりを管理するIDがついているので、これを見て自分のリクエストのレスポンスかどうかがわかる。リクエストの中にあるtokenは、Twitter Anywhereにコネクトした後、Cookieの中にtwttr_anywhereという名前で保存されているものが使われているようだ。
実際に作ってみた例がこれ。DMを送りつける。あやしい。
http://stomita.sakura.ne.jp/lab/anywhere/
なお、postMessageを実装してないブラウザには、さまざまなFallback方法があって異なるドメイン間でのフレーム間通信を実現できるが、ここではめんどくさいので省略。
実際に送られるAPIのHTTPリクエストの内容は、Firebugにでてくるのでよくわかる。
Host api.twitter.com User-Agent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9 Accept application/json, text/javascript, */* Accept-Language ja,en-us;q=0.7,en;q=0.3 Accept-Encoding gzip,deflate Accept-Charset Shift_JIS,utf-8;q=0.7,*;q=0.7 Keep-Alive 115 Connection keep-alive X-Requested-With XMLHttpRequest Authorization OAuth oauth_access_token="012345678-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN" ....
AuthorizationヘッダにOAuthのトークンがくっついているが、OAuth WRAPに近い形で署名は省かれている。
ちなみに表題の「斜め上に掘り下げる」って、どうもおかしな日本語だが、本トピックは通常の反応としては斜め上方向だとおもうし、実際にIFRAMEの構造を下方向に掘り下げて解析したので実はえーじさんはおかしくはない。