Cross-Domain Ajax request (extjs) implemented using SCRIPT tags)

Source: Internet
Author: User
Tags script tag

In the Ajax application environment, the browser does not allow the XMLHttpRequest component to request cross-origin resources for security reasons. In many cases, this restriction causes a lot of inconvenience. Many colleagues have studied various solutions:

1. modify document. domain and the hidden IFRAME to implement cross-origin requests. This scheme may be the simplest one for cross-origin requests, but it is also the most restrictive scheme. First, it can only implement cross-origin requests under the same top-level domain name. In addition, when another IFRAME is contained in a page, security exceptions may occur and access is denied.

2. By requesting the proxy of the current domain, the server proxy can access resources of another domain. XMLHttpRequest requests a server resource in the domain and provides the target resource to be accessed to the server. The server then acts as a proxy to access the target resource. This scheme can achieve full cross-origin access, but the consumption of the request process will be relatively large during development.

3. You can request cross-origin resource tag reference in HTML, such as image, script, and link tags. Among these tags, script is undoubtedly the most suitable. When requesting every script resource, the browser will parse and run the function defined in the script file, or the Javascript that needs to be executed immediatelyCode, We can use the server to return a script or JSON object, parse and execute in the browser, so as to achieve the purpose of cross-origin requests. Use the script tag to implement cross-origin requests. You can only use the get method to request server resources. The length of parameter passing is also limited by the address bar length.

Here, we will introduce the third solution. Let's take a look at the example found on the network (the source is unknown. If anyone knows, please provide the original article link. Thank you ):

Javascript:

VaR scriptblock = Document. createelement ("script ");
Startget ();

Function startget (){
Scriptblock. src = "";
Scriptblock. src = "http: // localhost: 6144 /";
Scriptblock. type = "text/JavaScript ";
Scriptblock. Language = "JavaScript ";
Document. getelementsbytagname ("head") [0]. appendchild (scriptblock );
Scriptblock. onreadystatechange = returndata;
}

Function returndata (){
// Alert (scriptblock. readystate );
// Uninitialized object is not initialized with data.
// Loading object is loading its data.
// Loaded object has finished loading its data.
// Interactive user can interact with the object even though it is not fully loaded.
// Complete object is completely initialized.

If ("loaded" = scriptblock. readystate ){
VaR DIV = Document. getelementbyid ("htmldiv ");
Div. innerhtml = A. Project [0]. Name; // A is the variable in the returned JSON.
}
}

Call the startget method to send a cross-origin request. Use the onreadystatechange event to listen to the request end event and display the returned results on the page.

In this event function, where does the object of a come from? It is a JSON object output through http: // domain2/getdata. aspx and parsed by the browser. Check the following server code to understand it.

ASP. NET:

 
Protected VoidPage_load (ObjectSender, eventargs E)
 
{
 
Response. Write ("Var A = {'project': [{'name': 'a1'}, {'name': 'a2 '}]};");
 
}

The server outputs the script content of a json object through this code.

The above example shows how to use a script to request resources across domains. However, there is another problem here: the onreadystatechange event of the script tag is not the W3C standard event definition and is only valid in IE. In the following example, the extjs team expanded the Ext. Data. Connection class to support cross-origin requests. With its extension, we can easily use Ext. Ajax to request cross-origin resources and ensure the security of resource recovery. Let's take a look at its code:

 
Ext. Lib. Ajax. iscrossdomain =Function(U ){
 
VaRMatch = /(? :( \ W *:)\/\/)? ([\ W \.] * (? : \ D *)?) /. Exec (U );
If(! Match [1])Return False;// No protocol, not cross-domain
 
Return(Match [1]! = Location. Protocol) | (Match [2]! = Location. HOST );
 
};
 
 
 
