2009-10-28 46 views
6

Voy a ser lo más específico y detallado posible e incluir parte del código que estoy usando. Ya hice una búsqueda y encontré this question, que parece similar; sin embargo, el autor utilizaba ActionScript 2 en lugar de 3, y parecía que no podía aplicar ninguna de las respuestas dadas a mi propia situación de manera efectiva.¿Cómo soluciono este error entre dominios de ActionScript 3?

Estoy tratando de emular (de forma limitada) el comportamiento del objeto XMLHttpRequest de JavaScript a través de Flash/ActionScript 3, para superar la limitación del mismo dominio. Pero descubro que ActionScript tiene sus propias limitaciones en ese sentido. Admito que podría estar equivocado, pero por lo que entiendo, teóricamente todavía es posible hacer este tipo de scripts de dominio cruzado utilizando ActionScript, siempre y cuando tenga todos los permisos correctos. Y ahí es donde me estoy metiendo en problemas.

Primero, tomé prestado algún código de código abierto para una clase llamada AjaxRequest, que guardé como /ajax/AjaxRequest.as. Luego creé un archivo Flash llamado /jsajax.fla que exporta al archivo SWF final, /jsajax.swf. Ahora, aquí está el código de ActionScript que comprende el primer y único fotograma del archivo Flash:

import ajax.AjaxRequest; 
Security.allowDomain("domainone.com"); 
Security.allowDomain("domaintwo.com"); 

function jsAjax(stringURL:String, stringMethod:String, stringData:String):void 
{ 
    var xhr:AjaxRequest = new AjaxRequest(stringURL); 
    xhr.contentType = "application/x-www-form-urlencoded"; 
    xhr.dataFormat = URLLoaderDataFormat.TEXT; 

    if (stringMethod.toUpperCase() == "POST") { 
     xhr.method = URLRequestMethod.POST; 
    } else { 
     xhr.method = URLRequestMethod.GET; 
    } 

    xhr.addEventListener("complete", jsAjaxResponse); 
    xhr.send(stringData); 
    return; 
} 

function jsAjaxResponse(evt:Event):void 
{ 
    ExternalInterface.call("jsAjaxResponse", evt.currentTarget.data.toString()); 
    return; 
} 

ExternalInterface.addCallback("jsAjax", jsAjax); 
ExternalInterface.call("jsAjaxReady"); 

Hasta ahora todo bien. Tengo la sensación de que una o más de esas llamadas Security.allowDomain no son necesarias, pero fueron mis intentos (infructuosos) de intentar resolver este problema.

En mi JavaScript, tengo tres funciones definidas: jsAjax, jsAjaxResponse y jsAjaxReady. La última es solo una función muy básica que se utiliza para indicar que el objeto Flash se cargó correctamente (que solo se llama una vez e inmediatamente después de cargarlo), mientras que los otros dos se utilizan para enviar y recibir los datos. Como puede ver, tienen contrapartes de ActionScript correspondientes.

Por último, creé una página HTML sencilla llamada /test.html que incrusta el archivo SWF (usando swfobject) y tiene un par de controles de formulario simples para llamar a la función jsAjax. Todas mis definiciones de JavaScript están incrustadas en este archivo HTML también. También creé un script PHP muy simple llamado /test.php que imprime los contenidos de la matriz $_REQUEST. Esa es la secuencia de comandos que pretendo solicitar con este método ajax.

Hay tres escenarios que he probado, pero sólo fue capaz de conseguir dos de ellos de trabajo:


Escenario uno: Todo en un servidor de
Si subo todos estos archivos a domainone.com, y luego solicite test.php, funciona bien. Mi estructura de archivos/carpetas a continuación, se ve así:

domainone.com/jsajax.swf 
domainone.com/test.html 
domainone.com/test.php 

Una vez más, esto funciona . La función jsAjaxResponse recibe nuevamente los datos de test.php.


