What is CORS

In summary it’s a way of securely enabling a client side app to exchange data with a server that is not in the same domain – which is of course against cross domain security policies, but yet is something we all need to do, all the time. I’ve dealt with that in a number of different ways in other articles on this site – for example Proxy jsonp,  JSONP and JSON and Google Apps Script webapps,  Light JSONP implementation, and even in VBA apps such as Rest to Excel library.
Essentially though each one was varying degrees of hackery that always left me with something I couldn’t quite do.  The Apps Script environment does not yet support CORS, but increasingly other APIS do. For this example we’ll look at the GitHub API, since for the Enhanced Github gadget I needed to POST to the Github Markdown Api, which I couldn’t do from a client app. One solution would have been to create an apps script webapp, and proxy the markdown conversation to that (in fact I do have one of those that I may write up when I get round to it), but I thought I’d look into CORS again  (here’s the Wikipedia article) since GitHub supports it.
The last time I looked at CORS I came away with a headache and decided to just continue to resort to hackery. Here’s the flowchart for the apache/tomcat cors implementation.
However, as it turns out, I read this article, found some code on html5rocks, and realized that nowadays most of the preflight conversation and header handling is done by the browser, so it’s actually a piece of cake (the client part anyway). Checking into the Mozilla Developer network I see most browsers support it too.
Here’s an implementation you can use on most clients, including some of the older IEs.
You’ll find it on GitHub or below
// thanks to http://enable-cors.org/ for info on cors/html5

  
    /**
     *do a cors request
     *@param {function} callback the load callback
     *@param {function} errorCallback the error callback
     *@param {string}  url the url
     *@param {string} method the method (default GET)
     *@param {*} payload the optional payload
     *@return {object} the response
     */
    function corsRequest (callback, errorCallback,url , method, payload ) {
    
      // get the appropriate xhr
      var xhr = getXhr();
      if (!xhr) throw 'cant do cors with this browser';
      
      // now we can go
      xhr.open (method || "GET" , url , true);
      
      // set up callbacks
      xhr.onload = function (response) {
        // meed to catch this since it doesnt actually catch http errors
        if (response.target.status <200 || response.target.status >=300) {
          errorCallback (response.target);
        }
        else {
          callback (response.target);
        }
          
      }
      xhr.onerror = function (response) {
        errorCallback (response.target);
      }
      
      // execute
      return xhr.send (payload);
      
       /**
 * get the correct xhr object for the browser being used
 * @return {XDomainRequest|XMLHttpReQuest} the xhr
 */
     function getXhr () {
       
       // likely to be this, unless its IE
       var xhr = new XMLHttpRequest();
       return isDefined(xhr.withCredentials) ? 
         xhr : (isDefined(XDomainRequest) ? new XDomainRequest () : undefined);
     }
     
     function isDefined (ob) {
       return typeof ob !== typeof undefined;
     }
     
    }

How to use it

Here’s how I call the Github markdown API to ask it to render some markdown into html.
corsRequest (
    function (response) {                // the success callback
        // a success - dosomething with reponse.responseText
    },
    function (response) {                // the failure callback
       // a failure - do something with response.status and response.statusText
    },
    "https://api.github.com/markdown",   // the url you want to call
    "POST",                              // the HTTP method
    JSON.stringify({"text": content})    // the payload
  );

See more like this in Enhanced Github gadget.

More Google apps scripts snippets here