Ext.Override(Ext. Data. Connection ,{
 
 
 
Request:Function(O ){
 
If(This. Fireevent ("Beforerequest",This, O )! =False){
 
VaRP = O.Params;
 
 
 
If(TypeofP ="Function"){
 
P = P. Call (O. Scope | window, O );
 
}
If(TypeofP ="Object"){
 
P = ext. urlencode (P );
 
}
 
If(This. Extraparams ){
 
VaRExtras = ext. urlencode (This. Extraparams );
 
P = P? (P +'&'+ Extras): extras;
 
}
 
 
 
VaRUrl = O. url |This. Url;
 
If(TypeofUrl ='Function'){
 
Url = URL. Call (O. Scope | window, O );
 
}
 
 
 
If(O. Form ){
VaRForm = ext. getdom (O. form );
 
Url = URL | form. Action;
 
 
 
VaREnctype = form. getattribute ("Enctype");
 
If(O. isupload | (enctype & enctype. tolowercase () ='Multipart/form-data')){
 
Return This. Doformupload (O, P, URL );
 
}
 
VaRF = ext. Lib. Ajax. serializeform (form );
 
P = P? (P +'&'+ F): F;
 
}
 
 
 
VaRHS = O. headers;
 
If(This. Defaultheaders ){
HS = ext. Apply (HS || {},This. Defaultheaders );
 
If(! O. headers ){
 
O. headers = HS;
 
}
 
}
 
 
 
VaRCB = {
 
Success:This. Handleresponse,
 
Failure:This. Handlefailure,
 
Scope:This,
 
Argument: {options: O },
 
Timeout:This. Timeout
 
};
 
 
 
VaRMethod = O. Method |This. Method | (P?"Post":"Get");
 
 
If(Method ='Get'&&(This. Disablecaching & O. disablecaching! =False) | O. disablecaching =True){
 
URL + = (URL. indexof ('? ')! =-1?'&':'? ') +'_ Dc ='+ (NewDate (). gettime ());
 
}
 
 
 
If(TypeofO. autoabort ='Boolean'){// Options gets top priority
 
If(O. autoabort ){
 
This. Abort ();
 
}
 
}Else If(This. Autoabort! =False){
This. Abort ();
 
}
 
If(Method ='Get'& P) | O. xmldata | O. jsondata ){
 
URL + = (URL. indexof ('? ')! =-1?'&':'? ') + P;
 
P ='';
 
}
 
If(O. scripttag |This. Scripttag | Ext. Lib. Ajax. iscrossdomain (URL )){
 
This. Transid =This. Scriptrequest (method, URL, CB, P, O );
 
}Else{
 
This. Transid = ext. Lib. Ajax. Request (method, URL, CB, P, O );
 
}
Return This. Transid;
 
}Else{
 
Ext. Callback (O. Callback, O. Scope, [O,Null,Null]);
 
Return Null;
 
}
 
},
 
 
 
Scriptrequest:Function(Method, URL, CB, Data, options ){
 
VaRTransid = ++ Ext. Data. scripttagproxy. trans_id;
 
VaRTrans = {
 
ID: transid,
 
CB: Options. callbackname |"Stccallback"+ Transid,
 
Scriptid:"Stcscript"+ Transid,
 
Options: Options
 
};
 
 
URL + = (URL. indexof ("? ")! =-1?"&":"? ") + Data + String. Format ("& {0 }= {1 }", Options. callbackparam |This. Callbackparam |'Callback', Trans. CB );
 
 
 
VaRConn =This;
 
Window [Trans. CB] =Function(O ){
 
Conn. handlescriptresponse (O, trans );
 
};
 
 
 
// Set up the timeout Handler
 
Trans. timeoutid =This. Handlescriptfailure. Defer (CB. Timeout,This, [Trans]);
 
 
 
VaRScript = Document. createelement ("Script");
Script. setattribute ("Src", URL );
 
Script. setattribute ("Type","Text/JavaScript");
 
Script. setattribute ("ID", Trans. scriptid );
 
Document. getelementsbytagname ("Head") [0]. appendchild (SCRIPT );
 
 
 
ReturnTrans;
 
},
 
 
 
Handlescriptresponse:Function(O, trans ){
 
This. Transid =False;
 
This. Destroyscripttrans (trans,True);
 
VaROptions = trans. options;
 
 
 
// Attempt to parse a string parameter as XML.
VaRDoc;
 
If(TypeofO ='String'){
 
If(Window. activexobject ){
 
Doc =NewActivexobject ("Microsoft. xmldom");
 
Doc. async ="False";
 
Doc. loadxml (O );
 
}Else{
 
Doc =NewDomparser (). parsefromstring (O,"Text/XML");
 
}
 
}
 
 
 
// Create the bogus xhr
 
Response = {
 
Responseobject: O,
Responsetext :(TypeofO ="Object")? Ext. util. JSON. encode (o): string (O ),
 
Responsexml: Doc,
 
Argument: Options. Argument
 
}
 
This. Fireevent ("Requestcomplete",This, Response, options );
 
Ext. Callback (options. Success, options. Scope, [response, options]);
 
Ext. Callback (options. Callback, options. Scope, [options,True, Response]);
 
},
 
 
 
Handlescriptfailure:Function(Trans ){
 
This. Transid =False;
 
This. Destroyscripttrans (trans,False);
VaROptions = trans. options;
 
Response = {
 
Argument: Options. argument,
 
Status: 500,
 
Statustext:'Server failed to respond',
 
Responsetext:''
 
};
 
This. Fireevent ("Requestexception",This, Response, options ,{
 
Status:-1,
 
Statustext:'Communication failure'
 
});
 
Ext. Callback (options. Failure, options. Scope, [response, options]);
 
Ext. Callback (options. Callback, options. Scope, [options,False, Response]);
 
},
 
 
// Private
 
Destroyscripttrans:Function(Trans, isloaded ){
 
Document. getelementsbytagname ("Head") [0]. removechild (document. getelementbyid (trans. scriptid ));
 
Cleartimeout (trans. timeoutid );
 
If(Isloaded ){
 
Window [Trans. CB] = undefined;
 
Try{
 
Delete window [Trans. CB];
 
}Catch(E ){}
 
}Else{
 
// If hasn' t been loaded, wait for load to remove it to prevent Script Error
 
Window [Trans. CB] =Function(){
Window [Trans. CB] = undefined;
 
Try{
 
Delete window [Trans. CB];
 
}Catch(E ){}
 
};
 
}
 
}
 
});

