Weather Doll Local weather

none none none
none Google's Weather API in Flash

These are my notes that I collected as I tried to make google weather API work in Flash.
Here is a running version: Flash app using google weather feed

Google weather API

The base URL
http://www.google.com/ig/api?

The weather parameter
Multiple ways to set the weather parameter (Google's Weather XML API)
1) US postal code (i.e. google.com/ig/api?weather=90120)
2) Canadian postal code (i.e. google.com/ig/api?weather=V9B1A7)
3) City, state (US or canadian) (i.e. google.com/ig/api?weather=toronto,ON)
4) City, country (Sometimes there are multiple cities with the same name in one country, in that case it does not work, i.e. Victoria,BC works but Victoria,Canada does not)

The hl parameter (language parameter)
The default setting, if not defined, is hl=en
You can test it with French, hl=fr (i.e. google.com/ig/api?weather=V9B1A7&hl=fr)
The language code will NOT change the XML tags, only the data in those tags
The list of legal language codes (ISO 639-1) is in the reference section below

Google's weather information is provided by Weather Underground (wunderground.com)



Flash actionscript

Created a bare bones hard coded flash program to retrieve the file. This works locally.

var city:String = "Toronto,ON"; // hard coded the city while testing
var xml:XML = new XML();
var urlloader:URLLoader = new URLLoader();

urlloader.load( new URLRequest("http://www.google.com/ig/api?weather="+city) );
urlloader.addEventListener("complete", xmlComplete);

function xmlComplete(e:Event):void
{
xml = XML(e.target.data);
trace(xml);

var tf:TextField = new TextField();
tf.text = "Temp: "+city+" \n"+xml.weather.current_conditions.temp_c.@data+" Celsius";
addChild(tf);
}


Policy files

The reason this did not work when I posted it up on the website was because of Adobe's Flash Security sandbox. They implemented restrictions in manipulating data retrieved from other sites. You can still load images, swf's or other objects into your flash file as long as you are NOT manipulating them, as soon as you wish to massage the data you would run into security restrictions.

What is the security model they use?
Policy files, crossdomain.xml

Flash tries to retrieve this file using the default name crossdomain.xml and assuming it's located in the root directory of a web site.
In this case it's http://google.com/crossdomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="by-content-type" />
</cross-domain-policy>

As we can see we are NOT granted permission to access this content.
What we would be looking for was something along the lines of allow-access-from domain="*".
(see references below for specification pf crossdomain policy file)


Proxy (first run)

To get around this you could request specific inclusion of your domain.
Or they create access for all (allow-access-from domain="*").
Since the above requests are unlikely to be granted the best option left is to create a simple proxy. All you need to do is read the xml document and display it again.
My preference is PHP and Snoopy (see references below for download page for Snoopy)

header("Content-type: text/xml");
$weather = $_GET["weather"];
include "Snoopy.class.php";
$snoopy = new Snoopy;

if ($snoopy->fetch("http://www.google.com/ig/api?weather=".$weather))
{
echo $snoopy->results;
} else
echo "Snoopy: error while fetching document: ".$snoopy->error."\n";

And you would change your URLRequest in flash to ...
new URLRequest("http://weatherdoll.com/xml_proxy.php?weather="+city);


Proxy (second run)

After reviewing the code (always a good practice), I realize I don't snoopy since all I am doing is loading the file and displaying it through the proxy.

The second proxy uses readfile (you could also use fopen, fpassthru, fclose)

In addition we tightened up the headers, for example if the server zips up the file before sending it, we set the compression to off to prevent errors on certain browsers.
We also set the cache to false, (we should actually set the cache to 1 hour)
And we also store a local copy of the XML file that we get, so we don't bombard google with multiple requests of the same data in the span of a few minutes.


ini_set("zlib.output_compression", "Off");
header("Content-type: text/xml");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: no-cache');

$weather = $_GET["weather"];

$url = "http://www.google.com/ig/api?weather=".urlencode($weather);
$file = "_weather_".str_replace( array(","," "), "_", $weather).".xml";

ob_clean();
flush();

// check if a local file less than an hour old is already on file
if (!file_exists($file) || filemtime($file) < time() - 3600 || filesize($file) == 0)
{
ob_start();
readfile($url);
$google_xml = ob_get_clean();

echo $google_xml;

// save local copy of xml
$handle = fopen($file,w);
fwrite($handle, $google_xml);
fclose($handle);
} else
{
// load local copy of xml
ob_start();
readfile($file);
$google_xml = ob_get_clean();
echo $google_xml;
}


Concerns still linger on using this API since Google does not publicly endorse it.


Summary

I put up all my reference material on this page to help others (and myself) whenever I need to update the project.
Like all good projects, you get to where you are going through the help of others.

Note to self: getting the degree symbol on the mac, shift + option + 8


References:
PHP caching using ouput buffering
PHP Snoopy download
Crossdomain Policy file specification
Poking holes in policy files
Google Weather API by emerick.org
Android Weather API
Yahoo Weather API XML / RSS
Weather.com sigup for free XML feed
List of ISO 639-1 codes
none
none none none



Contact: elouai@gmail.com