首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于SWF的xhr和amplifyJS - Status 200,但是执行错误函数

基于SWF的xhr和amplifyJS - Status 200,但是执行错误函数
EN

Stack Overflow用户
提问于 2013-07-18 17:12:11
回答 2查看 605关注 0票数 0

我有一个SWF对象的实现,用于修改针对IE的跨域请求的XHR对象。

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

代码语言:javascript
复制
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:无效字符

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

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

来自IE的响应机构是:

代码语言:javascript
复制
{
"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中只有一个反斜杠的用户名。

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

代码语言:javascript
复制
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;
    }

}

//
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-20 11:31:18

public function onData( data:String )中,数据没有正确的转义。

在将其修改为下面的内容之后,事情就像预期的那样工作了:

代码语言:javascript
复制
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);
}
票数 0
EN

Stack Overflow用户

发布于 2013-07-19 22:58:56

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17729922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档