プログラマでありたい

おっさんになっても、プログラマでありつづけたい

何故JSONPでJavaScriptのクロスドメイン通信ができるのか?

一人Advent Calendarの3日目です。

 JSONPを使って外部のAPIを呼び出して、結果を取り込むということは色々なところで行われています。しかし、そもそもJavaScriptを利用した場合、クロスドメイン通信が使えないという前提があります。JSONPだったら、何故そこを回避できるのでしょうか?あまり詳しく考えたことが無かったので、簡単に調べてまとめてみました。なんというか4周くらい遅れている話題ですが、気がついた時に整理するとスッキリします。

JSONPの動作原理



 Wikipediaさんをみてみると、そのものずばりのことが書かれています。scriptタグ内のsrc属性は別ドメインのURLを指定できるという点と、そのレスポンスはJavaScript関数呼び出し形式になるという点をついたのが、JSONPの動作原理です。なんというか、仕様の考慮不足を利用した仕組みだと思います。
JSONP - Wikipedia

ブラウザなどに実装されている「同一生成元ポリシー」という制約により、Webページは通常、自分を生成したドメイン以外のドメインのサーバと通信することはできない。 しかし、HTMLのscriptタグのsrc属性には別ドメインのURLを指定して通信することができるという点を利用することによって別ドメインのサーバからデータを取得することが可能になる。
JSONPでは、通常、上記src属性のレスポンスの内容はjavascript関数呼び出しの形式となるため、src属性に指定するURLにその関数の名前をクエリ文字列の形式で付加する。一般的な方法では、この時に指定する関数名はWebページ側ですでに定義されているコールバック用の関数の名前になる。

 しかし考えてみたら、他のサイトに設置されたJavaScriptを呼び出して使うというのは、当たり前のようにやっていますよね。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

JSONPはそれに対してデータを返す形式を、呼び元と呼び先でお互いに決めておくことで成り立っています。
図にすると、こんな感じだと思います。
f:id:dkfj:20141204194739p:plain

jquery.xdomainajax.jsの謎



 両者のお約束の元に成り立っているのがJSONPです。一方で、どんなサイトからでもデータをとってこれるという謎のプラグインがあります。jquery.xdomainajax.jsです。スクレイピングで利用されることが多いのですが、どうやってるのかなぁと思っていました。JSONPの原理を理解した上でソースを見ると、一目瞭然でした。 Yahoo! Pipesをかまして、JSONP形式に変換しています。
f:id:dkfj:20141204200201p:plain

 Yahoo! Pipesの太っ腹さに依存したライブラリです。外部サービスに依存したモジュールという異色の存在なのかもしれません。

感想



 長年何となく気になってて放置してたものを、ちょっとだけ調べてみました。10分くらいの調査で直ぐ解るので、気になったことはちゃんと調べるに限りますね。もし理解が間違っていたら教えて下さい。

See Also:
プログラマになりたい Advent Calendar 2014