1 /**
  2  * @fileOverview 
  3  * Helper functions for path-based dispatching of the request.
  4  */
  5 /**
  6  * Helper functions for path-based dispatching of the request.
  7  * @type object
  8  * @constructor
  9  * @class Helper functions for path-based dispatching of the request.
 10  */
 11  var dispatching = {};
 12  
 13 /**
 14  * Converts the path into a function name and calls that function.  The function
 15  * name is by replacing '/' characters in the path with underscores, and prepending
 16  * the request method (get or post).  For requests that end in '/', you can
 17  * optionally suffix your function name with 'main'.
 18  *
 19  * @example
 20 function get_main() {
 21   // called with user visits http://appname.appjet.net/
 22   print("hello");
 23 }
 24 function get_page() {
 25   // called with user visits http://appname.appjet.net/page
 26 }
 27 function post_foo() {
 28   // called when user POSTs to http://appname.appjet.net/foo
 29 }
 30 dispatch(); // examines request and calls one of the above functions.
 31  *
 32  * @param {object} [opts] (optional) if opts.custom404 is a function, then this function will be
 33  *   called if there is no function corresponding to the request path.  If opts is
 34  *   is not specified, a default 404 handler displays "404 not found".
 35  */
 36 function dispatch(opts) {
 37   var custom404 = null;
 38   if (opts && opts.custom404) {
 39     custom404 = opts.custom404;
 40   }
 41   var fname = request.method.toLowerCase() + request.path.replace(/\//g, '_');
 42   var f = appjet._internal.global[fname];
 43   if (typeof(f) == 'function') {
 44     f();
 45     return;
 46   }
 47   if (fname.charAt(fname.length - 1) == '_') {
 48     f = appjet._internal.global[fname + 'main'];
 49     if (typeof(f) == 'function') {
 50       f();
 51       return;
 52     }
 53   }
 54   _404(custom404);
 55 }
 56 
 57 function _404(custom404) {
 58   response.setStatusCode(404);
 59   if (custom404) {
 60     custom404();
 61   } else {
 62     _default404();
 63   }
 64 }
 65 
 66 function _default404() {
 67   print(raw(sprintf('<div style="font-size: 200%%;">404 Path not found: %s</div>',
 68 		    request.path)));
 69   print(P("Request is:"));
 70   print(request);
 71 }
 72 
 73 /**
 74  * Similar to dispatch(), but you provide your own mapping of regular expresions
 75  * to functions.
 76  *
 77  * @example
 78 function handleIndex() {
 79   print("this is the main landing page");
 80 }
 81 function handleFoo() {
 82   print("this is the foo page");
 83 }
 84 function unknown() {
 85   response.setStatusCode(404);
 86   print("path not found: ", request.path);
 87 }
 88 patternDispatch(
 89   [/^\/$/, handleIndex],
 90   [/^\/foo$/, handleFoo],
 91   unknown
 92 );
 93  *
 94  * @param {array} pattern1 array of [regexp, method]
 95  * @param {array} pattern2 array of [regexp, method]
 96  * @param {array} patternN ...
 97  * @param {function} [optional404] called if none of the previous patterns match
 98  */
 99 function patternDispatch(pattern1, pattern2, patternN, optional404) {
100   var pathfound = false;
101   function match(pattern, f) {
102     if ((typeof(pattern) == 'string') && (pattern == request.path)) {
103       f();
104       return true;
105     }
106     if (pattern instanceof RegExp) {
107       var result = pattern.exec(request.path);
108       if (result && result.length > 0) {
109 	f.apply(this, result.slice(1));
110 	return true;
111       }
112     }
113     return false;
114   }
115   for (var i = 0; i < arguments.length; i++) {
116     if (i == arguments.length - 1 && ! (arguments[i] instanceof Array)) // ok if last arg isn't an array
117       continue;
118     var pattern = arguments[i][0];
119     var f = arguments[i][1];
120     if (match(pattern, f)) {
121       pathfound = true;
122     }
123   }
124   if (!pathfound) {
125     var lastArg = arguments[arguments.length-1];
126     if (typeof(lastArg) == 'function')
127       _404(lastArg);
128     else
129       _404();
130   }
131 }
132