Loading XML from different domain through Flash AS3

This time I was working with flash and AS3 to load and XML feed.
I discovered that Flash can not load assets from a different domain where the movie is located. There are two ways to solve this problem and I explain them in this post.

Project description

The project is very simple. A flash banner that loads an XML from a web application. This XML contains the information about the medalls of London 2012 Olympics.

The web application is a CakePHP custom content manager that administer a MySQL table with these fields: country, flag, number of gold, silver and bronze medalls.

The SWF files should be in the customer's domain so they could count how many visits they have. The web application should be in another server so I can use it for more than one purpose.

 

Problem loading XML

To load XML is just simple like this:

 

var FLAGS_NUMBER:Number = 6;
var URL_DOMAIN:String = "http://webdev.lightbyte.org/olympics/";

var xmlString:URLRequest = new URLRequest(URL_DOMAIN + "countries/medalls.xml?numitems=" + FLAGS_NUMBER);
var xmlLoader:URLLoader = new URLLoader(xmlString);
xmlLoader.addEventListener("complete", init);

function init(event:Event):void{
  var medallsXML:XML = XML(xmlLoader.data);
  for(var i:Number = 0; i < medallsXML.country.length() && i < FLAGS_NUMBER; i++) {
    var foo:CountryLoader = new CountryLoader(i, medallsXML.country[i], main, URL_DOMAIN);
    main.countries.addChild(foo.getCountryObj());
  }
}

This AS3 snippet will work if the SWF file is in the same domain that the XML file which is trying to load. If you try the flash movie stright from the Flash environment, it will work perfectly, but if you try to run the SWF file from the final domain (different than XML file location) won't work and no errors will be shown.

 

Solutions

Searching on Internet I found the reason why this problem happens. This "problem" is not such a problem at all, because I understood that it's just some flash protection. The name of the problem is Cross-domain Policy. In the link you will find more information to understand this feature of Flash.

There are two ways to solve this issue:

1. crossdomain.xml

This way is the most easiest. You just add a file called crossdomain.xml in the root of domain where the XML file resides.

For example, if the path to XML file is

http://webdev.lightbyte.org/olympics/countries/medalls.xml

then you should copy the crossdomain.xml file in

http://webdev.lightbyte.org

 

The file itself can be like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>

In the allow-access-from tag the asterisk in the domain property means that wherever the SWF file is will have rights to access to the XML file.

If you want to limit the access to a certain domain you can change the asterisk "*" for the domain you want, for example "http://www.lightbyte.org".

You can add more lines of allow-access-from as you want.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="http://lightbyte.org" />
<allow-access-from domain="http://webdev.lightbyte.org" />
</cross-domain-policy>

For more information on this go to oficial site of adobe.

 

2. proxy.php

Another way to solve the problem is working a bit with PHP.

You have to create a small PHP file in the same location that the SWF file will be. Let's call it proxy.php. This PHP will receive a parameter named target_url where it will receive the URL to load, in other words, the URL to the XML file. Finally it will return the contents of the XML.

The source file will explain better than the words.

<?php

/*
 * First option, fopen.
 */
fopen($_GET['target_url'], 'r');
echo fread();
fclose();

?>

Another possible version of this PHP file would be this one:

<?php

/*
 * Second option, CURL.
 */
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET['target_url']);
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
echo curl_exec($ch);
curl_close($ch);

?>

Another way to write this PHP file can be like this too:

<?php

/*
 * Thirth option, file_get_contents.
 */
echo file_get_contents($_GET['target_url']);

?>

Also you have to change some lines in your AS3 in order to load contents from the proxy.php file explained above. The AS3 would look like this:

var FLAGS_NUMBER:Number = 6;
var URL_DOMAIN:String = "http://webdev.lightbyte.org/olympics/";

/*
 * These are the new lines.
 */
var url:String = "proxy.php";
// paramVal will contain the escaped URL to the XML file so it can be transmited as a GET parameter.
var paramVal:String = encodeURIComponent(URL_DOMAIN + "countries/medalls.xml?numitems=" + FLAGS_NUMBER);
// Adding parameter to the proxy.php
url += "?target_url=" + paramVal;
var xmlString:URLRequest = new URLRequest(url);

var xmlLoader:URLLoader = new URLLoader(xmlString);
xmlLoader.addEventListener("complete", init);

function init(event:Event):void{
  var medallsXML:XML = XML(xmlLoader.data);
  for(var i:Number = 0; i < medallsXML.country.length() && i < FLAGS_NUMBER; i++) {
    var foo:CountryLoader = new CountryLoader(i, medallsXML.country[i], main, URL_DOMAIN);
    main.countries.addChild(foo.getCountryObj());
  }
}

This way is working like a charm in my local server but when I uploaded it to the online hosting it threw these errors:

/*
 * Error when using fopen version php file
 */
Warning: fopen() [function.fopen]: URL file-access is disabled in the server configuration


/*
 * Error when using curl version php file
 */
Warning: curl_exec() has been disabled for security reasons


/*
 * Error when using file_get_contents version php file
 */
Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration

 

All of these errors are shown because the parameter allow_url_fopen has to be turned on in the php configuration file (php.ini).

I'm sure that if I call to my hosting they would be glad to turn it on for me, but having the first solution they don't deserve to be bothered.

 

Sat, Aug 4th 2012, 16:35 | AS3

0 Comments

Add New Comment

Your name:
Your e-mail:
Your web page:
Comment:
I would like to receive new comment notification.
Security code: