English | Site Directory

Introduction to makeRequest

Arne Roomann-Kurrik, OpenSocial Team
April 2008

Sometimes gadgets and OpenSocial applications need to work with data located on remote servers. This functionality is very useful, but is not as straightforward as making a simple AJAX request. Fortunately, the gadgets API provides a function called makeRequest that allows you to fetch data from and send data to remote servers.

This article provides an introduction to the various types of requests that can be sent using makeRequest. Using this information, you will be able to make your application send and retrieve data outside of the bounds of the current container.

Contents

  1. About this article
  2. What is makeRequest?
  3. Programming with makeRequest
    1. Calling makeRequest
    2. Optional parameters
    3. Response structure
  4. Content types
    1. Text requests
    2. DOM requests
    3. JSON requests
    4. Feed requests
  5. Methods
    1. GET
    2. POST
  6. Working with request caching
  7. To learn more

About this article

This article details the use of the makeRequest function in the gadgets API. It assumes that you have beginner to intermediate knowledge of the gadgets and OpenSocial APIs, and that you have written at least one gadget.

If you do not meet these requirements, you may wish to take a look at these additional resources before continuing:

Because this is an introductory article, the topics of authentication and signed calls fall outside of the scope of discussion and will not be covered here. Future articles will explain these functions in detail.

What is makeRequest?

Most sophisticated OpenSocial applications will need to send and receive data from third party servers. This functionality is particularly important for existing websites or social applications that want to make their site features available in OpenSocial containers. However, browser security models prevent gadget JavaScript from making cross-domain requests, meaning that developers cannot use standard AJAX libraries to fetch content from other sites.

Fortunately, the gadgets specification describes the gadgets.io.makeRequest function which provides support for gadgets to GET data from and POST data to third party sites. As you will see in this article, makeRequest is very powerful. It can:

  • Generate HTTP requests using both GET and POST methods
  • Return the server response in a variety of formats
  • Transmit critical OpenSocial information to the remote server in a verifiable manner

Programming with makeRequest

If you are experienced using the gadgets API, calling makeRequest will be fairly straightforward. However, there are many parameters that you may pass to makeRequest that affect the function's behavior. This section will cover most of the different types of requests that you can make.

Calling makeRequest

The makeRequest signature looks like this:

gadgets.io.makeRequest(url, callback, opt_params)

There are three arguments to this function:

  • url - A string containing the URL of the page to request.
  • callback - A reference to a function that will be called when the request completes.
  • opt_params - A JavaScript object containing additional parameters for the call. This parameter is optional. More detailed information about opt_params can be found in the next section.

Optional parameters

The opt_params argument to makeRequest should be an object that contains one or more gadgets.io.RequestParameters fields as keys. These keys are:

gadgets.io.RequestParameters.AUTHORIZATION

The type of authentication to use in the request. Can be one of:

  • gadgets.io.AuthorizationType.NONE
  • gadgets.io.AuthorizationType.SIGNED
  • gadgets.io.AuthorizationType.AUTHENTICATED

Note: gadgets.io.AuthorizationType.AUTHENTICATED is listed in the gadgets specification, but the specification does not define which format this authenticated request must be in. This feature is therefore not currently implemented on any container.

gadgets.io.RequestParameters.CONTENT_TYPE

The type of content you want to treat the response as. Can be one of:

  • gadgets.io.ContentType.DOM
  • gadgets.io.ContentType.FEED
  • gadgets.io.ContentType.JSON
  • gadgets.io.ContentType.TEXT

gadgets.io.RequestParameters.GET_SUMMARIES

If the content is a feed, whether to retrieve the summary fields for the feed. Can be either true or false.

gadgets.io.RequestParameters.HEADERS

Headers to pass along in the request. Should be an object containing key/value pairs corresponding to the headers to be sent to the server. For example:

{
  "Content-Type" : "application/atom+xml",
  "Accept-Language": "en-us"
}

gadgets.io.RequestParameters.METHOD

The HTTP method of the request. Can be one of:

  • gadgets.io.MethodType.GET
  • gadgets.io.MethodType.POST

gadgets.io.RequestParameters.NUM_ENTRIES

If the content is a feed, the number of entries from the feed to retrieve. Should be specified as a number.

gadgets.io.RequestParameters.POST_DATA

If the method is a POST, the raw POST data to pass to the other server. Should be specified as a string.

Example usage

For example, to generate an opt_params object to set the content-type of the request to JSON, you can use the following code:

