JAvascriptのドメイン間リクエスト
8251 ワード
卒業後、Silicon Graphicsで7年間オペレーティングシステムとネットワークプログラミングをした(まさか一人の会社の感情も7年間かゆい).
彼の実家を離れた後、MicrokernelとDSPプログラミングを遊び始めたMicrokernelは、MIPSアーキテクチャのgcc R 4000ポートに初めて接触した.
彼はNetscapeとMozillaの時に事業の頂点に達した.1995年4月、彼はMochaをプレイし始め、彼のしばらくの努力を経てMochaは強くなった.そこで同年の9月、華麗な変身を遂げ、livescriptに改名し、Netscape Navigator 2.0に初めて装着された.同年12月4日、Sun社との共同声明でlivescriptが最終形態に変身し、JavaScript神兵が誕生した.
JavaScript神兵が強すぎたため、人々は彼に封印を加えた.しかし人はいつも私心があって、そこでまたいくつか封印の方法を開けることを残しました.
薄く引っ張ってしまいましたが、封印と封印を解く方法を紹介します.
Same origin policy
まず、ドメイン間アクセスを封印し、javascript同源ポリシーの制限、すなわちa.comドメイン名のjsはb.comドメイン名のオブジェクト(ドメイン間)を操作できない.以下にいくつかの例を挙げて、もっとイメージ的に見えます.
URL 1
URL 2
通信を許可するかどうか
コメント
http://www.a.com/a.js
http://www.a.com/b.js
はい
同ドメイン名
http://www.a.com/a.js
http://www.a.com:8080/b.js
いいえ
ドメイン名と異なるポート
http://www.a.com/a.js
https://www.a.com/b.js
いいえ
ドメイン名と異なるプロトコル
http://www.a.com/a.js
http://127.0.0.1/b.js
いいえ
ドメイン名とそのIP
http://www.a.com/a.js
http://www.b.com/b.js
いいえ
メインドメイン名サブドメイン名
http://www.a.com/a.js
http://www.b.com/b.js
いいえ
異なるドメイン名
Same origin policyに何か分からないことがあったらhttp://en.wikipedia.org/wiki/Same_origin_policy見てください.
以下に、ドメインを越えてこの封印にアクセスするいくつかの主要な手跡を解く.
手印一JSONP、すなわちJSON with Padding.同源ポリシーの封印の制限により,ドメイン間アクセスが封印された.封印を解いてドメイン間リクエストを行う必要がある場合はhtmlのscriptタグを使用してドメイン間リクエストを行い、responseで実行するjavascriptコード、JSONオブジェクトなどを返す.このように封印を解いてドメイン間で要求する方式をJSONPと呼ぶ.
www.a.comドメイン名の下に以下のhtmlファイルがあります.
<html>
<head>
</head>
<body>
<script type="text/javascript" id="script1"></script>
<input type="text" id="a" name="a">
<input type="button" value="click" onclick="document.getElementById('script1').src='http://www.b.com/response.js'">
</body>
</html>
www.b.comでのレスポンスのresponse.jsコード
var a=1;//
alert("Hello World");//
document.getElementById("a").value="Hello World";//
多くの場合、ダイナミックのために私たちはこのように遊んでいます.www.a.com下のhtmlを
<html>
<head>
</head>
<body>
<script type="text/javascript" id="script1"></script>
<input type="text" id="a" name="a">
<input type="button" value="click" onclick="document.getElementById('script1').src='http://www.b.com/response.jsp'">
</body>
</html>
www.b.com/response.jsをresponseに変更する.jsp
<%out.print("var a=1;alert(\"Hello World\");document.getElementById(\"a\").value=\"Hello World\"");%>
URLにはpが1つしかないが、手印JSONPは封印を解くと同時に破壊力を持つようになる.
手印JSONPに加え、仙人YUI、Jquery、Dojo、Extなどが独自の手印を次々と研究している.
YUI3.2のjsonpの使い方は以下の通りです(以下、YUI 3.2を中心に分析します):
var url = "http://yuilibrary.com/gallery/api/random?callback={callback}";
function handleJSONP(response){//...};
//...
Y.jsonp(url,handleJSONP);
//...
ps:ソースコード中examples/jsonp/jsonp_gallery.htmlには詳細があります.
印刷が速く、呼び出しが便利で、どのように実現されているかを見てみましょう.
ダウンロードhttp://developer.yahoo.com/yui/3/,Full Developer Kit版を選択,yui_3.2.0.zip解凍後、yui/buil/jsonpディレクトリに6つのファイルが表示されます.
jsonp.js
jsonp-debug.js
jsonp-min.js
jsonp-url.js
jsonp-url-debug.js
jsonp-url-min.js
主にjonpを見てください.jsというファイルは、8行目に
YUI.add('jsonp', function(Y) {
//...
YUIというfunctionにjsonpというfunctionを動的に追加しました.後のコードには、おなじみのprototype、apply、unshiftなどのJavaScript神兵の秘法が使われており、一つ一つ分析せず、133行目から137行目のコードを直接見ています.
//...
Y.Get.script(url, {
onFailure: wrap(config.on.failure),
onTimeout: wrap(config.on.timeout),
timeout : config.timeout
});
//...
ここにY.Get.がありますscript(...)の呼び出しは、url、onFailure、onTimeout、timeoutパラメータがありますが、これはいったい何をしているのでしょうか.
yui/build/yui/getを見てください.jsというファイル.
30行目から726行目はきれいな閉包をしながらY.Getに値を付けた.505行から725行を見ると、Y.Getはこのように成長していることがわかります.
{
PURGE_THRESH:20,
_finalize:function(id){ ... },
abort: function(o) { ... },
script: function(url, opts) { return _queue("script", url, opts); },
css: function(url, opts) { ... }
}
やっと上記のY.Get.を見つけました.scriptというfunctionですが、中には別の穴があり、もう一つあります.queur(...)の呼び出しは、虎穴に入らないと虎子にならない、これを見てください.queueのfuncitonにはいったい神馬浮雲があるのか.
362行にジャンプして、見つけました_queueの実装.でも焦らないで、まず上の353から361の注釈を見てください.
/**
* Saves the state for the request and begins loading
* the requested urls
* @method queue
* @param type {string} the type of node to insert
* @param url {string} the url to load
* @param opts the hash of options for this request
* @private
*/
と言いますqueueはrequestの状態を保存し、loadを開始します.コードを見てください.372行から378行、389行目のコード:
//...
queues[id] = Y.merge(opts, {// merge , yui/build/yui/yui.js 。
tId: id,
type: type,
url: url,
finished: false,
nodes: []
});
//...
_next(id);
//...
requestを保存した状態が実現したことが判明し、ここではloadを実現していないのではなく389行目に複数の_next(id)の呼び出し.これはnext(...)いったい何をしているのでしょうか.(この_nextが主役なので、詳しく分析します)
//...
d = w.document;
h = d.getElementsByTagName("head")[0];
//...
if (q.timeout) {
// q.timer = L.later(q.timeout, q, _timeout, id);
q.timer = setTimeout(function() {
_timeout(id);
}, q.timeout);
}
//...
n = _scriptNode(url, w, q.attributes);
//...
if (insertBefore) {
//...
} else {
h.appendChild(n);
}
//...
まずdocumentを取って、それからhを受け取ってheadラベルだけを考えて、nは通過します_scriptNode再着_node、documentを返します.createElement("script"),nodeにはきれいなfor(i in attr){...}ループはプロパティバインドを完了しました.最後に、insertBefore要素が指定されていない場合は、headラベルに、上に作成したscriptラベルappendを入れます.
これで仙人YUIのJSONP実現分析が完了した.次に、仙人JqureyがJSONPをどのように実現したのかを分析します.
まずJqueryでJSONPの使い方を見てみましょう.上の例の多くは$である.getJSON、しかも紹介が良かったです.JEには多くの牛人が具体的な分析と実現過程を書いた.審美疲労がある人がいるので、次の例はもっと強い$を使っています.ajax({dataType:'script'...}).jsonだけでなくscriptコードがロードされているからです.次はどうやって使うか見てみましょう.
$.ajax({
url: "http://2520011.appspot.com/js/cross_domain_demo.js",// GAE js
dataType: 'script',
success: function(data ){
alert(data);
}
});
インタフェースのapiのデザインも便利で、次に彼がどのように実現したかを見てみましょう.
ソースコード5762行でajaxの実装を見つけた.真ん中に積み重ねられた関係のないコードをスキップして5859行に来て、ここで柳暗花明になって、私たちはやっと長い間求めていたソースコードを見つけました.
var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
//...
script.src = s.url;
//...
head.insertBefore( script, head.firstChild );
挿入を含めて4行...Jqueryは本当に簡素です.牛人は普通そうでしょう、O(∩∩)Oはははは~
ここまで仙人Jqueryの実现を分析して、本当に1つの牛に比べて、次の段、私达はいっしょにDojoの実现を分析します.
to be continued......
ps:月曜日から金曜日まで毎日少なくとも1週間、週末は休みです.