復興ログ

未来の被災地にいるアナタと数十年後のキミたちへ。すべての記録を残します。

JSONPでクロスドメイン突破

広く知られていて、度々使う手法のJSONPなのですが。
使う度に調べながら使うことになるので、まとめておこうと思いました。

Ajaxで非同期通信

Webアプリケーションがリッチになるに連れて、クライアントサイド(ブラウザ側)で、Javascript形式のデータ(JSON)を利用して処理を行うことが一般的になりました。
JSON形式のデータを扱うには

  • JSONをページに埋め込んでおく
  • AjaxでJSONを取得する

という手法がとられます。
非同期の通信を行うのであれば、AjaxによるJSON取得という手法が選ばれます。
ですが、AjaxにはSame-Originポリシーが存在しており、ドメインをまたいだアクセスは出来ません。。

つまり、yahoo.co.jpのページからAjaxを使用して、google.co.jpのサーバに存在しているJSON(JSONに限りません)を取得することはブラウザが許していません。

そこで、使われるのがJSONPという手法。

JSONPって?

JSON with paddingの略

Javascriptの非同期通信でよく使われるXMLHttpRequestオブジェクトにはSame-Originポリシーが存在し、クロスドメインアクセスができない。

一方,scriptタグを用いると,ドメインの異なるサーバに置いているスクリプトファイルを読み込むことができる。この仕組みを利用し、scriptタグのsrcに、データを取得できるAPIのURLを指定し,ドメインの異なるサーバからデータを取得する仕組みの総称として、JSOPという言葉が使われる。JSONP用のAPIでは、関数名+取得データをjson形式で表記して引数とした形式(例.callbackFunc({id:1000,name:aaa}))のレスポンスが一般的で、APIから返されるコールバック関数と同じ名前の関数(callbackFunc(jsonData))をクライアント側で定義しておけば、データを読み込んだ際にそのコールバック関数が実行される。動的にscriptのDOMを生成することで、非同期でデータが取得できるようになる。


ただし、Same-Originポリシーが存在しないため、機密情報をAPIに含める際には十分な注意が必要である。

JSONPとはより。

使い方

JSON

JSONPとはJSONをデータとして渡す手法なので、まずJSONについて抑えておく必要があります。

JavaScript Object Notationの略。JavaScriptにおけるオブジェクトの表記法の1つを、ほとんどそのまま利用したデータフォーマット。

JSONとはより。
データ形式は軽量で、非常に理解しやすいです。

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address": {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumbers": [
         { "type": "home", "number": "212 555-1234" },
         { "type": "fax", "number": "646 555-4567" }
     ],
     "newSubscription": false,
     "companyName": null
 }

JSON - Wikipediaより

scriptタグ

クロスドメインを突破するために、利用するJSONP
scriptタグを非同期で生成することで、JSONのデータをドメインをまたいで、受け取ります。
scriptタグの生成方法はJavascriptで下記のように記述します。

var jsonpURL =
"http://search.twitter.com/search.json?q="
+ query + 
"&callback=listTweet";

var script = document.createElement('script');          // 1
script.type = 'text/javascript';                        // 2
script.src = jsonpURL;                                  // 3
var head = document.getElementsByTagName("head")[0];    // 4
head.appendChild(script);                               // 5
  1. scriptタグを生成
  2. scriptのタイプ
  3. scriptタグのソースURL
  4. headタグを得る
  5. 4で得たタグの子ノードにscriptタグを生成

これで、クロスドメインを突破するところまで完了です。

callback関数

JSONPの最も難解な部分であるcallback関数
scriptタグを生成して、クロスドメインを突破したら、JSONPがデータとして返ってきます。
JSONPとは、説明にもあるように

callbackFunc(jsonData)

データ形式で返ってきます。
こうすることで、JSONPが読み込まれるとcallbackFun関数にjsonDataが引数として渡されることになります。
つまり、ここで、必要なのはクライアント側にcallbackFuncという関数を定義しておくことです。

一般的に公開されているJSONP形式のWebAPIではcallback関数の定義が可能です。
上記例のソースのリクエストURLは

var jsonpURL =
"http://search.twitter.com/search.json?q="
+ query + 
"&callback=listTweet";

となっており、callback関数としてlistTweetという関数を定義していることになります。

listTweetは以下の内容。

var listTweet = function(data) {
	entry = data.results;
〜(略)〜
	document.getElementById('tweetResult').innerHTML = html;
}

data変数がJSONという事になります。
JSONへのアクセスは「 . 」を使用してアクセスします。

このcallback関数の内部でinnerHTMLを使用して、htmlを流しこむことで非同期でコンテンツを生成することが可能となります。
注意点としては、scriptタグを生成した時点で「非同期通信」が発生することになるので、Javascriptの流れがブラウザによって変化する可能性があります。
scriptタグを生成した後は、通信が発生し、callback関数が呼ばれるということをお忘れなく。

今回のJSONPで作ったコンテンツはこちらになります。
参考までにJavascriptこちらです。