RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Against the Browser's Will: Make Mashups Talk Across Domains : Page 2

With all the great Web service APIs out there today, making mashups to extend public Web-based apps is a new passion for many developers. But cross-domain restrictions, built into all major browsers, are an aggravating foe. Learn to use a PHP proxy or JSON to eliminate your mashup frustrations.

Ways Around Cross-Domain Requests
An application that wants to retrieve data at runtime can use JavaScript and the XMLHTTPRequest object to make an HTTP request. Unfortunately, the XMLHTTPRequest object that browsers like Firefox and IE provide enforces a cross-domain restriction that does not allow HTTP calls from one domain to another. Modern Web applications depend on the ability to make these calls to provide a richer user experience.

The sample below will use Yahoo's geocoding Web service. This is a REST service where REST gets transported over HTTP; it is, therefore, subject to the cross-domain restrictions. There are a couple of ways to get around this restriction:

In this article I will only discuss the first two approaches since these do not require installation of Apache or write-access to the .htaccess file.

Software Proxy: What can PHP Do for You?
The easiest approach is to write a proxy that lives on the same server as the application, which passes only the request and response to and from the web server. There is a slight security risk since every proxy runs the risk of getting abused, but the sample in Listing 2 shows that you can limit the access. This works great for my example scenario. Listing 2 shows how to display a map with a marker in the middle, which opens a box when it gets clicked.

All that and more can be found in the GettingStartedGuide for AJAX. It gets a little more interesting when data sources come into play. A PHP file will serve as a proxy to overcome the cross-domain restrictions.

  header("Content-type: text/xml\n\n");
  $url = $_SERVER['QUERY_STRING'];
  //strpos allows only calls to specified endpoint
  if ( strpos($url,"http://api.local.yahoo.com/") === 0)
    $ch = curl_init($url);
This is a really simple proxy that is transparent for GET requests. To run the proxy, the PHP Curl extension needs to be enabled.

Now that the proxy is in place I am able to make a REST call, but only to api.local.yahoo.com. In the next example I will fix this by allowing the user to type in an address, which will be displayed on the map. MapProxy is the complete file, found in the downloadable ZIP file that accompanies this article.

Here, I will run through the MapProxy code block and discuss each step:

<div class="inputelement">
<input id="geoquery" value="5th Avenue,New York" size="50">
<button onClick="addGeocode()"> Add location</button> 
Once the button is pressed, the function addGeocode() gets called. It assembles the REST query and does a XmlHttpRequest to the proxy with the REST URL as parameter. While it waits for the proxy to complete the request it displays 'Loading' on the bottom of the page. The PHP proxy uses CURL to make the actual request, and the callback method parseResult() gets executed once the call has succeeded.

var query = document.getElementById("geoquery").value;
var target = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=devxsample&location=" + query; 
if(target !== ""){
  var url = 'yproxy.php?' + encodeURI(target);
  xmlhttp.open('GET', url, true);
  xmlhttp.onreadystatechange = function() {
    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      document.getElementById('result').innerHTML = '';
      //callback method 
    } else {
      document.getElementById('result').innerHTML = "Loading...";
From here, all that's left is parsing the XML and adding the markers. Because this is a very simple result string, I use 'regex' to pull out the latitude and longitude, and then use the values to create and add the marker as seen above.

function parseResult(result, service) { var start = (result.search(/<Latitude>/) +10 );
  var end = result.search(/<\/Latitude>/)
  var lat = result.substr(start, (end -start) );

  start = (result.search(/<Longitude>/) +11 );
  end = result.search(/<\/Longitude>/)
  var lon = result.substr(start, (end -start) );

  var point = new YGeoPoint(parseFloat(lat),parseFloat(lon));
  var smart = "<div style='width: 110px; color: black; font-size: small; margin: 0 3px 2px 3px;'>"
  smart += "Long: " + lon + "<br />" + "Lat: " + lat;
  var myMarker = createYMarker(point, 1, smart);
  ymap.drawZoomAndCenter(point, 6);

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date