Remote Data Requests (v0.9)

Sometimes OpenSocial gadgets need to work with data located on remote servers, but cannot make AJAX requests due to cross-browser limitations. Fortunately, the OpenSocial APIs provide functions to send HTTP requests to remote servers.

Your OpenSocial applications are able to:

  • Securely transmit unique identifiers for the owner and viewer using*request signing*.
  • Make HTTP requests from a gadget to a remote server using*osapi.http*.
  • Request social information to be sent from the container to a server using*Data Pipelining*.
  • Render a web page from a server as a gadget view using*Proxied Content*.

Request Signing

When sending data from a gadget to a remote server that contains important information such as user ID numbers and profile data, it is important for the remote server to know that the data request has not been modified in any way by a malicious party.

OpenSocial uses request signing to protect against such tampering. To be secure, your application must only transmit the value of the current owner or viewer's OpenSocial ID numbers using signed requests. If you are not familiar with the concept of request signing, please read the Introduction To Signed Requests article.

JavaScript HTTP requests

You can generate HTTP requests from within gadgets to fetch remote data. Which method you use to make these requests depends on the version of OpenSocial you are developing for:

osapi.http (OpenSocial versions 0.9+)

OpenSocial 0.9 introduced the simpler osapi.http JavaScript library. An example of making a signed osapi.http request to fetch JSON data is below:

osapi.http.get({
    'href' : 'http://www.example.com',
    'format' : 'json',
    'authz' : 'signed'
}).execute(callback);

Please see the osapi.http documentation for more examples.

gadgets.io.makeRequest (OpenSocial versions 0.7, 0.8)

Using makeRequest has been deprecated, but is still widely available on many containers. An example of a signed makeRequest call to fetch JSON data is below:

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

Please see the gadgets.io.makeRequest documentation for more examples.

Preloading data

Applications which need to access remote content for each render can improve their performance dramatically by preloading this data.

A preload is executed at the same time that the gadget is rendered, so it effectively saves a whole round trip from the user of your application to the container where your app is running. Preloads are also fetched when the app is initially fetched, so you don't have to wait for an {{onload} event to fire before requesting remote data.

If you have a request that looks like the following:

osapi.http.get({'href' : 'http://www.example.com'}).execute(callback)

