docs: function processWebRequest(routeInfo, callbacks) {
      var appName = routeInfo.appName;
      var serverOnly = !!routeInfo.query.server;
      var page = injector.loadModule('app/' + appName + '/pages/' + routeInfo.name + '.page');
  
      // get the callbacks
      var serverPreprocessing = callbacks.serverPreprocessing || function () { return false; };
      var appAddToModel = callbacks.addToModel || function () {};
      var pageCacheService = callbacks.pageCacheService || defaultPageCache;
      var initialModel, cacheKey;
  
      return getInitialModel(routeInfo, page)
          .then(function (model) {
              initialModel = model || {};
  
              // if the server pre-processing returns true, then return without doing anything
              // this is because the pre-processor sent a reply to the user already
              if (serverPreprocessing(routeInfo, page, model)) {
                  return true;
              }
  
              //TODO: may be weird edge cases with this. need to test more to ensure performance and uniqueness
              // but note that we have an hour default timeout for the redis cache just in case
              // and we have the redis LRU config set up so the least recently used will get pushed out
              cacheKey = utensils.checksum(routeInfo.lang + '||' + routeInfo.appName + '||' +
                  routeInfo.url + '||' + JSON.stringify(model));
  
              return pageCacheService.get({ key: cacheKey });
          })
          .then(function (cachedPage) {
              if (cachedPage === true) { return null; }
              if (cachedPage && !serverOnly) { return cachedPage; }
  
              // allow the app level to modify the model before rendering
              appAddToModel(initialModel, routeInfo);
  
              // finally use the client side plugin to do the rendering
              return clientPlugin.renderPage(routeInfo, page, initialModel, inlineCssCache[appName + '||' + routeInfo.name]);
          })
          .then(function (renderedPage) {
              if (!serverOnly && renderedPage) {
                  pageCacheService.set({ key: cacheKey, value: renderedPage });
              }
  
              return renderedPage;
          });
  }