http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/
Brief introduction
Asynchronous JavaScript and XML (AJAX) are key technologies that drive a new generation of Web sites (popular terminology for Web 2.0 sites). Ajax allows data retrieval in the background without disturbing the display and behavior of the WEB application. Using XMLHttpRequest
functions to get data, it is an API that allows client-side JavaScript to connect to a remote server via HTTP. Ajax is also a driving force for many mashups, which can make content collections from multiple locations a single WEB application.
However, because of browser restrictions, this method does not allow cross-domain communication. If you try to request data from a different domain, a security error occurs. These security errors can be avoided if you have control over the remote server where the data resides and each request goes to the same domain. But what is the use of WEB applications if you only stay on your own servers? What if you need to collect data from multiple third-party servers?
Understanding the same-origin policy limitations
The same-origin policy prevents scripts loaded from one domain from getting or manipulating document properties on another domain. That is, the domain of the requested URL must be the same as the domain of the current Web page. This means that the browser isolates content from different sources to prevent operations between them. This browser policy is very old and exists from Netscape Navigator version 2.0.
A relatively simple way to overcome this limitation is to have the Web page request data to the Web server it originates from, and have the Web server forward requests to a true third-party server like a proxy. Although the technology has been widely used, it is not scalable. Another way is to use frame features to create a new zone in the current Web page, and use the GET
request to get any third-party resources. However, when resources are obtained, the content in the framework is limited by the same-origin policy.
The best way to overcome this limitation is to insert a dynamic script element into a Web page that points to a service URL in another domain and gets the data in its own script. It starts executing when the script loads. This approach is possible because the same-origin policy does not prevent dynamic script insertions and considers the script to be loaded from the domain that provides the Web page. However, if the script tries to load a document from another domain, it will not succeed. Fortunately, this technique can be improved by adding JavaScript Object Notation (JSON).
JSON and JSONP
JSON is a lightweight data format for exchanging information between a browser and a server (as opposed to XML). Joson relies on JavaScript developers because it is a string representation of JavaScript objects. For example, suppose you have a ticker object with two attributes: symbol and price. This is how the ticker object is defined in JavaScript:
var ticker = {symbol: ' IBM ', price:91.42};
And this is how it's JSON represented:
{symbol: ' IBM ', price:91.42}
Find out more about JSON and use it as the data internal interchange format from resources. Listing 1 defines a JavaScript function that displays the share price of IBM when the function is called. (We don't have a detailed description of how to add this function to a Web page.)
Listing 1. Defining the Showprice function
function Showprice (data) { alert ("Symbol:" + Data.symbol + ", Price:" + Data.price);}
You can pass the JSON data as a parameter to invoke the function:
Showprice ({symbol: ' IBM ', price:91.42}); Alerts:Symbol:IBM, price:91.42
Now you are ready to include these two steps in the Web page, as shown in Listing 2.
Listing 2. Include Showprice functions and parameters in a Web page
<script type= "Text/javascript" >function showprice (data) { alert ("Symbol:" + Data.symbol + ", Price:" + DATA.PR ICE);} </script><script type= "Text/javascript" >showprice ({symbol: ' IBM ', price:91.42});</script>
After loading the page, you should see the warning shown in 1.
Figure 1. IBM Ticker
At this point, this article has shown how to call a JavaScript function with static JSON data as a parameter. However, by dynamically wrapping JSON data in function calls, you can call functions with Dynamic Data, which is a technique for dynamic JavaScript insertion. To see the effect, put the following line in a standalone JavaScript file named Ticker.js.
Showprice ({symbol: ' IBM ', price:91.42});
Now change the script in the Web page to make it the same as listing 3.
Listing 3. Dynamic JavaScript Insertion Code
<script type= "Text/javascript" >//this is we function to being called with JSON datafunction Showprice (data) { Ale RT ("Symbol:" + Data.symbol + ", Price:" + Data.price);} var url = "Ticker.js"; URL of the external script//this shows dynamic script Insertionvar script = document.createelement (' script '); script.se Tattribute (' src ', url);//Load the Scriptdocument.getelementsbytagname (' head ') [0].appendchild (script); </script>
In the example shown in Listing 3, the dynamically inserted JavaScript code is in the Ticker.js file, which invokes the real JSON data as a parameter showPrice()
function.
As mentioned earlier, the same-origin policy does not prevent the insertion of dynamic script elements into a document. That is, you can dynamically insert JavaScript from different domains, and these fields carry JSON data. This is actually a real JSONP (JSON with Padding): JSON data packaged in a function call. Note that in order to do this, the Web page must have an already defined callback function at the time of insertion, in our case showPrice()
.
However, so-called JSONP services (or Remote JSON service) is a WEB service with additional functionality that supports the packaging of returned JSON data in user-specific function calls. This method relies on the remote service that accepts the callback function name as the request parameter. The service then generates a call to the function, passing the JSON data as a parameter, inserting it into the Web page and starting execution when the client arrives.
Back to top of page
JQuery's JSONP support
Starting with version 1.2, JQuery has local support for the JSONP callback. If you specify a JSONP callback, you can load the JSON data that is located in the other domain, with the syntax for the callback: url?callback=?
.
JQuery automatically replaces the ? with the name of the build function to invoke. Listing 4 shows the code.
Listing 4. Using the JSONP callback
Jquery.getjson (url+ "&callback=", function (data) { alert ("Symbol:" + Data.symbol + ", Price:" + Data.price);});
To do this, jQuery attaches a global function to the window object that needs to be called when the script is inserted. In addition, JQuery optimizes non-cross-domain calls. If a request is made to the same domain, jQuery translates it into a normal Ajax request.
Example services with JSONP support
In the previous example, a static file (Ticker.js) was used to dynamically insert JavaScript into a Web page. Although the JSONP reply is returned, it does not allow you to define a callback function name in the URL. This is not a JSONP service. So how can you convert it into a real JSONP service? There are many ways to use it. Here we will show two examples using PHP and Java, respectively.
First, assume that your service has accepted a parameter named in the requested URL callback
. (The parameter name is not important, but both the client and the server must agree to the name). Also assume that the request sent to the service is this:
Http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=showPrice
In this case, the symbol
request parameter that represents the request for ticker symbol is the name of the callback
callback function for the WEB application. Using the code shown in Listing 5, the service can be invoked through JQuery's JSONP support.
Listing 5. Invoke Callback Service
Jquery.getjson ("http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=?", function (data) { alert (" Symbol: "+ Data.symbol +", Price: "+ Data.price);"});
Note that we use the name of the ?
callback function instead of the real function name. Because JQuery is replaced with the generated function name ?
. So you don't have to define showPrice()
a function like that.
Listing 6 shows a piece of code for the JSONP service implemented in PHP.
Listing 6. Code Snippets for JSONP services implemented in PHP
$jsonData = Getdataasjson ($_get[' symbol '); Echo $_get[' callback ']. ' ('. $jsonData. ‘);‘;/ /prints:jsonp1232617941775 ({"symbol": "IBM", "Price": "91.42"});
Listing 7 shows the Java™servlet method with the same functionality.
Listing 7. JSONP Services implemented with Java servlet
@Overrideprotected void Doget (HttpServletRequest req, HttpServletResponse resp) throws Servletexception, IOException {String jsondata = Getdataasjson (req.getparameter ("symbol")); String output = Req.getparameter ("callback") + "(" + Jsondata + ");"; Resp.setcontenttype ("Text/javascript"); PrintWriter out = Resp.getwriter (); out.println (output);//prints:jsonp1232617941775 ({"symbol": "IBM", "Price": "91.42 "});}
So what if you want to build a mashup, collect content from third-party servers and display them in a single Web page? The answer is simple: you must use a third-party JSONP service. There are many such services.
Ready-made JSONP services
Once you know how to use JSONP, you can start building applications and mashups using some off-the-shelf JSONP Web services. Below is the preparation for the next development project. (Tip: You can copy a specific URL and paste it into the browser's address bar to check the resulting JSONP response).
Digg API: Headline News from Digg:
Http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript&callback=?
Geonames API: Location information for postal code:
Http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?
Flickr API: The latest cat images from Flickr:
http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json& Jsoncallback=?
Yahoo! Local Search API: Find Pisa in the 10504 area of Zip:
http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query=pizza&zip=10504 &results=2&output=json&callback=?
Back to top of page
Important Notes
JSONP is a powerful technology for building mashups, but unfortunately it is not a panacea for all cross-domain communication needs. It has some drawbacks that must be carefully considered before submitting development resources. First, and most important, there is no error handling on the JSONP call. If the dynamic script insert is valid, the call is executed, and if it is not valid, the silence fails. There is no hint of failure. For example, you cannot catch a 404 error from the server, and you cannot cancel or restart the request. However, waiting for a period of time has not responded, do not have to ignore it. (The future JQuery version may have the feature to terminate the JSONP request.)
Another major drawback of JSONP is the danger of being used by untrusted services. Because the JSONP service returns a JSON response packaged in a function call, the function call is executed by the browser, which makes the host WEB application more susceptible to various types of attacks. If you intend to use the JSONP service, it is important to understand the threats it can pose. (See Resources for more information).
Back to top of page
Conclusion
In the first article in the series, we explained how to quickly build powerful mashups using JSONP and JQuery. Key topics include:
- Browser-origin policy limitations and workarounds
- As an effective cross-domain communication technology, JSONP can bypass the current browser's same-Origin policy restrictions
- JSONP enables WEB application developers to quickly build mashups
- Example JSONP service and its use: Ticker service
The next article in this series introduces the Yahoo! Query Language (YQL), a single endpoint JSONP service that allows you to query, filter, and merge data across the WEB. Finally, a mashup application is built using YQL and jQuery.
Use JSONP for cross-domain communication, part 1th: Quickly build powerful mashups with JSONP and jQuery