Escenario dos: en ambos servidores, reclinado a la izquierda
Cuando he subido el código HTML y SWF al primer servidor, y luego acabo de llamar a que el script PHP en el segundo servidor, no lo hizo trabajar de inmediato Investigué un poco y descubrí que al crear un archivo crossdomain.xml en domaintwo.com que otorgaba acceso a domainone.com, esto lo arreglaba.Así que mi estructura de archivos/carpetas se veía así:

domainone.com/jsajax.swf 
domainone.com/test.html 
domaintwo.com/test.php 
domaintwo.com/crossdomain.xml 

Cuando se permite explícitamente domainone.com en el archivo crossdomain.xml, esto funciona. De nuevo, la función jsAjaxResponse recibe nuevamente los datos de test.php.


Escenario tres: en ambos servidores, inclinándose derecho
Cuando he subido todos, pero el HTML para domaintwo.com, yo ya no podía conseguir que funcione. En otras palabras, el HTML en domainone.com hace referencia a un archivo SWF alojado en domaintwo.com, y ese archivo SWF intenta realizar una solicitud a domaintwo.com. Dejé el mismo archivo crossdomain.xml del Escenario 2, por si acaso. Mi estructura de archivos/carpetas se veía así:

domainone.com/test.html 
domaintwo.com/jsajax.swf 
domaintwo.com/test.php 
domaintwo.com/crossdomain.xml 

Este es el único caso que no podía conseguir trabajo, y este es el caso de que necesite para conseguir trabajo. Los primeros dos fueron realmente solo escenarios de prueba para ver si el script estaba funcionando. Cuando trato de ejecutar mi función jsAjax aquí, termino con un error que aparece dos veces en Firebug:

uncaught exception: Error calling method on NPObject! [plugin exception: Error in Actionscript. Use a try/catch block to find error.]. 
uncaught exception: Error calling method on NPObject! [plugin exception: Error in Actionscript. Use a try/catch block to find error.]. 

Ayuda! ¿Cómo lo hago funcionar en el escenario 3?

Respuesta

4

¡Lo descubrí! Tenía que ver con los comandos Security.allowDomain en mi archivo Flash. De hecho, estaba hospedando el test.html en un subdominio de domainone.com, y eso lo estaba tirando. Tiene que ser una coincidencia exacta, subdominio y todo. ¡Resulta que no necesitaba el comando Security.allowDomain que hacía referencia a domaintwo.com, ni necesitaba el archivo crossdomain.xml para estar presente en el Escenario 3!

Dado que en la versión "real" de este script que termino usando, no necesariamente saben lo que realmente es domainone.com, he cambiado el código en la parte superior del archivo Flash para esto:

import ajax.AjaxRequest; 
try { 
    var domain1:String = LoaderInfo(this.root.loaderInfo).parameters["allow"]; 
    if (domain1.length > 0) { 
     Security.allowDomain(domain1); 
    } 
} catch (error:Error) { } 
try { 
    var domain2:String = LoaderInfo(this.root.loaderInfo).parameters["allowhttps"]; 
    if (domain2.length > 0) { 
     Security.allowInsecureDomain(domain2); 
    } 
} catch (error:Error) { } 
... 

Luego, en el JavaScript que estoy usando para incrustar el SWF allí en primer lugar, básicamente tomo el dominio actual de la página de document.location.toString(), verifico si está usando http o https, y luego paso el dominio como allow y/o allowhttps en el parámetro flashvars. Puede haber una forma "mejor" de hacer esto que no dependa de configurar el dominio de forma explícita en los Flash Vars (algún tipo de detección automática desde dentro de Flash), pero no soy lo suficientemente versado en ActionScript como para entender que fuera. Y dado que este archivo ya está haciendo una gran cantidad de comunicación bidireccional entre JavaScript y ActionScript, no es gran cosa. Esta solución es lo suficientemente buena para mí.