refactor router to use array for route storage and improve route handling
This commit is contained in:
parent
ce9f313220
commit
566a1b671c
5
dist/index.js
vendored
5
dist/index.js
vendored
@ -50,9 +50,8 @@ export default class Flummpress {
|
|||||||
yield this.processPipeline(this.middleware, req, res);
|
yield this.processPipeline(this.middleware, req, res);
|
||||||
const route = this.router.getRoute(req.url.pathname, req.method);
|
const route = this.router.getRoute(req.url.pathname, req.method);
|
||||||
if (route) {
|
if (route) {
|
||||||
const [pathPattern, methods] = route;
|
const handler = route.methods[(_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()];
|
||||||
const handler = methods[(_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()];
|
req.params = ((_b = req.url.pathname.match(new RegExp(route.path))) === null || _b === void 0 ? void 0 : _b.groups) || {};
|
||||||
req.params = ((_b = req.url.pathname.match(new RegExp(pathPattern))) === null || _b === void 0 ? void 0 : _b.groups) || {};
|
|
||||||
req.post = yield this.readBody(req);
|
req.post = yield this.readBody(req);
|
||||||
yield this.processPipeline(handler, req, res);
|
yield this.processPipeline(handler, req, res);
|
||||||
}
|
}
|
||||||
|
46
dist/router.js
vendored
46
dist/router.js
vendored
@ -12,7 +12,8 @@ import path from "node:path";
|
|||||||
import Tpl from "./template.js";
|
import Tpl from "./template.js";
|
||||||
export default class Router {
|
export default class Router {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.routes = new Map();
|
this.routes = [];
|
||||||
|
this.routes;
|
||||||
this.mimes = new Map();
|
this.mimes = new Map();
|
||||||
}
|
}
|
||||||
importRoutesFromPath(p_1) {
|
importRoutesFromPath(p_1) {
|
||||||
@ -70,7 +71,6 @@ export default class Router {
|
|||||||
}
|
}
|
||||||
use(obj) {
|
use(obj) {
|
||||||
if (obj instanceof Router) {
|
if (obj instanceof Router) {
|
||||||
this.routes = new Map([...this.routes, ...obj.routes]);
|
|
||||||
this.sortRoutes();
|
this.sortRoutes();
|
||||||
}
|
}
|
||||||
if (obj instanceof Tpl) {
|
if (obj instanceof Tpl) {
|
||||||
@ -102,27 +102,47 @@ export default class Router {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
registerRoute(path, method, handler) {
|
registerRoute(path, method, handler) {
|
||||||
var _a;
|
const existingRoute = this.routes.find(route => typeof route.path === "string"
|
||||||
const route = (_a = this.routes.get(path)) !== null && _a !== void 0 ? _a : {
|
? route.path === path
|
||||||
[method]: handler
|
: route.path instanceof RegExp && path instanceof RegExp && route.path.toString() === path.toString());
|
||||||
};
|
if (existingRoute) {
|
||||||
this.routes.set(path, route);
|
existingRoute.methods[method] = [
|
||||||
|
...(existingRoute.methods[method] || []),
|
||||||
|
...handler
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.routes.push({
|
||||||
|
path,
|
||||||
|
methods: { [method]: handler }
|
||||||
|
});
|
||||||
|
}
|
||||||
console.log("route set:", method.toUpperCase(), path);
|
console.log("route set:", method.toUpperCase(), path);
|
||||||
this.sortRoutes();
|
this.sortRoutes();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
getRoute(path, method) {
|
getRoute(path, method) {
|
||||||
return [...this.routes.entries()]
|
return this.routes
|
||||||
.find(r => {
|
.find(r => {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return typeof r[0] === "string"
|
return typeof r.path === "string"
|
||||||
? r[0] === path
|
? r.path === path
|
||||||
: ((_b = (_a = r[0]).exec) === null || _b === void 0 ? void 0 : _b.call(_a, path))
|
: ((_b = (_a = r.path).exec) === null || _b === void 0 ? void 0 : _b.call(_a, path))
|
||||||
&& r[1][method.toLowerCase()];
|
&& r.methods[method.toLowerCase()];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
sortRoutes() {
|
sortRoutes() {
|
||||||
this.routes = new Map([...this.routes.entries()].sort().reverse());
|
this.routes.sort((a, b) => {
|
||||||
|
const aLength = typeof a.path === "string" ? a.path.length : a.path.source.length;
|
||||||
|
const bLength = typeof b.path === "string" ? b.path.length : b.path.source.length;
|
||||||
|
if (typeof a.path === "string" && typeof b.path === "string")
|
||||||
|
return bLength - aLength;
|
||||||
|
if (typeof a.path === "string")
|
||||||
|
return -1;
|
||||||
|
if (typeof b.path === "string")
|
||||||
|
return 1;
|
||||||
|
return bLength - aLength;
|
||||||
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
readMimes(file = "/etc/mime.types") {
|
readMimes(file = "/etc/mime.types") {
|
||||||
|
@ -89,10 +89,9 @@ export default class Flummpress {
|
|||||||
const route = this.router.getRoute(req.url.pathname, req.method!);
|
const route = this.router.getRoute(req.url.pathname, req.method!);
|
||||||
|
|
||||||
if(route) {
|
if(route) {
|
||||||
const [pathPattern, methods] = route;
|
const handler = route.methods[req.method?.toLowerCase()!];
|
||||||
const handler = methods[req.method?.toLowerCase()!];
|
|
||||||
|
|
||||||
req.params = req.url.pathname.match(new RegExp(pathPattern))?.groups || {};
|
req.params = req.url.pathname.match(new RegExp(route.path))?.groups || {};
|
||||||
req.post = await this.readBody(req);
|
req.post = await this.readBody(req);
|
||||||
await this.processPipeline(handler, req, res);
|
await this.processPipeline(handler, req, res);
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,11 @@ import Tpl from "./template.js";
|
|||||||
import { Request, Response, Handler } from "./types.js";
|
import { Request, Response, Handler } from "./types.js";
|
||||||
|
|
||||||
export default class Router {
|
export default class Router {
|
||||||
private routes: Map<RegExp | string, { [key: string]: Handler[] }>;
|
private routes: Array<{ path: string | RegExp; methods: { [method: string]: Handler[] } }> = [];
|
||||||
private tpl?: Tpl;
|
private tpl?: Tpl;
|
||||||
private mimes: Map<string, string>;
|
private mimes: Map<string, string>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.routes = new Map();
|
|
||||||
this.mimes = new Map();
|
this.mimes = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +95,7 @@ export default class Router {
|
|||||||
*/
|
*/
|
||||||
use(obj: Router | Tpl): void {
|
use(obj: Router | Tpl): void {
|
||||||
if(obj instanceof Router) {
|
if(obj instanceof Router) {
|
||||||
this.routes = new Map([...this.routes, ...obj.routes]);
|
this.routes = { ...this.routes, ...obj.routes };
|
||||||
this.sortRoutes();
|
this.sortRoutes();
|
||||||
}
|
}
|
||||||
if(obj instanceof Tpl) {
|
if(obj instanceof Tpl) {
|
||||||
@ -181,10 +180,24 @@ export default class Router {
|
|||||||
method: string,
|
method: string,
|
||||||
handler: Handler[]
|
handler: Handler[]
|
||||||
): this {
|
): this {
|
||||||
const route: { [key: string]: Handler[] } = this.routes.get(path) ?? {
|
const route = this.routes.find(route =>
|
||||||
[ method ]: handler
|
typeof route.path === "string"
|
||||||
};
|
? route.path === path
|
||||||
this.routes.set(path, route);
|
: route.path instanceof RegExp && path instanceof RegExp && route.path.toString() === path.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
if(route) {
|
||||||
|
route.methods[method] = [
|
||||||
|
...(route.methods[method] || []),
|
||||||
|
...handler
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.routes.push({
|
||||||
|
path,
|
||||||
|
methods: { [method]: handler }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
console.log("route set:", method.toUpperCase(), path);
|
console.log("route set:", method.toUpperCase(), path);
|
||||||
this.sortRoutes();
|
this.sortRoutes();
|
||||||
@ -198,11 +211,11 @@ export default class Router {
|
|||||||
* @returns The matching route or undefined.
|
* @returns The matching route or undefined.
|
||||||
*/
|
*/
|
||||||
getRoute(path: string, method: string): any {
|
getRoute(path: string, method: string): any {
|
||||||
return [...this.routes.entries()]
|
return this.routes
|
||||||
.find(r => typeof r[0] === "string"
|
.find(r => typeof r.path === "string"
|
||||||
? r[0] === path
|
? r.path === path
|
||||||
: r[0].exec?.(path)
|
: r.path.exec?.(path)
|
||||||
&& r[1][method.toLowerCase()]
|
&& r.methods[method.toLowerCase()]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +224,18 @@ export default class Router {
|
|||||||
* @returns The Router instance for chaining.
|
* @returns The Router instance for chaining.
|
||||||
*/
|
*/
|
||||||
private sortRoutes(): this {
|
private sortRoutes(): this {
|
||||||
this.routes = new Map([...this.routes.entries()].sort().reverse());
|
this.routes.sort((a, b) => {
|
||||||
|
const aLength = typeof a.path === "string" ? a.path.length : a.path.source.length;
|
||||||
|
const bLength = typeof b.path === "string" ? b.path.length : b.path.source.length;
|
||||||
|
|
||||||
|
if(typeof a.path === "string" && typeof b.path === "string")
|
||||||
|
return bLength - aLength;
|
||||||
|
if(typeof a.path === "string")
|
||||||
|
return -1;
|
||||||
|
if(typeof b.path === "string")
|
||||||
|
return 1;
|
||||||
|
return bLength - aLength;
|
||||||
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user