var params = {};
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
gadgets.io.makeRequest("http://example.com", function() {}, params);

This would make a request to example.com and attempt to treat the returned content as a JSON encoded string. Note that the callback specified is an empty function— you would want to specify your own function to handle the content returned in the response.

Response structure

When you receive a response from a makeRequest call, you are returned a JavaScript object with the following structure:

{
  data : <parsed data, if applicable>,
  errors : <any errors that occurred>,
  text : <raw text of the response>
}

The returned object has three properties:

  1. data - This will contain a different type of data depending on the type of request that was made. See the sections about the different request types for information about what to expect in this field.
  2. errors - This will contain an array of any errors that occurred when making this request. For example, if a 500 error occurred in the request:
    [ "500 error" ]
  3. text - This will return the unparsed text of the response. For certain types of requests, this will be the only field populated.

This object will be supplied as the only argument to the callback function specified when the request was made.

Content types

The value you specify in the ContentType parameter to makeRequest determines the sort of content you get back in the response. This section covers the four available content types.

Text requests

Text requests are the default content type for makeRequest calls. Text content type requests do not make any attempt to parse the content of the response.

You make a text content request like this:

function request() {  
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] =  
      gadgets.io.ContentType.TEXT;
  var url = "http://example.com";
  gadgets.io.makeRequest(url, response, params);
};

If the request is successful, the response will come back with both the text and data fields populated with the raw response text.

function response(obj) {
  /** obj.text contains the text of the page that was requested **/
};

If the content at http://example.com is the following:

<html>
  <body>
    <h1>Hello!</h1>
  </body>
</html>

Then obj.text and obj.data fields will have the following value:

<html>\n  <body>\n    <h1>Hello!</h1>\n  </body>\n</html>

DOM requests

DOM requests attempt to retrieve a remote web page and parse it into a DOM document. You can use standard DOM manipulation/query methods on the resulting document to work with nodes in the response.

You can make a DOM request like this:

function request() {  
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
  var url = "http://example.com";
  gadgets.io.makeRequest(url, response, params);
};

If the request is successful, the response will come back with the raw XML in the text field and the DOM object in the data field.

function response(obj) {
  /** obj.data contains a DOM element corresponding to the requested page **/
  output(obj.data);
};

If the content at http://example.com is the following document:

<?xml version="1.0"?>
<root>
  <title>Hello!</title>
</root>
</pre>

The obj.text property will have the following value:

<?xml version=\"1.0\"?>\n<root>\n  <title>Hello!</title>\n</root>

The obj.data property will have the following general structure (many of the attributes available on the returned XML document have been left out for clarity).

{
  ...

  nodeName : "#document",
  childNodes : [
    {
      nodeName : "root",
      childNodes : [
        "\n",
        {
          nodeName : "title",
          childNodes : [ "Hello!" ]
        },
        "\n"
      ]
    }
  ],

  ...
}

JSON requests

JSON requests attempt to parse the response as a JSON encoded object. You can specify a JSON content type like this:

function request() {  
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://example.com";
  gadgets.io.makeRequest(url, response, params);
};

If the request is successful, then the response will come back with the raw JSON string in the text field and the parsed JavaScript object in the data field:

function response(obj) {
  /** obj.data contains an object corresponding with the JSON-encoded response **/
  output(obj.data);
};

If the content at http://example.com is the following:

{ "Message" : "Hello!", "Test" : [ "Item 1", "Item 2" ] }

The obj.text property will have the following value:

