0

我有一个 SWF 对象的实现来修改 IE 的跨域请求的 XHR 对象。

一旦对象可用,我将像这样修改 XHR:

if ($.browser.msie) {
    amplify.subscribe("request.before.ajax", function (resource, settings, ajaxSettings, xhr) {
        if (resource.url.indexOf(requestConfig.apiUrl) != -1) {
            xhr.setRequestHeader("Accept", "application/xml, text/xml");
            var shr = new SWFHttpRequest();                
            ajaxSettings.xhr = function () {
                return shr;
            };
            ajaxSettings.crossDomain = false;
            ajaxSettings.error = function (e) {
                // Returns the data object I expect:
                alert(e.responseText);
            }
        }
    });
};

我的 jQuery ajaxError 抛出的错误是: SyntaxError: Invalid character

  • 该错误是由反斜杠引起的:

例如,当在我的 JSON 中:"Username" : "DOM\\PRO4"它以某种方式进入"DOM\PRO4"浏览器并给出语法错误。但是服务器正在转义,因为我可以看到从服务器发送的原始数据有 \ 但由于某种原因,我可以理解闪存可能会破坏这一点。

在此处输入图像描述

在此处输入图像描述

来自 IE 的响应正文是:

{
"ResponseCode": 200,
"ResponseDescription": "OK",
"ResponseEntity": [
    {
        "Id": "6d0d9471-f118-4984-9182-a20300a037b6",
        "Name": "DYN",
        "ConnectionTypeId": "20000000-0000-0000-0003-000000000003",
        "ConnectionTypeName": null,
        "Address": "http://54.229.51.444:7777/CRMServer",
        "UserName": "DOM\\PRO4",
        "Password": "",
        "AddedById": "20000000-0000-0000-0004-000000000001",
        "DateAdded": "07/22/2013 09:43:20",
        "DateModified": "22/07/2013 15:00:01",
        "ModifiedById": "",
        "TypeName": "Dynamics"
    }
]
}

您可以看到用户名已正确转义,但 ajax 设置错误警报显示 responseText 中的用户名只有 1 个反斜杠。

如果您还需要查看 SWF 对象,它是使用 haxe 开发的开源模块的修改版本:

import flash.external.ExternalInterface;
import flash.Lib;
import haxe.Http;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.display.Sprite;

class SWFHttpRequest {

    public static var ver:String = '0.3';

    public static var transports:Map<String,Transport> = new Map();

    public static function abort( instance:Int ) {
        transports.get( instance + '' ).abort();
    }

    public static function open( instance:Int, method:String, url:String ) {
        transports.set( instance + '', new Transport( instance, method, url ) );
    }

    public static function send( instance:Int, data:String ) {
        transports.get( instance + '' ).send( data );
    }

    public static function setRequestHeader( instance:Int, header:String, value:String ) {
        transports.get( instance + '' ).setRequestHeader( header, value );
    }

    public static function version() {
        return ver;
    }

    private static function onLoaded(event:Event):Void
    {
        flash.external.ExternalInterface.call("swfHttpLoaded");
    }

    public static function main() {
        flash.system.Security.allowDomain("*");     
        ExternalInterface.addCallback("abort",abort);
        ExternalInterface.addCallback("open",open);
        ExternalInterface.addCallback("send",send);
        ExternalInterface.addCallback("setRequestHeader",setRequestHeader);
        ExternalInterface.addCallback("SWFHttpRequestVersion",version);
        ExternalInterface.call( [ "(function(){",
            "if (window.SWFHttpRequest) return;",
            "var Class = function(properties){",
                "var klass = function(){ return this.abort.apply(this); };",
                "klass.prototype = properties;",
                "klass.constructor = arguments.callee;",
                "return klass;",
            "};",
            "window.SWFHttpRequest = new Class({",
                "abort: function(){",
                    "if (typeof this.instance != 'undefined') {",
                        "window.SWFHttpRequest.instances[this.instance] = null;",
                        "window.SWFHttpRequest.engine.abort( this.instance );",
                    "}",
                    "this.readyState = 0;",
                    "this.responseText = '';",
                    "this.responseXML = null;",
                    "this.status = 0;",
                    "this.statusText = '';",
                    "this.instance = window.SWFHttpRequest.instances.length;",
                    "window.SWFHttpRequest.instances.push( this );",
                "},",
                "getAllResponseHeaders: function(){ return null; },",
                "getResponseHeader: function(){ return null; },",
                "onreadystatechange: null,",
                "open: function(method, url, async, user, password){",
                    "this.status = 0;",
                    "this.readyState = 1;",
                    "this.statusText = this.responseText = '';",
                    "this.responseXML = null;",
                    "window.SWFHttpRequest.engine.open( this.instance, method, url );",
                "},",
                "send: function(data){",
                    // TODO: Once haxe.Http supports setPostData() for flash9 targets, this function
                    // should be updated to allow for a Document as the data.  When that's the case,
                    // it should be serialized as XML prior to sending over to the Flash executor.
                    "window.SWFHttpRequest.engine.send( this.instance, data );",
                "},",
                "setRequestHeader: function(header, value){",
                    "if (this.readyState != 1 || !header || !value) return;",
                    "window.SWFHttpRequest.engine.setRequestHeader( this.instance, header, value );",
                "}",
            "});",
            "window.SWFHttpRequest.instances = [];",
            "window.SWFHttpRequest.version = '" + ver + "';",
            "var f = function(tag){",
                "var elems = document.getElementsByTagName(tag);",
                "for (var i=0; i<elems.length; i++) if (elems[i].SWFHttpRequestVersion) return elems[i];",
            "};",
            "window.SWFHttpRequest.engine = f('embed') || f('object');",
        "})" ].join('') );
        var params = Lib.current.loaderInfo.parameters;
        if (Reflect.hasField(params,'onload')) ExternalInterface.call( Reflect.field(params,'onload') );
        Lib.current.loaderInfo.addEventListener(Event.COMPLETE, onLoaded);
    }
}

class Transport {

    var active:Bool;
    var instance:Int;
    var method:String;
    var url:String;
    var http:Http;

    public function new( instance:Int, method:String, url:String ) {
        this.active = true;
        this.instance = instance;
        this.method = method.toUpperCase();
        this.url = url;
        this.http = new Http( this.url );
        this.http.onData = this.onData;
        this.http.onError = this.onError;
        this.http.onStatus = this.onStatus;     
    }

    public function send( ?data:String ) {
        if ( data==null ) return this.http.request( this.method=='POST' );
        // NOTE: Once haxe.Http supports the setPostData() method for flash9 targets,
        // all the following should be replaced by: this.http.setPostData( data );
        // var re = ~/^(.*?)=(.*)$/;
        // var pairs:Array<String> = data.split('&');
        // var ud = function(s){
            // try { return StringTools.urlDecode(s); }
            // catch ( e:Dynamic ) { }
            // return s;
        // };
        // for( i in 0...pairs.length ) {
            // if (re.match(pairs[i])) this.http.setParameter( ud(re.matched(1)), ud(re.matched(2)) );
            // else this.http.setParameter( ud(pairs[i]), '' );
        // }
        this.http.setPostData( data );
        return this.http.request( this.method=='POST' );
    }

    public function setRequestHeader( header:String, value:String ) {
        this.http.setHeader( header, value );
    }

    public function onData( data:String ) {
        if (!this.active) return;
        ExternalInterface.call( [ "(function(instance, data){",
            "var shr = window.SWFHttpRequest.instances[instance];",
            "if (!shr) return;",
            "shr.status = 200;",
            "shr.statusText = 'OK';",
            "shr.readyState = 4;",
            "shr.responseText = data;",
            "try {",
                "if (window.DOMParser) {",
                    "var dp = new DOMParser();",
                    "shr.responseXML = dp.parseFromString( data, 'text/xml' );",
                "} else {",
                    "shr.responseXML = new ActiveXObject('Microsoft.XMLDOM');",
                    "shr.responseXML.async = 'false';",
                    "shr.responseXML.loadXML(data);",
                "}",
            "} catch(error) { shr.responseXML = null; }",
            "if (shr.onreadystatechange && typeof shr.onreadystatechange=='function') shr.onreadystatechange();",
        "})" ].join(''), this.instance, data);
    }

    public function onError( msg:String ) {
        if (!this.active) return;
        ExternalInterface.call( [ "(function(instance){",
            "var shr = window.SWFHttpRequest.instances[instance];",
            "if (!shr) return;",
            "shr.status = 404;",
            "shr.statusText = 'Not Found';",
            "shr.readyState = 4;",
            "shr.responseText = null;",
            "shr.responseXML = null;",
            "if (shr.onreadystatechange && typeof shr.onreadystatechange=='function') shr.onreadystatechange();",
        "})" ].join(''), this.instance );
    }

    public function onStatus( status:Int ) {
        if (!this.active || status==200) return;
        ExternalInterface.call( [ "(function(instance, status){",
            "var shr = window.SWFHttpRequest.instances[instance];",
            "if (!shr) return;",
            "shr.status = status;",
            "if (shr.onreadystatechange && typeof shr.onreadystatechange=='function') shr.onreadystatechange();",
        "})" ].join(''), this.instance, status );
    }

    public function abort() {
        this.active = false;
    }

}

//
4

2 回答 2

0

您不再需要使用 Flash 进行跨域 XHR,即使在 IE 中也是如此。从您的图像来看,CORS 标头已启用。

所有主流浏览器和 IE 10+ 都原生支持跨域请求。早期版本的 IE 支持检查标头的XDomainRequest对象Access-Control-Allow-Origin(部分 CORS 支持)。

因此,除非您确实需要支持 IE 7 或更低版本,否则请使用常规XMLHttpRequestXDomainRequest.

于 2013-07-19T22:58:56.413 回答
0

in public function onData( data:String )data 没有正确的转义。

将其修改为以下内容后,现在可以按预期工作:

public function onData( data:String ) {
    if (!this.active) return;
    var stringified = haxe.Json.stringify(haxe.Json.parse(data));
    var stringifiedEscaped = StringTools.replace(stringified, "\\", "\\\\");
    ExternalInterface.call( [ "(function(instance, data){",
        "var shr = window.SWFHttpRequest.instances[instance];",
        "if (!shr) return;",
        "shr.status = 200;",
        "shr.statusText = 'OK';",
        "shr.readyState = 4;",
        "shr.responseText = data;",
        "try {",
            "if (window.DOMParser) {",
                "var dp = new DOMParser();",
                "shr.responseXML = dp.parseFromString( data, 'text/xml' );",
            "} else {",
                "shr.responseXML = new ActiveXObject('Microsoft.XMLDOM');",
                "shr.responseXML.async = 'false';",
                "shr.responseXML.loadXML(data);",
            "}",
        "} catch(error) { shr.responseXML = null; }",
        "if (shr.onreadystatechange && typeof shr.onreadystatechange=='function') shr.onreadystatechange();",
    "})" ].join(''), this.instance, stringifiedEscaped);
}
于 2013-07-20T11:31:18.383 回答