JavaScriptによるcross domain & streamingなAPIアクセスの方法色々 - Nakamap APIの場合 -

こんにちは。すぎゃーん(@sugyan)です。

先日、Nakamap APIを公開しましたが、今回はそれをJavaScriptから使うためのライブラリを用意してみましたので紹介させていただきます。

使い方

<script type="text/javascript"http://developer.nakamap.com/js/nakamap.js"></script>

とscriptを読み込むことで使用できます。 access_tokenが既に取得できていれば、

var client = new Nakamap.Client({ token: '*********' });
/* REST API */
client.get('/me', function (result) {
    console.log(result);
});
/* Streaming API */
client.listen('/group/' + group_id, function (data) {
    console.log(data);
});

のような形でREST APIへのアクセス、Streaming APIからの受信ができます。

access_tokenはOAuth認証で取得しますが、Twitter @anywhereを参考に、access_tokenを意識せずに認証とAPIアクセスを行うインタフェースも用意しました。

<script type="text/javascript">
  Nakamap.anywhere({
      id: '********************'
  }, function (n) {
      if (n.isConnected()) {
          n.get('/me', function (result) {
              console.log(result);
          });
      } else {
          n('#nakamap').connectButton({
              scope: ['read_basic'],
              authComplete: function () {
                  n.get('/me', function (result) {
                      console.log(result);
                  });
              }
          });
      }
  });
</script>
<div id="nakamap"></div>

必要なのは開発者サイトでアプリ登録した際に発行されるclient_idのみです。 ここで登録したドメインと同一ドメイン上であれば動作します。 指定した要素にconnectButtonメソッドを呼ぶことで認証ダイアログをpopupさせるボタンが表示され、認証が完了すればその場でAPIへのアクセスが可能になります。

デモ

jsdo.itにてデモアプリを公開しています。JavaScriptのみで動く、Nakamapのチャットアプリです。

Nakamap App - jsdo.it - share JavaScript, HTML5 and CSS

動作原理

Nakamap APIのエンドポイントのドメインは"https://thanks.nakamap.com"となっており、JavaScriptからのアクセスは基本的にクロスドメインの通信をすることになります。 XMLHttpRequest Level 2であればAccess-Control-Allow-Originヘッダを指定することでクロスドメインの通信が可能になるので、Chrome, Firefox, Safariなどのブラウザではこれを使用します。

一方、Internet ExplorerではXDomainRequestを使用することで同様にクロスドメイン通信が可能ですが、こちらはhttp/httpsの壁が越えられないなどの制約もあり、IE8以降を対象にwindow.postMessageを使ったAPIアクセスを行うようにしています。 具体的には、https://thanks.nakamap.com/上にレシーバとなるページを用意し、iframeでそのページを読み込み、window.postMessageを使ってリクエストとレスポンスをJSONでシリアライズした文字列を使ってやりとりする、という方法です。 レシーバのページからのAPIアクセスは同一ドメインからのアクセスになるため、通常のXMLHttpRequestで取得できます。 window.postMessageではiframeの親と子の間でメッセージをやり取りできます。これを使って別ドメインからのリクエストをここで中継して代わりに行い、結果を返す、ということでInternet Explorerでもクロスドメインのリクエストを実現させます。

また、Streaming APIの受信ですが、XMLHttpRequest Level 2ではmultipart/mixedなレスポンスを受けるmxhr.jsというライブラリがありますのでこれを使わせていただいています。 Internet ExplorerのXMLHttpRequestではレスポンスを途中まで受け取って処理する、ということができませんが、XDomainRequestが近い機能を持っています。 ただし、最初の数百バイトは受け取ってもonprogressイベントは発火されない仕様のようで、最初にダミーデータとして数百バイトのデータを返すようにしました(XDomainRequest with "prelude"として紹介されています)。 これを使うことで、IE8以上の環境でもStreaming APIからのデータを受信できるようにしています。

まとめ

JavaScriptは様々な環境での動作を考慮しないといけないので大変ですね。。 たくさん躓いて色々と勉強になりました。

 

カヤックではNakamapとJavaScriptが大好きな技術者も募集しています!