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