{ \"Message\" : \"Hello!\", \"Test\" : [ \"Item 1\", \"Item 2\" ] }

The obj.data property will have the following structure:

{
  Message : "Hello!",
  Test : [
    "Item 1",
    "Item 2"
  ]
}

Feed requests

Feed requests attempt to parse an ATOM or RSS xml feed and return the response as a JSON encoded object. You can specify a feed content type like this:

function request() {  
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
  var url = "http://example.com";
  gadgets.io.makeRequest(url, response, params);
};

If the request is successful, then the response will come back with the raw XML text in the text field and the parsed JavaScript object in the data field:

function response(obj) {
  /** obj.data contains an object corresponding with the JSON-encoded response **/
  output(obj.data);
};

If the content at http://example.com is the following:

<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Example Feed</title>
  <subtitle>A subtitle.</subtitle>
  <link href="http://example.com/feed/" rel="self"/>
  <link href="http://example.com/"/>
  <updated>2008-03-12T18:30:02Z</updated>
  <author>
    <name>Sample Testington</name>
    <email>stestington@example.com</email>
  </author>
  <id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>
  <entry>
    <title>You can request feeds with makeRequest</title>
    <link href="http://example.com/entry12345"/>
    <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
    <updated>2008-03-12T18:30:02Z</updated>
    <summary>Some text.</summary>
  </entry>
</feed>

The obj.text property will be set to the text of the xml document. The obj.data property will have the following structure:

{
  URL : "http://example.com",
  Title : "Example Feed",
  Description : "A subtitle.",
  Link : "http://example.com/feed/",
  Author : "Sample Testington",
  Entry : [
    {
      Title : "You can request feeds with makeRequest",
      Link : "http://example.com/entry12345",
      Summary : "Some text."
    }
}

Methods

makeRequest also allows you to choose between the HTTP GET and POST methods.

GET

Typically, you use GET to retrieve information from a website. GET is the default mode for makeRequest, but you can explicitly make a GET request with the following code:

function makeRequest(url) {
  var params = {};
  params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
  gadgets.io.makeRequest(url, response, params);
};

function response(obj) {
  alert(obj.text);
};

makeRequest("http://example.com");

To pass parameters to your server in the GET request, just append them to the querystring when you make the request:

makeRequest("http://example.com?param1=12345¶m2=hello");

POST

POST requests are typically used to pass data to a server with the intent to modify or delete records. You can pass larger amounts of data in a POST request than you would be normally able to with a GET request.

A POST can be performed using the following code:

function makeRequest(url, postdata) {
  var params = {};
  postdata = gadgets.io.encodeValues(postdata);
  params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
  params[gadgets.io.RequestParameters.POST_DATA]= postdata;
  gadgets.io.makeRequest(url, response, params);
};

function response(obj) {
  output(obj.text);
};

var data = {
  data1 : "test",
  data2 : 123456
};
makeRequest("http://example.com", data);

In addition to specifying the METHOD in the opt_params for this request, you should specify a parameter under the key gadgets.io.RequestParameters.POST_DATA. The default encoding for POST is application/x-www-form-urlencoded which means that the value for the POST_DATA parameter should be a series of urlencoded key/value pairs joined with ampersands (&). To make converting objects of data into this format easier, the function gadgets.io.encodeValues is provided. encodeValues accepts a JavaScript object and returns an encoded string suitable for the POST_DATA parameter.

For example, running:

var data = {
  data1 : "test",
  data2 : 123456
};

gadgets.io.encodeValues(data);

produces the string:

data1=test&data2=123456

This string can be passed directly as the value for gadgets.io.RequestParameters.POST_DATA.

Working with request caching

Depending on the container you are developing for, makeRequest calls may be cached. This is great for reducing the load that your servers have to be able to handle, since OpenSocial applications may have millions of users, each requesting data from your server. However, this caching of makeRequest calls can wind up displaying old data to users if the content returned by your server changes often.

If you expect the content at the URL you are fetching to change frequently, you may want to work around the automatic caching with a more finely grained method.

The following code defines a function named makeCachedRequest. This function takes the same parameters as makeRequest, but accepts one additional parameter named refreshInterval, which should be specified as the number of seconds that should elapse before the makeRequest call requests content from your servers again. For example, specifying 10 will mean that the container would only query the supplied URL once every 10 seconds, no matter how many people are using your application. Specifying 0 will query your server each time the function is called, effectively bypassing the cached version.

This function gives you more control over how frequently your content is cached. You can tweak the refreshInterval parameter to optimize request caching for your application's specific request patterns.

function makeCachedRequest(url, callback, params, refreshInterval) {
  var ts = new Date().getTime();
  var sep = "?";
  if (refreshInterval && refreshInterval > 0) {
    ts = Math.floor(ts / (refreshInterval * 1000));
  }
  if (url.indexOf("?") > -1) {
    sep = "&";
  }
  url = [ url, sep, "nocache=", ts ].join("");
  gadgets.io.makeRequest(url, response, params);
};

The way this method works is that it appends a timestamp to each request URL before actually requesting the data, meaning that each millisecond that passes results in a new unique URL that does not exist in the makeRequest cache. Specifying refreshInterval divides this timestamp by the number of seconds between requests so that a unique URL is generated only once every X seconds, where X is the value of refreshInterval.

You can call makeCachedRequest in places where you would use gadgets.io.makeRequest— just change the function name and put the extra parameter at the end of the arguments you would normally use.

To learn more

This article should have given you a good understanding of the different ways to use makeRequest. For more information about some of the topics discussed here, check the following resources: