123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /* appjet:version 0.1 */
- /* appjet:library */
- // Copyright (c) 2009, Herbert Vojčík
- // Licensed by MIT license (http://www.opensource.org/licenses/mit-license.php)
- /** Decoded segments of full path */
- request.fullPathSegments = request.path.split('/').map(decodeURIComponent);
- /** Decoded full path */
- request.fullPath = request.fullPathSegments.join('/');
- /**@ignore*/
- request.fullPathSegments.of = request.fullPath;
- /**
- * <p>Enhanced dispatcher function. Dispatches according to request.fullPath. Allows for:</p>
- * <ul><li>nonalphanumeric characters in path. Serve /robots.txt with <code>get_robots$txt</code></li>
- * <li>subpath matching: <ul>
- * <li>Serve /foo/, /foo/bar and /foo/bar/baz from <code>get_foo_</code></li>
- * <li><code>get_foo_main</code> serves only the /foo/ path, but not the /foo/bar, nor /foo</li>
- * <li>If there are more functions matching, the most specific (the longest one) wins</li>
- * <li><code>request.pagePath</code> is set to path of your handler (/foo), <code>request.pathTail</code> is set to the rest(/bar).</li>
- * <li><code>request.fullPath</code> contains the full path in decoded form</li>
- * <li>request.fullPathSegments, request.pagePathSegments and request.pathTailSegments contain segments of these paths</li>
- * </li></ul>
- * <li>404 handling is different: assign your 404 handler to dispatchPlus.f404</li>
- * <li>If you pass arguments to dispatchPlus call, they are passed to handler function. No more need for globals to pass initial information to handler functions.</li>
- * </ul>
- */
- function dispatchPlus(arg1, arg2, etc) {
- _rejuvenateFullPathSegments();
- var selectorSegments = request.fullPathSegments.map(function(x) {
- return [x.replace(/[\W]/g,'$$'), "_"];
- });
- selectorSegments.push([selectorSegments.pop()[0] || "main"]);
- var handler, handlerSegments, selector = arguments.callee[request.method] || request.method.toLowerCase();
- selectorSegments.forEach(function(segment, index) {
- selector += segment.join('');
- var candidate = appjet._internal.global[selector];
- if (typeof candidate === "function") {
- handler = candidate;
- handlerSegments = index + 1;
- }
- });
- if (handler) {
- request.pagePathSegments = request.fullPathSegments.slice(0, handlerSegments);
- request.pathTailSegments = request.fullPathSegments.slice(handlerSegments);
- request.pagePath = request.pagePathSegments.join('/');
- request.pathTail = request.fullPath.substring(request.pagePath.length);
- }
- (handler || arguments.callee.f404).apply(null, arguments);
- }
- /** The 404 (page not found) handler. You can replace it with your own. */
- dispatchPlus.f404 = function() {
- response.setStatusCode(404);
- printp("Path not found: ", request.fullPath);
- print(request);
- response.stop();
- };
- /** The prefix for GET method dispatcher functions. Default is "get", you can change it. */
- dispatchPlus.GET = "get";
- /** The prefix for HEAD method dispatcher functions. Default is "get", you can change it. */
- dispatchPlus.HEAD = "get";
- /** The prefix for POST method dispatcher functions. Default is "post", you can change it. */
- dispatchPlus.POST = "post";
- /** The prefix for CRON method dispatcher functions. Default is "cron", you can change it. */
- dispatchPlus.CRON = "cron";
- function _rejuvenateFullPathSegments() {
- if (request.fullPathSegments.of === request.fullPath) return;
- request.fullPathSegments = request.fullPath.split('/');
- request.fullPathSegments.of = request.fullPath;
- }
- /* appjet:server */
- import("lib-app/dispatch-plus");
- /**@ignore*/
- function printRequest() {
- printp({
- pagePath: request.pagePath,
- pagePathSegments: request.pagePathSegments,
- fullPath: request.fullPath,
- fullPathSegments: request.fullPathSegments,
- pathTail: request.pathTail,
- pathTailSegments: request.pathTailSegments
- });
- };
- /**@ignore*/
- function get_(arg) {
- printp("Serviced by ", CODE(arguments.callee));
- printp("Try these links:");
- print(UL(
- LI(A({href:"/long/path/here.2"}, "/long/path/here.2")),
- LI(A({href:"/papľuh/path-ing/"}, "/papľuh/path-ing/"))
- ));
- printp("Hello, ", arg, "!");
- printRequest();
- }
- /**@ignore*/
- function get_papľuh_(arg) {
- printp("Serviced by ", CODE(arguments.callee));
- printp("Hello, ", arg, "!");
- printRequest();
- }
- /**@ignore*/
- var get_papľuh_path$ing = "This is not a function";
- /**@ignore*/
- function get_long_path_() {
- throw new Error("This should not be called.");
- }
- /**@ignore*/
- function get_long_path_here$2(arg) {
- printp("Serviced by ", CODE(arguments.callee));
- printp("Hello, ", arg, "!");
- printRequest();
- }
- /**@ignore*/
- function get_long_path_here$2_() {
- throw new Error("This should not be called.");
- }
- /**@ignore*/
- function get_long_path_here$2_main() {
- throw new Error("This should not be called.");
- }
- printp("Features of extended dispatcher:");
- print(UL(
- LI("Any nonalphanumeric characters (except the slash, of course) are replaced by '$' (dollar sign). Now you can serve /robots.txt by get_robots$txt function."),
- LI("You can put a handler only to a beginning part of the path, if you use name like get_beginning_. This serves all paths in the form /beginning/... The path is broken to request.pagePath (the first part) and request.pathTail (the rest)."),
- LI("If you end function with _main, it will not serve subpaths (it only matches to full path ending with / (a slash)."),
- LI("If there are more subpath handlers and full path handlers, the most specific (the one that matches the longest part of the path) is chosen. If case of get_path_ and get_path_main, the latter will be chosen to service /path/, but the former to service /path/some/more."),
- LI("404 is handled other way: you specify your 404 handler by assigning it to dispatchPlus.f404 before placing a call."),
- LI("Any arguments you put in dispatchPlus call, gets copied into your handler function.")
- ));
- printp("The statments issued in this minitest is ", CODE('dispatchPlus("world")'));
- dispatchPlus("world");
|