In the reqeust method, after processing parameters (these are original implementations ). When sending a request, determine whether the scripttag attribute exists (the value is true). If the scripttag is defined and true, call scriptrequest to send a cross-origin request through the script tag. In the request, it concatenates all parameters into the method for passing parameters through the address, and there is also a callback parameter (or its own parameter name ), used to identify the callback method that the client receives (called in the JavaScript code generated by the server). This callback function is dynamically generated based on different requests, in the same context, the callback function names of each request are different. By specifying parameters, you can solve the trouble caused by the absence of onreadystatechange event definitions in the script tag. In error handling, it uses timeout error processing. Because there is no event, it will have a request timeout delay function call to recycle resources.

After the above extension, when using the Ext. Ajax. Request method, we only need to add a flag to identify it as a cross-origin request:Scripttag: True. The following calls:

 
Ext. Ajax. Request ({
URL:'Http: // localhost: 8080/aspicio/getxml. Do',
 
Params:{
 
Listid:'Countrylistmanager141grid509',
 
Format:'Xml'
 
},
 
Scripttag:True,// Use script tag transport
 
Success:Function(R ){
 
Console. Log (R );
 
}
 
});

The following is a sample code of the server:

 
1: // Obtain the client callback function name
 
2: StringCallback = reqeust. querystring ("Callback");
 
3: // Other parameters can be obtained through reqeust. querystring.
 
4: // Output the Javascript call to the client.
5:Response. Write (callback +"('[Value: 0]')";);

The callback function is called by the server to complete the cross-origin request process.

**************************************** ************************************

What is the jsonp protocol? Jsonp is JSON with padding. Due to the same-origin policy restrictions, XMLHttpRequest only allows requests to resources of the Current Source (domain name, protocol, port. For cross-origin requests, we can use the HTML Script tag to perform cross-origin requests, and return the script code to be executed in the response, where JavaScript objects can be directly transmitted using JSON. This cross-origin communication method is called jsonp. Obviously, jsonp is a script injection behavior and requires special attention to its security. For the jsonp instance in jquery, we need two pages to assume the client and server roles of the Protocol respectively. Client code: <! Doctype HTML public "-// W3C // dtd xhtml 1.0 transitional // en" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <HTML xmlns = "http://www.w3.org/1999/xhtml">  Program Or page, used to obtain the parameter name of the jsonp callback function (usually the default value is: callback) jsonpcallback: "feedbackstate", // custom jsonp callback function name, the default value is the random function name success automatically generated by jquery: function (data) {var $ ul = $ ("<ul> </ul>"); $. each (data, function (I, V) {$ ("<li/> "). text (V ["ID"] + "" + V ["name"]). appendto ($ UL)}); $ ("# remote "). append ($ UL) ;}, error: function () {alert ('fail ');}});}); </SCRIPT> 

Related Article

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.