The JSONP Utility is a specialized API for communicating with web
services that provide JSON responses wrapped in a callback
function. A typical JSONP request URL might look like
"http://example.com/service.php?callback=handleData" and
receive a text response in the form of
handleData({"records":[....]});
.
The nature of YUI 3's sandbox model complicates JSONP transactions
because JSONP relies on a global access point to process the
response, but YUI 3 implementation code is typically wrapped in a
use(...)
callback and is therefore not globally
accessible. The JSONP module provides a proxy system for
channeling JSONP responses back into your YUI instance sandbox.
Security Note: JSONP is an inherently unsecure communication method, since it involves the transfer of unvalidated JavaScript. It is by convention alone that the format is associated with JSON, but in reality, the response can include any arbitrary JavaScript, potentially opening your page to attack. Be cautious about which services you communicate with via JSONP. For safe JSON communication, use the JSON module in conjunction with the IO module wherever possible.
To include the source files for JSONP and its dependencies, first load the YUI seed file if you haven't already loaded it.
<script src="http://yui.yahooapis.com/3.18.1/build/yui/yui-min.js"></script>
Next, create a new YUI instance for your application and populate it with the
modules you need by specifying them as arguments to the YUI().use()
method.
YUI will automatically load any dependencies required by the modules you
specify.
<script> // Create a new YUI instance and populate it with the required modules. YUI().use('jsonp', 'jsonp-url', function (Y) { // JSONP is available and ready for use. Add implementation // code here. }); </script>
For more information on creating YUI instances and on the
use()
method, see the
documentation for the YUI Global Object.
Y.jsonp
method
The JSONP utility provides the Y.jsonp(url, callback)
method
for single transactions as well as a Y.JSONPRequest
class to
manage reusable connections.
The first argument to either the Y.jsonp
method or the
Y.JSONPRequest
constructor is the URL of the JSONP service,
and the second is a callback function or configuration
object that contains a callback function. When the service responds
with the data, the callback will be executed with the response data as the
first parameter.
In place of the JSONP callback name in the URL, include the string "{callback}". This placeholder will be used for a proxy function that will route the data to your callback.
// instead of service.php?callback=handleJSONP var url = "http://example.com/service.php?callback={callback}"; function handleJSONP(response) { // response is a JavaScript object. No parsing necessary Y.one("#output").setHTML(response.outputHTML); } Y.jsonp(url, handleJSONP); // or var service = new Y.JSONPRequest(url, handleJSONP); service.send();
Y.jsonp(url, callback)
will dispatch the request immediately.
JSONPRequest instances will dispatch the request each time their
send()
method is called.
// request sent immediately Y.jsonp(url, handleJSONP); // No request sent var service = new Y.JSONPRequest(url, handleJSONP); // ...until now service.send(); // ...and now again service.send();
Y.jsonp(url, callback)
is a convenience wrapper to instantiate
a JSONPRequest instance and call its send()
method.
This will generate a request to a URL like this one (note that the
{callback}
placeholder has been replaced with a dynamically
generated callback name):
http://example.com/service.php?callback=YUI.Env.JSONP.yui_3_3_0_1_1294184187597423
The server will then be expected to respond with a JavaScript value wrapped in a call to that function, like this:
YUI.Env.JSONP.yui_3_3_0_1_1294184187597423({"foo":"bar"});
The second argument to either Y.jsonp
or the
Y.JSONPRequest
constructor can be a success callback function
or for more control, it can be a configuration object. The supported keys
of this object are:
Property | Description |
---|---|
timeout |
This value, defined as milliseconds, is a time threshold for
the transaction (e.g., { timeout: 2000 } ). When
this limit is reached, the transaction's
on.timeout callback will be executed if
supplied.
|
context |
Defines what will be "this " in the
callbacks. If undefined, the default will be the JSONPRequest
instance.
|
args | An array of additional arguments that will be passed to the callbacks as second, third, and so on arguments. |
on |
Required. This object defines the
callbacks to be used for the transaction. At least an
|
format |
Preprocessor function to stitch together the supplied URL
(first argument), the proxy function name (internally
generated), and any additional arguments passed to
send() . See Customizing the
JSONP URL for more detail.
|
This is an example of a configuration object, with a set of properties defined.
var url = "http://example.com/service.php?callback={callback}", service = new Y.JSONPRequest(url, { on: { success: MyApp.handleJSONP, timeout: MyApp.handleTimeout }, context: MyApp timeout: 3000, // 3 second timeout args: [new Date(), 100] // e.g. handleJSONP(data, date, number) }); service.send(); // or Y.jsonp(url, { on: { success: MyApp.handleJSONP, timeout: MyApp.handleTimeout }, context: MyApp timeout: 3000, // 3 second timeout args: [new Date(), 100] // e.g. handleJSONP(data, date, number) });
An extension for the jsonp
module is the
jsonp-url
module which provides a few additional features.
Y.MyApp.handleJSONP
), you can include the
name in the URL and omit the second parameter entirely.
Y.MyApp.handleJSONP = function (data) { Y.one("#output").setHTML(data.outputHTML); }; Y.jsonp("http://example.com/service.php?callback=Y.MyApp.handleJSONP"); // or Y.jsonp("http://example.com/service.php", { context: Y.MyApp, on: { success: Y.MyApp.handleJSONP, failure: Y.MyApp.handleFailure } });
The default URL formatter simply replaces the "{callback}"
placehold with the name of the generated proxy function. If you want to
customize the URL generation process, you can provide a format
function in the configuration. The function will receive the configured
URL (with "{callback}" placeholder), the string name of the proxy
function, and any additional arguments that were passed to
send()
.
// Our custom formatter will expect a URL with an additional placeholder for // username that must be supplied in send("bill"); // e.g. http://example.com/bill/json?fn=YUI.Env.JSONP._12345 function prepareJSONPUrl(url, proxy, username) { // URI-escape the content before it is inserted into the URL. var name = encodeURIComponent(username) || "user"; return Y.Lang.sub(url, { callback: proxy, name: name }); } var url = "http://example.com/{name}/json?fn={callback}"; var service = new Y.JSONPRequest(url, { format: prepareJSONPUrl, on: { success: handleJSONP } }); service.send("apipkin"); service.send("tivac"); service.send("razass");
Anytime unsafe content is injected into the URL context, it should be URI-encoded. This defends against HTTP Parameter Pollution.
XMLHttpRequest
to fetch it's data.