Cross-origin asynchronous request 2

Source: Internet
Author: User

let's talk about the jsonp principle. Our cross-domain dependency is very serious. In fact, this is a script injection action. It involves two script fragments and some global variables. For ease of explanation, I will first release the example:

<! Doctype HTML> 

<Br/> <! Doctype HTML> <br/> <pead> <br/> <title> jsonp principle by situ zhengmei </title> <br/> <meta charset = "UTF-8"/> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <meta name = "keywords" content = "jsonp principle by situ zhengmei"/> <br/> <meta name = "Description" content = "jsonp principle by situ zhengmei"/> <br/> <SCRIPT type = "text/JavaScript" charset = "UTF-8"> <br/> window. onload = function () {<br/> var script = document. crea Teelement ("script"); <br/> window. jsonpcallback = function (JSON) {<br/> for (VAR item in JSON) {<br/> alert (item) <br/>}< br/> If (window. JSON) {<br/> alert (window. JSON. stringify (JSON) <br/>}< br/> script. src = "http://api.flickr.com/services/feeds/photos_public.gne? Tags = cat & tagmode = any & format = JSON & jsoncallback = jsonpcallback "<br/> var head = document. getelementsbytagname ("head") [0]; <br/> head. appendchild (SCRIPT ); <br/>}< br/> </SCRIPT> </P> <p> </pead> <br/> <body> <br/> <p> jsonp principles by situ zhengmei </p> </P> <p> </body> <br/> </ptml> <br/>

RunCode

There is an internal script on this page, which is called script fragment 1. It dynamically generates a script tag after loading the page, sets SRC and adds it to the DOM tree. The key is the structure of SRC, which is composed of a common URL and some query parameters. These query parameters depend on the company, but one of them must be used to identify the name of the callback function. Here is jsonpcallback. Since there is a function name, there must be a function itself. Since we define this function, it is not necessarily in the global scope, so I add a "window prefix" for it ". There is an interesting analogy that the global scope is like a public toilet. Although you can't go to it, you should also go to it less. If possible, we should try to clean it after using it to avoid excessive global variables and reduce the risk of name conflicts. However, we don't need to clean it now. This also involves a problem. Let's look at how the background works.

Since the script label adds the src attribute, it should be a JS file and will not report errors. In a standard browser, we can use onerror to listen to it. But now we can see that it is not a JS file. This relies entirely on the creation of the target server! When we send this strange thing, it should break down these parameters and function names, generate a JSON according to the parameters, and write them into a JS file (dynamically generated ), then obtain the function name. Because this is a global function, you can call it directly. Well, it is in the text state. Add a pair of brackets to the function name and put JSON in the middle. In other words, this JS file looks like this:

// Dynamically Loaded new JS file var JSON = {"title": "Recent uploads tagged cat", "Link": "http://www.flickr.com/photos/tags/cat/", "Description ":"", "modified": "2010-05-25t17: 21: 19z", "generator": "http://www.flickr.com/", "items": [/** lots of data, here is a little **/]} window. jsonpcallback (JSON)

Therefore, once the JS file is parsed, You can execute the callback function and process the data (JSON) returned by our request ). Okay, it's time to clean it. First, this script tag for background interaction is useless after callback function execution. We can remove it. In addition, after the callback function is executed, the function is useless and can be removed.

Window. jsonpcallback = function (JSON) {for (VAR item in JSON) {alert (item)} If (window. JSON) {alert (window. JSON. stringify (JSON)} script. parentnode & script. parentnode. removechild (SCRIPT); // This is a matter of privilege. Although the value is set to undefined, we can still... the jsonpcallback window is traversed in the in loop. jsonpcallback = undefined; try {// Delete the jsonpcallback member permanently. // unfortunately, the IE window is based on COM, And the delete method is not used. Therefore, it fails! Alert (window instanceof object) delete window. jsonpcallback} catch (e ){}}

As mentioned in the comment, it is easy to treat God with difficulty. We need to change our strategy and adopt a single-foot stand-alone structure to reduce global pollution! In other words, the method names of these callback functions must be members of an object! To improve efficiency, I have made an array of objects (if I only use one object to load them, The for... in loop will be disgusting !)

// Small jsonp class library by situ zhengmei var Dom ={}; // exposes the only global variable of the class library as the namespace Dom. jsonp = function (URL, OBJ, method) {var self = arguments. callee; If (self. callbacks. length) {// implement asynchronous loading, asynchronous callback setTimeout (function () {self (URL, OBJ, method)}, 0); return;} var query = []; for (var I in OBJ) {query. push (I + "=" + OBJ [I])} var callback = "dom. jsonp. callback "url = URL + "? "+ Query. join ("&") + "&" + method + "=" + callback; var script = document. createelement ("script"); script. src = URL; var head = document. getelementsbytagname ("head") [0]; var OBJ = {method: function (JSON) {for (VAR item in JSON) {alert (item)} If (window. JSON) {alert (window. JSON. stringify (JSON)} script. parentnode & script. parentnode. removechild (SCRIPT) ;}} Dom. jsonp. addcallback (OBJ) Head. appendchild (SCRIPT);} Dom. jsonp. callbacks = [] Dom. jsonp. addcallback = function (OBJ) {This. callbacks. push (OBJ)} Dom. jsonp. callback = function (JSON) {// callback function var objs = This. callbacks; For (VAR I = 0, El; El = objs [I ++];) {el. method. call (El, JSON)} This. callbacks = [];} window. onload = function () {Dom. jsonp ("http://api.flickr.com/services/feeds/photos_public.gne", {tags: 'cat', tagmode: 'any', format: 'json'}, "jsoncallback"); Dom. jsonp ("http://api.cnet.com/restApi/v1.0/techProductSearch", {parttag: 'mtv', IOD: 'hlprice', viewtype: 'json', Results: '123', query: 'ipod '}, "Callback"); Dom. jsonp ("http://del.icio.us/feeds/json/fans/stomita", null, "Callback ");}

<Br/> <! Doctype HTML> <br/> <pead> <br/> <title> jsonp principle by situ zhengmei </title> <br/> <meta charset = "UTF-8"/> <br/> <meta content = "Ie = 8" http-equiv = "X-UA-compatible"/> <br/> <meta name = "keywords" content = "jsonp principle by situ zhengmei"/> <br/> <meta name = "Description" content = "jsonp principle by situ zhengmei"/> <br/> <SCRIPT type = "text/JavaScript" charset = "UTF-8"> <br/> var Dom = {}; // expose the only global variable of the class library as the namespace <br/> Dom. jsonp = Function (URL, OBJ, method) {<br/> var self = arguments. callee; <br/> If (self. callbacks. length) {<br/> setTimeout (function () {self (URL, OBJ, method)}, 0); <br/> return; <br/>}< br/> var query = []; <br/> for (var I in OBJ) {<br/> query. push (I + "=" + OBJ [I]) <br/>}< br/> var callback = "dom. jsonp. callback "<br/> url = URL + "? "+ Query. join ("&") + "&" + method + "=" + callback; <br/> var script = document. createelement ("script"); <br/> script. src = URL; <br/> var head = document. getelementsbytagname ("head") [0]; <br/> var OBJ = {<br/> method: function (JSON) {<br/> for (VAR item in JSON) {<br/> alert (item) <br/>}< br/> If (window. JSON) {<br/> alert (window. JSON. stringify (JSON) <br/>}< br/> script. parentnode & script. parentnode. removechild (SCRIPT); <br/>}< br/> Dom. jsonp. addcallback (OBJ) <br/> head. appendchild (SCRIPT); <br/>}< br/> Dom. jsonp. callbacks = [] <br/> Dom. jsonp. addcallback = function (OBJ) {<br/> This. callbacks. push (OBJ) <br/>}< br/> Dom. jsonp. callback = function (JSON) {// unified processing callback function <br/> var objs = This. callbacks; <br/> for (VAR I = 0, El; El = objs [I ++];) {<br/> el. method. call (El, JSON) <br/>}< br/> This. callbacks = []; <br/>}</P> <p> Dom. jsonp ("http://api.cnet.com/restApi/v1.0/techProductSearch", {<br/> parttag: 'mtv', <br/> IOD: 'hlprice', <br/> viewtype: 'json ', <br/> results: '123', <br/> query: 'ipod '}, "Callback"); </P> <p> Dom. jsonp ("http://del.icio.us/feeds/json/fans/stomita", null, "Callback "); <br/>}< br/> </SCRIPT> </P> <p> </pead> <br/> <body> <br/> <p> jsonp principles by situ zhengmei </p> </P> <p> </body> <br/> </ptml> <br/>

Run code

// Http://www.blogjava.net/emu/articles/129240.html
VaR Dom ={}; // the only global variable in the exposed class library is used as the namespace.
// {URL, OBJ, callbackname, callback}
Dom. jsonp = function (URL, OBJ, method, callback, caching ){
Method = method | "Callback ";
VaR script = Document. createelement ('script ');
VaR Index = Dom. jsonp. Index ++;
VaR query = Dom. toquerystring (OBJ );
Callback = callback | function (JSON ){
For (VAR item in JSON ){
Alert (item)
}
If (window. JSON ){
Alert (window. JSON. stringify (JSON ))
}
}
Url = URL + "? "+ Query +" & "+ method +" = "+ escape ('dom. jsonp. Callbacks. _ '+ index );
If (! Caching) URL + = '& Rand =' + math. Random ();
Dom. jsonp. Callbacks ['_' + Index] = function (){
Delete Dom. jsonp. Callbacks ['_' + Index];
If (arguments. Length = 1 ){
Callback (arguments [0]);
} Else {
VaR arry = [];
For (VAR I = 0; I

Posted onSitu zhengmei reading (...) Comment (...) EDIT favorites

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.