ebook img

Professional Rich Internet Applications: AJAX and Beyond (Programmer to Programmer) PDF

603 Pages·1983·2.45 MB·English
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Professional Rich Internet Applications: AJAX and Beyond (Programmer to Programmer)

Chapter 3: The Programmable Web: The Mashup Ecosystem Listing 3-5 shows PHPcode for managing the proxy for the XMLQueryExample.html(Listing 3-2) example above. Listing 3-5: xmlQuery.php PHP 1 <?php 2 header(“Content-type: text/xml”); 3 $url = $_SERVER[‘QUERY_STRING’]; 4 if ( strpos($url,”http://api.search.yahoo.com/”) === 0) 5 { 6 $ch = curl_init(); 7 curl_setopt($ch, CURLOPT_URL,$url); 8 $xml = curl_exec($ch); 9 curl_close($ch); 10 echo $xml; 11 } 12 ?> Notice that you specify to the browser a return type of text/xmlfor the content. Listing 3-6 is the PHPcode for managing the proxy for the JSONQueryExample.html example above. Listing 3-6: json.php PHP 1 <?php 2 header(“Content-type: text/plain”); 3 $url = $_SERVER[‘QUERY_STRING’]; 4 if ( strpos($url,”http://api.search.yahoo.com/”) === 0) 5 { 6 $ch = curl_init(); 7 curl_setopt($ch, CURLOPT_URL,$url); 8 $json = curl_exec($ch); 9 curl_close($ch); 10 echo $json; 11 } 12 ?> Here you specify a return type of text/plainfor the JSON content. Otherwise, the PHPis identical. Here, the URLthe Web application calls terminates in the current domain. Recall that the actual URLpassed tothe XMLHttpRequest’s openmethod terminates in the same Web server as the Web application— here are lines 22–23 of Listing 3-2: 22 var url = ‘../phpscripts/xmlQuery.php?’ + target; 23 xmlhttp.open(‘GET’, url, true); and lines 24–25 in Listing 3-4: 24 var url = ‘../phpscripts/json.php?’ + target; 25 xmlhttp.open(‘GET’, url, true); 95 Part I: An Introduction to RIAs In each case, the application appends an argument onto the URL; the argument representing the actual termination point of the request and the provider of the data. Thus, as far as the Web application is con- cerned, the PHPproxy terminates the request. In actual fact, the PHPcode relays your application’s request to another domain, in this case: http://api.search.yahoo.com/ImageSearchService/V1/imageSearch. Additionally,theproxysimplypassestheadditionalargumentsyouconstructedtothe externaldomain,inthisexample: ?appid=YahooDemo&query=rose&results=1&output=xml. Aproxy makes the operation easy to shuttle requests to and from other domains. In fact, it may make things too easy. Make no mistake: Aproxy has the potential to create a gaping security hole. However, you can mitigate this potential by rigorously constraining the potential forwarding domains. In Listing 3-5, for example, the first operation sets $urlfrom $_SERVER, which is a PHPdictionary that the Web server itself creates. The ‘QUERY_STRING’slot has as its value everything that the Web server passed to the PHPcode (i.e., the actual URLand its arguments). The PHPchecks the actual destination domain at Listing 3-5, line 4. If the domain is acceptable, it passes the request along, or else it does nothing. Here, the PHP5 CURL convenience library opens the connection and invokes the foreign server. The only significant difference between Listings 3-5 and 3-6 is that one sets the return header to be XMLand the other to be JSON. Working without a Proxy Proxies are slightly painful to set up, and even when you use one you still have to exercise some care about what sites you permit to return data back to your Web page-as-application. Consider the follow- ing scenario: Your application makes an outbound call, specifying the returned data representation as JSON. Your callback does an immediate eval of the JSON, and in it there’s a nefarious method that reads your cookies and does a subsequent HTTPPOST to a rogue Web site. Now your system is possibly com- promised. Although this is an extreme case, perhapsit could happen, although the odds seem acceptably low given that you have given thought to the validity of the data source you’re choosing to mashup, and your application is source-aware. Is working without a proxy really like a circus high-wire performer working without a net? Opinions are somewhat mixed, but given careful consideration, mashups can be (and have been) written that use an approach to get around the problem altogether. This is discussed in this chapter’s capstone application in the section “The Yahoo and Google Traffic Mashup.” XML or JSON As mentioned earlier, many sites produce output either in XMLor in JSON. Given a choice, which should you prefer? This is mostly a matter of personal style for many developers; certainly both representations have a variety of advocates, and libraries abound for both. One consideration that helps tip the scales is that JSON is already expressed as a native object in your application’s implementation language, and therefore is most easily consumed by your application code. Additionally, the json.js parser and string creation code is pretty compact overall—about 1K after being passed through JSMin (see www.crockford .com/javascript/jsmin.html), a nice open-source code compacter that eliminates spaces and other visual aids to code inspection (and as a side effect acts as a sort of minimal code obfuscator). 96 Chapter 3: The Programmable Web: The Mashup Ecosystem The Yahoo and Google Traffic Mashup In previous examples seen in Figures 3-2 and 3-6, you invoked one service to add a simple image search- and-retrieval capability to your page-based application. Now you can combine more than one service into a composite application that none of the specific services provides, and that’s the objective of this chapter’s capstone application, which might be deemed the “Find a Location, Map It, and Tell Me about Traffic Alerts” application. The capstone application for the chapter mashes up the following: ❑ The Google Maps dynamically produce a map and add it to the calling page. ❑ Yahoo’s geocoding produces a set of latitude and longitude coordinates from a location. ❑ Yahoo’s traffic alert annotates the map with relevant traffic information—at least for any urban U.S. area covered by the service. Each of the constituent segments is partially shown, followed by the composite application. Not only is this a practical learning application, but it also is helpful in daily use. The application uses Yahoo’s geocoder to convert a location description into latitude/longitude pairs. This is necessary because Google will onlyaccept a latitude/longitude pair to create the contents of a map; thus, the services com- plement each other in a way that the individual API creators had not envisioned—the perfect definition of a mashup. Getting a Geocode Having worked through previous example mashups in the chapter you are familiar with the code strat- egy by now: 1. Find an interesting and useful API. 2. Determine the data representation it returns. 3. Code a proxy to access it. 4. Create an XMLHttpRequest as a transport mechanism. 5. Attach a callback function to the request. 6. Parse the results and populate DIV or SPAN sections of the document appropriately This is precisely what you do in the next listing, which shows the functionality of first third of the ulti- mate mashup. Again, you can download the code from http://RIABook.ideastax.com/ Chapter03.zip. The application is shown in Figure 3-11. The user enters location information (in this case the address of Fenway Park) and in return gets a latitude/longitude pair. You can try this out at http://RIABook.ideastax.com/RIA/GeoCodeProxy.html, which is created from the code shown inListing 3-7. 97 Part I: An Introduction to RIAs Figure 3-11 Listing 3-7: GeocodeProxy.html HTML 1 <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” ; “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”> 2 <html xmlns=”http://www.w3.org/1999/xhtml” xmlns:v=”urn:schemas-microsoft- com:vml”> 3 <head> 4 <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8”/> 5 6 <title>Yahoo! Geocoder</title> 7 <link rel=StyleSheet href=”../../stylesheets/RIAStyle1.css” TYPE=”text/css”> 8 <script src=”../../scripts/createXMLHttpRequest.js” ; type=”text/javascript”></script> 9 10 <script type=”text/javascript”> 11 //<![CDATA[ 12 var __xmlhttp = false; 13 var __appid = “YahooDemo”; 14 15 function callWS(target) { 16 if(target !== “”){ 17 var url = ‘../../phpscripts/geocoder.php?’ + encodeURI(target); 18 __xmlhttp.open(‘GET’, url, true); 19 __xmlhttp.onreadystatechange = function() { 20 if(__xmlhttp.readyState == 4 && __xmlhttp.status == 200) { 21 document.getElementById(‘Result’).innerHTML = ‘’; 22 getLatLon(__xmlhttp.responseText); 98 Chapter 3: The Programmable Web: The Mashup Ecosystem 23 } else { 24 document.getElementById(‘State’).innerHTML = “Loading...”; 25 } 26 }; 27 __xmlhttp.send(null); 28 } 29 } 30 function getLatLon(result){ 31 var start = (result.search(/<Latitude>/) +10 ); 32 var end = result.search(/<\/Latitude>/); 33 var lat = result.substr(start, (end -start) ); 34 35 start = (result.search(/<Longitude>/) +11 ); 36 end = result.search(/<\/Longitude>/); 37 var lon = result.substr(start, (end -start) ); 38 39 document.getElementById(“Latitude”).innerHTML = lat; 40 document.getElementById(“Longitude”).innerHTML = lon; 41 document.getElementById(“State”).innerHTML = “”; 42 } 43 44 function onLoad() { 45 __xmlhttp = createXMLHttpRequest(); 46 } 47 function callGeocode() { 48 var query = document.getElementById(“geoquery”).value; 49 var uri = ; http://api.local.yahoo.com/MapsService/V1/geocode?appid= +__appid+”&location=” + query; 50 callWS(uri); 51 } 52 //]]> 53 </script> 54 </head> 55 56 <body onload=”onLoad()”> 57 <div id=”header”> 58 <h1>Simple Geocoding Example </h1> 59 <h2>Input a loose location description, and Yahoo’s Geocoding service ; returns a Latitude / Longitude pair</h2> 60 61 </div> 62 <br /> 63 <div class=”inputelement”><button onClick=”callGeocode()”>; Geocode Location</button>&nbsp; 64 <input id=”geoquery” value=”1300 N. 17th St, Arlington VA” ; size=”50”></input> 65 </div> 66 <br /> 67 68 <div id=”State”></div> 69 <div id=”Result”></div> 70 <p>Latitude: <span id=”Latitude” style=”font-weight:bold”></span> </p> 71 <p>Longitude: <span id=”Longitude” style=”font-weight:bold”></span> </p> 72 </body> 73 </html> 99 Part I: An Introduction to RIAs The code for the little request creator is now in a separate file and is included on line 8. At the end of the chapter is a general utility function that handles request creation and posting and getting requests. This is used frequently in subsequent chapters. Again (on line 17), the URI string attached to the proxy (geocoder.php) is encoded to deal with any potentially troublesome characters, using the browser’s built-in encoder. The getLatLon()function (beginning on Line 30) is an variant, designed to demonstrate to you that there are many ways to extract the returned data. When you explore this service, hand-coding a URL(for example: http://api.local.yahoo.com/ MapsService/V1/geocode?appid=YahooDemo&location=4%20Yawkey%20Way%20Boston,%20MA), you discover that just as in previous examples, the returned data representation is string data represent- ing XML. An example of the data returned from a direct invocation is shown in Figure 3-12. Figure 3-12 You can, as before, create a DOM parser, load the XML, and extract data that way. Alternatively, know- ing that a string is a string, you can just use built-in JavaScript string manipulation methods. That’s what lines 31–37 in getLatLon()do. You already know what you’re looking for: normally tagged NODEs; extracting them can be a simple matter. That completes the first part of the mashup. Now it’s time to examine Google’s Map API. The code shown in Listing 3-8 produces the application shown in Figure 3-13. 100 Chapter 3: The Programmable Web: The Mashup Ecosystem Listing 3-8: geocoder.php PHP <?php header(“Content-type: text/xml”); $url = $_SERVER[‘QUERY_STRING’]; if ( strpos($url,”http://api.local.yahoo.com /”) === 0) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); $xml = curl_exec($ch); curl_close($ch); echo $xml; } ?> You now have a way to convert a location described in free text into a geographic coordinate. Turning next to an example showing how you can get traffic for the location reveals something interesting. Figure 3-13 101 Part I: An Introduction to RIAs Getting the Traffic Report Figure 3-14 shows a simple application that serves as the basis for the traffic data portion of the chap- ter’s capstone mashup. In the figure, the user enters a location into the input box and the mashup retrieves the current traffic information. Figure 3-14 As mentioned in the section “Working without a Proxy,” you can work more directly with the data provider, without writing and deploying a proxy, without making an XMLHttpRequest, and without having to work with XML. If all this is not sufficient inducement, a final “sweetener” is that application performance is better as well. The code for the application is shown in Listing 3-8, and it presents a completely new way to interact with a data source, and at the same time dynamically direct the script logic. By now, you should be com- fortable with the concept that you can replace segments of a RIAPage’s document object model (DOM) tree without having to re-fetch and re-render the entire application container. That’s a fundamental AJAXism. The fuller implications may not have hit you yet, but they are about to. You may also have noticed that some elements in the RIAPage’s DOM have the quality that they are “execute immediate”: On encountering them, the browser deals with them immediately, substituting the data resulting from acting on the directive instead of the directive itself. You saw this effect in Listing 3-2, when you used the URI of the image retrieved by the search to construct an IMG tag: 102 Chapter 3: The Programmable Web: The Mashup Ecosystem 62 document.getElementById(“PictureURL”).innerHTML = 63 “<img src=\””+ 64 docRoot.getElementsByTagName(“ClickUrl”).item(0); .getFirstChild().getNodeValue() + 65 “\” alt=\””+ 66 docRoot.getElementsByTagName(“ClickUrl”).item(0). ; getFirstChild().getNodeValue() + 67 “\”/>” 68 ; The resulting “PictureURL”spantag(line 117 of Listing 3-2) didn’t show the IMGtag constructed on lines 62–68; rather, it populates with the resultof the browser’s having parsed and satisfied the directive contained in the tag—a nice picture of some parakeets. Furthermore, this happened dynamically, as aside effect of your overwriting a node in your RIAPage’s DOM tree. The fact that browsers do this “execute immediate” trick has been true ever since the first browser. Every modern browser understands that it should do the same thing with elements in the HEAD, such as LINKtags, which include a href=”URI”attribute for specifying cascading style sheets to import, and SCRIPTtags, where the src=”URI”tag attribute is used. In both cases, the browser dutifully fetches the content of the URI and places it into the browser. It’s effectively like the #includestatement in C and C++, or the import statement in Java or Python. What may not have occurred to you (and here comes the “magic” part), is that you can dynamicallyadd to, replace, and remove elements of the DOM tree that are child nodes of the HEADtag. Thus, you can add a SCRIPTnode and the browser includes the properties defined in the JavaScript (and technically, any methods as well). This is rather like adding a new method to a running Java program (and is rather slick indeed). Imagine that you could code in the srcattribute a URI that would do the following: 1. Return the data result set for the query 2. Return it in JSON (making it very easy to work with) 3. Specify a callback method as a receiver for the data You needn’t just imagine this, however; it’s what you’re going to accomplish in Listing 3-9. Dynamically Injecting a SCRIPT Tag into the HEAD This script tag has as its SRCattribute the URLof the remote service being invoked. Normally this is a JavaScript file, but in this case it’s JSON, which you can then reference directly by the callback associated with the data fetched from the URL. In summary, the design strategy goes like this: ❑ Add a new SCRIPTtag dynamically to the DOM tree of the browser, as a child of the HEADtag. ❑ Specify the URLfor the data directly. (Instead of pointing to a JavaScript library, the URLpoints to a Web service.) ❑ Add that the output should be JSON. ❑ Add the callback method (which must exist at the time of the dynamic execution of the SCRIPT directive). 103 Part I: An Introduction to RIAs The “callback” parameter is not a Web standard; and at the time of this writing, not a lot of Web services support it in their APIs. Before you mash up a given service, check what your target server does! Because the capability is so attractive and simple to implement, it is documented in the belief that it willbecome much more common. To explore the Yahoo Traffic result set, try making the call directly, by typing the following into the address window of a browser: http://api.local.yahoo.com/MapsService/V1/trafficData?appid=YahooDemo&location= 4%20Yawkey%20Way%20Boston,%20MA&output=json. The format of the result set can be discerned from the return to the query: 1 {“ResultSet”: 2 { 3 “LastUpdateDate”:”1152157153”, 4 “Result”: 5 [ 6 7 {“type”:”incident”, 8 “Title”:”Slow traffic, on ONEILL TUNL NB at ; BANKNORTH GARDEN”, 9 “Description”:”CONCERT:MADONNA;EXPECT DELAYS.”, 10 “Latitude”:”42.366000”, 11 “Longitude”:”-71.060300”, 12 “Direction”:”NB”, 13 “Severity”:2, 14 “ReportDate”:1152228600, 15 “UpdateDate”:1152142612, 16 “EndDate”:1152239400 17 } 18 ... followed by more results 19 ] 20 } 21 } The JSON contains several elements that will be useful in the chapter capstone. The Resultarray includes several incident reports containing latitude/longitude coordinates and an incident description. Next, Listing 3-9 uses this URI signature and adds a callback parameter to demonstrate the end-to-end application. Listing 3-9: DynamicScripting.html HTML 1 <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” ; “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”> 2 <html xmlns=”http://www.w3.org/1999/xhtml” xmlns:v=”urn:schemas-microsoft- com:vml”> 3 <head> 4 <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8”/> 5 <title>Yahoo!Traffic API Call. JSON. No Proxy</title> 6 <script type=”text/javascript” src=”../../scripts/jsr_class.js”></script> 7 <script type=”text/javascript”> 104

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.