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