Skip to main content
Module

x/opine/src/router/route.ts

Fast, minimalist web framework for Deno ported from ExpressJS.
Very Popular
Go to Latest
File
import { Layer } from "./layer.ts";import { methods } from "../methods.ts";import type { NextFunction, OpineRequest, OpineResponse } from "../types.ts";
/** * Initialize `Route` with the given `path`. * * @param {string} path * @public */export const Route: any = function Route(this: any, path: string): void { this.path = path; this.stack = [];
// route handlers for various http methods this.methods = {};};
/** * Determine if the route handles a given method. * @private */Route.prototype._handles_method = function _handles_method(method: any) { if (this.methods._all) { return true; }
let name = method.toLowerCase();
if (name === "head" && !this.methods["head"]) { name = "get"; }
return Boolean(this.methods[name]);};
/** * @return {Array} supported HTTP methods * @private */Route.prototype._options = function _options() { let methods = Object.keys(this.methods);
// append automatic head if (this.methods.get && !this.methods.head) { methods.push("head"); }
for (let i = 0; i < methods.length; i++) { // make upper case methods[i] = methods[i].toUpperCase(); }
return methods;};
/** * dispatch req, res into this route * @private */Route.prototype.dispatch = function dispatch( req: OpineRequest, res: OpineResponse, done: NextFunction,) { let idx = 0; let stack = this.stack; if (stack.length === 0) { return done(); }
let method = req.method.toLowerCase(); if (method === "head" && !this.methods["head"]) { method = "get"; }
req.route = this;
next();
function next(err?: Error | string): any { // signal to exit route if (err && err === "route") { return done(); }
// signal to exit router if (err && err === "router") { return done(err); }
let layer = stack[idx++]; if (!layer) { return done(err); }
if (layer.method && layer.method !== method) { return next(err); }
if (err) { layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); } }};
/** * Add a handler for all HTTP verbs to this route. * * Behaves just like middleware and can respond or call `next` * to continue processing. * * You can use multiple `.all` call to add multiple handlers. * * function check_something(req, res, next){ * next(); * }; * * function validate_user(req, res, next){ * next(); * }; * * route * .all(validate_user) * .all(check_something) * .get(function(req, res, next){ * res.send('hello world'); * }); * * @param {function} handler * @return {Route} for chaining * @public */Route.prototype.all = function all() { let handles = Array.prototype.slice.call(arguments).flat(1);
for (let i = 0; i < handles.length; i++) { let handle = handles[i];
if (typeof handle !== "function") { let type = Object.prototype.toString.call(handle); let msg = "Route.all() requires a callback function but got a " + type; throw new TypeError(msg); }
let layer = Layer("/", {}, handle); layer.method = undefined;
this.methods._all = true; this.stack.push(layer); }
return this;};
methods.forEach(function (method) { Route.prototype[method] = function () { let handles = Array.prototype.slice.call(arguments).flat(1);
for (let i = 0; i < handles.length; i++) { let handle = handles[i];
if (typeof handle !== "function") { let type = Object.prototype.toString.call(handle); let msg = "Route." + method + "() requires a callback function but got a " + type; throw new Error(msg); }
let layer = Layer("/", {}, handle); layer.method = method;
this.methods[method] = true; this.stack.push(layer); }
return this; };});