Ext跨域请求的解决方法

发布时间:2020-06-01编辑:脚本学堂
Ext跨域请求的解决方法

默认情况下,不管是Ajax无法跨域请求的,但是通过一些方式比如代理,iframe,嵌入脚本等方式可以部分满足跨域的功能,Extjs提供了一个封装版本,使用方法也比较简单,但是如果不清楚用法的话还是很郁闷,调试了好久才知道后台代码也需要做处理,现将用法记录下来以备忘。

前台代码:有两种方式请求:

1. 方法一:
 

复制代码 代码如下:
ss = new Ext.data.ScriptTagProxy({ 
   url: 'http://xxx.xx.xx.xx',//跨域的url地址  
   callbackParam: "callback", 
   headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='} 
 }); 
 ss.load({'_out': 'json'}, 
         new Ext.data.JsonReader({root:"topics"}, 
                 [{name: 'name', mapping: 'name'}, 
                   {name: 'comment', mapping: 'comment'}]), 
         function(recordsBlock, arg, isok) { 
           alert(Ext.encode(recordsBlock)); 
           alert(Ext.encode(recordsBlock.records[0].data)); 
         }); 

2. 方法二:

(1)首先引入一个脚本文件CrossDomainAjax.js代码如下:
 

复制代码 代码如下:

function SetCrossDomain()
{
  Ext.override(Ext.data.Connection, {
        request : function(o){
            if(this.fireEvent("beforerequest", this, o) !== false){
                var p = o.params;
                if(typeof p == "function"){
                    p = p.call(o.scope||window, o);
                }
                if(typeof p == "object"){
                    p = Ext.urlEncode(p);
                }
                if(this.extraParams){
                    var extras = Ext.urlEncode(this.extraParams);
                    p = p ? (p + '&' + extras) : extras;
                }
                var url = o.url || this.url;
                if(typeof url == 'function'){
                    url = url.call(o.scope||window, o);
                }
                if(o.form){
                    var form = Ext.getDom(o.form);
                    url = url || form.action;
                    var enctype = form.getAttribute("enctype");
                    if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
                        return this.doFormUpload(o, p, url);
                    }
                    var f = Ext.lib.Ajax.serializeForm(form);
                    p = p ? (p + '&' + f) : f;
                }
                var hs = o.headers;
                if(this.defaultHeaders){
                    hs = Ext.apply(hs || {}, this.defaultHeaders);
                    if(!o.headers){
                        o.headers = hs;
                    }
                }
                var cb = {
                    success: this.handleResponse,
                    failure: this.handleFailure,
                    scope: this,             
                    argument: {options: o},
                    timeout : this.timeout
                };
                var method = o.method||this.method||(p ? "POST" : "GET");
                   if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
                    url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
                }
                if(typeof o.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)) {
                 if (o.scriptTag || this.scriptTag) {
                   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) {
            var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
            var trans = {
                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);
            var conn = this;
            window[trans.cb] = function(o){
                conn.handleScriptResponse(o, trans);
            };
    //      Set up the timeout handler
            trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);
            var script = document.createElement("script");
            script.setAttribute("src", url);
            script.setAttribute("type", "text/javascript");
            script.setAttribute("id", trans.scriptId);
            document.getElementsByTagName("head")[0].appendChild(script);
            return trans;
        },
        handleScriptResponse : function(o, trans){
            this.transId = false;
            this.destroyScriptTrans(trans, true);
            var options = trans.options;
    //      Attempt to parse a string parameter as XML.
            var doc;
            if (typeof o == 'string') {
                if (window.ActiveXObject) {
                    doc = new ActiveXObject("Microsoft.XMLDOM");
                    doc.async = "false";
                    doc.loadXML(o);
                } else {
                    doc = new DOMParser().parseFromString(o,"text/xml");
                }
            }
    //      Create the bogus XHR
            response = {
                responseObject: o,
                responseText: (typeof o == "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);
            var options = 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){}
                };
            }
        }
    });
}

(2) 在需要跨域请求的页面引入该文件
并在Ready函数中执行SetCrossDomain();并添加一下代码:
 

复制代码 代码如下:
 SetCrossDomain();
 Ext.Ajax.request({ 
   url: 'http://xxxx.xxx.xxx',//跨域地址 
   scriptTag: true,  
   success: function(req) { 
     alert(req.responseText); 
   }, 
   failure: function(req) { 
     alert(req.responseText); 
   }, 
   headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM='}, 
   params: { _out: 'json' } 
 });

后台代码
 

复制代码 代码如下:

PHP:
  $json = "xxxxxxxxxxxxxxxxxxxxxxx";//你的json数据

  $callback_function = array_key_exists('callback',$_GET) ? $_GET['callback'] : null;
  if($callback_function != null)
  {
   $result = $callback_function ."(".$json).")";
  }
  else
 {
   $result = $json;
 }
 echo $result;

 ASP.NET:
        string json = "...........................";//你的json数据
        string response = json;

        string callBack = Request.QueryString["call_back"] as string;
        if (callBack != null)
        {
            response = callBack + "(" + json + ")";
        }

        Response.Write(response);
        Response.Flush();

通过以上处理,在需要跨域请求时使用方法一的ScriptTagProxy或方法二的scriptTag: true会在请求加上callback参数,后台自动处理,如果没有跨域,后台也会自动识别。
在跨域请求中前台只能以Get方式,因为嵌入脚本代码是用Get方式请求的。