JSONP and JSON and Google Apps Script webapps

If you use any of my webapps that return json data, there will be an option to return jsonp instead. Here's a quick summary of what it's all about.

Same-Origin security policy.

Since JSON is really just JavaScript, it could be possible to insert malicious code disguised as data. This was especially true when eval() was commonly used to parse JSON strings into JavaScript objects. Nowadays of course we use JSON.parse(), but the same-origin security policy which prohibits Ajax requests from client JavaScript to a different domain than the one it is running on is still in place. More recently, CORS (cross origin resource sharing) has been introduced, which is a way to safely enable sharing across domains. The benefit is that can enable all Http operations (POST, PUT, GET etc..) whereas the JSONP approach (which I'll explain shortly), only permits GET operations. 

Google Apps Script Webapps

All this is relevant for GAS because it will typically be running on the google.com domain, whereas you will calling from some other domain of your own. At this time, you cannot setup CORS for Google Apps Script , so for now we have to continue to use JSONP. You can take a look at this blog post for more about what works and what doesn't work on GAS. Note that the same-origin loophole I refer to in this post has since been plugged.

What is JSONP ?

JSONP (I think it stands for JSON with padding), is a kind of hack to get round the same-origin policy. Javascript within <SCRIPT> tags is allowed to cross domains, so JSONP exploits that by passing JSON as if it was calling a JavaScript function, with the JSON data as the argument. 

so this JSON
{"foo":"bar"}

becomes this JSONP

myFunction ({"foo":"bar"});

Mime Type

The Mime Type describes what should be done with a set of data. That means that if you are returning JSON data you need to set a different Mime Type than the one needed for JSONP. In Google Apps Script terms, these are 

ContentService.MimeType.JAVASCRIPT (for JSONP)
ContentService.MimeType.JSON (for JSON)

Specifying JSONP

My webapps all provide a standard way to ask for JSONP rather than JSON. If you specify &callback=somefunction on the webapp url, then you'll get JSONP, otherwise you'll get JSON. Note that only GET provides JSONP. If you want to do POST or some other operation, then you need to make the requests from a server - or via a server proxy. But that's a post for another day. 

Example

Here's a typical doGet() function, supporting both JSONP and JSON

function doGet(e) {

  // do whatever this webapp is for
  var result = doSomething(e); 
  // prepare the result
  var s = JSON.stringify(result);
  // publish result
  return ContentService
    .createTextOutput(result.params.callback ? result.params.callback + "(" + s + ")" : s )
    .setMimeType(result.params.callback ? ContentService.MimeType.JAVASCRIPT : ContentService.MimeType.JSON);
}

For more like this see Google Apps Scripts snippets

For help and more information join our forumfollow the blogfollow me on twitter

You want to learn Google Apps Script?

Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly

If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.



Comments