Google Apps Script: How to Front Controller doGet()

Google Apps script standalone is a wonderful tool for the creation of cloud based web applications. But it has a limitation that many beginners to Google Apps consider a shortcoming in its implementation. This limitation is the that a web app can have only a two points of entry from a web browser.  These entries are the request types of GET and POST which are hard coded to the doGet() and doPost() functions of each web app.

In this short beginners tutorial you will see that Google has not limited you but actually helped you decide on using one of most common design patterns for web applications on the internet.


The Default


The doGet() function is the point at which all web apps land when called by a web browser via the URL provided in the Google Apps Script interface. While some may see this as a restriction it is actually very convenient. It allows a developer to make use of the Front Controller design pattern. Typically creating a web application requires configuring the server. In Apache Web Server use defaulting all requests to a single point of entry is done through the .htaccess file. On Microsoft IIS the same is done via the web.config file.  Configuration files are not a requirement when using Googles cloud based services because of the built-in defaults.

 

The URL

When you  create a new web app  a set of files will be created in that application by the Google system bot. In the main  script file there will be a  function  like this

/**
 * Serves HTML of the application for HTTP GET requests.
 * If folderId is provided as a URL parameter, the web app will list
 * the contents of that folder (if permissions allow). Otherwise
 * the web app will list the contents of the root folder.
 *
 * @param {Object} e event parameter that can contain information
 *     about any URL parameters provided.
 */
function doGet(e) {
  var template = HtmlService.createTemplateFromFile('Index');

  // Retrieve and process any URL parameters, as necessary.
  if (e.parameter.folderId) {
    template.folderId = e.parameter.folderId;
  } else {
    template.folderId = 'root';
  }

  // Build and return HTML in IFRAME sandbox mode.
  return template.evaluate()
      .setTitle('Web App Window Title')
      .setSandboxMode(HtmlService.SandboxMode.IFRAME);
}


 Once published the web app is accessible from a URL which looks like this:

https://script.google.com/macros/s/AKfycbx6vaIkoPx3qdI78zexn8OaJMoXy1uj3wrjoJ25YTXMdvDW1lY7/exec


Changing the URL slightly is needed to provide and action parameter. In this case we'll call it  "callback".

https://script.google.com/macros/s/AKfycbx6vaIkoPx3qdI78zexn8OaJMoXy1uj3wrjoJ25YTXMdvDW1lY7/exec?callback=formReg


The Front Controller


Normally a callback is not needed for a simple script where all the action takes place from within the doGet() function.  But building something more complex requires organization of functionality into parts that can be developed and maintained separately. This is where the idea of a front controller comes into being. The idea requires enforcing a rule that all page requests will be handled by a single method or function will  route  those request to other fuctions. The way we transform the simple doGet() function in to a router is by capturing a variable and reading its content to change actions. This do by a simple switch statement. Google scripts provides access to the URI as object.parameter.variablename.

function doGet(e) {

  
  var output = "";

  // process the URL which is sent as an object. The querystring  parameters can be captured and loaded like this
  var action = e.parameter.callback;
  
  // use the string in the callback parameter to determine an action
  switch (action)  {
        case "formReg":

            output = formReg(e);

            break;
            
        case "saveReg":

            output = saveReg(e);

            break;

        default:
            
            output = 'json output of default query from spreadsheet';
   } 

        return HtmlService.createHtmlOutput(ouput);
      
}


Callbacks

function formReg(e)
{

 return 'html user registration form';

}

function saveReg(e)
{

  return 'message from save operation';

}




Summary


One might ask why do this when creating another Web app is so easy? Well it's because I am lazy and would like to reuse functions in the web app only for different purposes. Low maintenance and better organization.

For me having only a single instance of GET or POST is not a problem but a tool. A tool for convenience in building a web application using a design pattern called the front controller.

Comments