You can preload the content at {{http://www.example.com} by adding a {{<Preload>} tag to your {{<ModulePrefs>} section:

<ModulePrefs title="Preloads">
 <Require feature="opensocial-0.9" />
 <Preload href="http://www.example.com" />
</ModulePrefs>

When your application executes the {{osapi.http} call, this content will be returned instantly, without needing to hit your server again. Preloaded requests can also be signed if you need, by adding the optional {{authz} attribute to your {{Preload} section:

<ModulePrefs title="Preloads">
  <Require feature="opensocial-0.9" />
  <Preload href="http://www.example.com" authz="signed" />
</ModulePrefs>

There are a few more optimizations you can use to make preloads work even better:

  1. Turn off sending the viewer in signed requests. If you don't need the VIEWER ID for your signed request, disable it by adding {{sign_viewer="false"} to your {{<Preload>} tag. This will allow the container to cache your request for a lot more requests. This is a critical improvement for profile pages!
  2. You may disable sending the OWNER ID in signed preloads by adding {{sign_owner="false"}.
  3. Use multiple {{<Preload>} tags if you have more than one request. You're not limited to one {{<Preload>} tag, so preload whatever you can.
  4. Restrict preloads to the correct view. If you only use a certain request in a specific view, restrict the preload to that view by adding a views attribute to your {{<Preload>} tag. For example, to restrict a preload to the canvas view, add {{views="canvas"} to your {{<Preload>} tag. You can also specify multiple comma separated views, like {{views="canvas,profile"}.

The following example makes three preloaded requests:

  1. The request to {{http://www.example.com/owner_data.json} is signed with only the owner's ID number.
  2. The request to {{http://www.example.com/global_view_data.json} is a regular HTTP GET request and preloaded for all views.
  3. The request to {{http://www.example.com/profile_view_data.json} is a regular HTTP GET request, and is only made for {{profile} and {{home} views.
<ModulePrefs title="Preloads">
  <Require feature="opensocial-0.9" />
  <Require feature="views" />
  <Preload href="http://www.example.com/owner_data.json" authz="signed" sign_viewer="false" />
  <Preload href="http://www.example.com/global_view_data.json" />
  <Preload href="http://www.example.com/profile_view_data.json" views="profile,home" />
</ModulePrefs>

Please see the Gadgets XML Reference for more information.

Proxied Content

Proxied content lets you use the HTML markup from a remote web page and use it as the content for one of your application views. This lets you do most of your gadget development on a remote server, instead of in a gadget XML file.

The following example uses the content at {{http://www.example.com} for the {{canvas} view:

<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs title="Proxied Content">
    <Require feature="opensocial-0.9" />
  </ModulePrefs>
  <Content href="http://www.example.com" view="canvas">
  </Content>
</Module>

For more information, see the /wiki/spaces/a/pages/527072 documentation.

Data Pipelining

Data Pipelining defines a way to declare social and remote data requests in gadget XML markup. Using Data Pipelining, an application author can:

  • Retrieve an HTTP URL and access the response in a gadget, through JavaScript or OpenSocial templates.
  • Send social data to a remote server and use the server's response as a gadget view.

Retrieving data using Data Pipelining

Gadget authors can use Proxied Content to specify data to be fetched when the gadget is rendered using the {{os:HttpRequest} tag. The remote content is made available in the current gadget's OpenSocial data context.

The following example demonstrates fetching text content from {{www.example.com} and accessing it from both JavaScript and OpenSocial templates:

<?xml version="1.0" encoding="UTF-8"?>
<Module>
  <ModulePrefs title="Data Pipelining - httprequest">
    <Require feature="opensocial-0.9" />
    <Require feature="opensocial-data"/>
    <Require feature="opensocial-templates" />
  </ModulePrefs>
  <Content type="html">
  <![CDATA[ 
    <script type="text/os-data" 
            xmlns:os="http://ns.opensocial.org/2008/markup" >
       <os:HttpRequest key="exampledata" href="http://www.example.com" format="text"/>
    </script>
    <script type="text/javascript">
      var exampledata = opensocial.data.getDataContext().getDataSet('exampledata');
      alert('Got: ' + exampledata.content);
    </script>
    <script type="text/os-template" 
            xmlns:os="http://ns.opensocial.org/2008/markup" 
            xmlns:osx="http://ns.opensocial.org/2009/extensions" 
            require="exampledata">
      Got ${exampledata.content}
    </script>
  ]]>
  </Content>
</Module>

For more information, see the /wiki/spaces/a/pages/526835 documentation.

Sending data using Data Pipelining and Proxied Content

While a:request signing can be used to pass an owner or viewer's ID to a remote server using a:JavaScript HTTP requests, your application may wish to transmit additional information, such as friends lists or profile data. Using Proxied Content and Data Pipelining enables this functionality. The following gadget makes a Data Pipelining call to {{http://www.example.com}, sending the current viewer and viewer's friends:

<?xml version="1.0" encoding="UTF-8"?>
<Module xmlns:os="http://ns.opensocial.org/2008/markup">
  <ModulePrefs title="Data Pipelining and Proxied Content">
    <Require feature="opensocial-0.9" />
    <Require feature="opensocial-data"/>
  </ModulePrefs>
  <Content href="http://www.example.com" authz="signed" sign_viewer="true">
    <os:PeopleRequest key="viewer_friends" userId="@viewer" groupId="@friends" count="2"/>
    <os:ViewerRequest key="viewer" />
  </Content>
</Module>

The server-side code at {{http://www.example.com} gets a signed POST request, with the following JSON-encoded POST body:

[
  { 
    "id" : "viewer",
    "data" : {
      "id" : "1111111111",
      "isViewer" : true,
      "name" : {
        "familyName" : "Testington",
        "givenName" : "Alice"
      },
      "thumbnailUrl" : "http://www.someexamplesocialnetwork.com/img/1111111111.png",
      "isOwner" : true 
    }
  },
  { 
    "id" : "viewer_friends",
    "data" : {
      "startIndex" : 0,
      "totalResults" : 65,
      "list" : [
        { 
          "id" : "2222222222",
          "isViewer" : false,
          "name" : {
            "familyName" : "Testington",
            "givenName" : "Bob"
          },
          "thumbnailUrl" : "http://www.someexamplesocialnetwork.com/img/2222222222.png",
          "isOwner" : false 
        },
        { 
          "id" : "3333333333",
          "isViewer" : false,
          "name" : {
            "familyName" : "Testington",
            "givenName" : "Claire"
          },
          "thumbnailUrl" : "http://www.someexamplesocialnetwork.com/img/3333333333.png",
          "isOwner" : false 
        }
      ]
    }
  }
]

By processing the POST body, the server can render a viewer-specific application view containing social data.

For more information, see the /wiki/spaces/a/pages/526835 documentation.