83 lines
1.8 KiB
JavaScript

import http from 'node:http';
import { pathToRegexp } from 'path-to-regexp';
class Router {
constructor() {
/**
* Store the current list of routes
*/
this.routes = {};
}
/**
* This function checks for the existence of a route and calls its handler
*
* @param {http.ClientRequest} req
* @param {http.ServerResponse} res
* @returns {boolean} Is route has been handled
*/
call(req, res) {
const mask = `${req.method}:${req.url}`;
/**
* Find the exact route
*/
if (this.routes.hasOwnProperty(mask)) {
this.routes[mask].handler(req, res);
return true;
}
/**
* Find route by regular expression
*/
const keys = Object.keys(this.routes);
let i = keys.length;
while (i--) {
const route = this.routes[keys[i]];
if (!route.options.exact && route.options.regexp !== undefined) {
const match = req.url.match(route.options.regexp);
if (match && keys[i].includes(req.method)) {
if (route.options.params !== undefined) {
req.params = {};
route.options.params.forEach((param) => {
req.params[param.name] = match[1];
});
}
route.handler(req, res);
return true;
}
}
}
return false;
}
/**
* Add more routes to router store
*
* @param {string} url
* @param {function} handler
* @param {boolean} exact
*/
define(
method = 'GET',
url,
handler,
options = { exact: true, regexp: undefined, params: undefined }
) {
if (url.includes(':')) {
options.params = [];
options.exact = false;
options.regexp = pathToRegexp(url, options.params);
}
this.routes[`${method}:${url}`] = {
method,
handler,
options,
};
}
}
export default new Router();