Skip to content

Commit

Permalink
Performance optmization
Browse files Browse the repository at this point in the history
  • Loading branch information
rajkumardusad committed Mar 4, 2023
1 parent f061b6f commit a9aa85a
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 139 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@routejs/router",
"version": "2.1.2",
"version": "2.1.3",
"description": "Fast and lightweight http routing engine for nodejs",
"main": "index.mjs",
"type": "module",
Expand Down
135 changes: 66 additions & 69 deletions src/route.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,23 @@ module.exports = class Route {
);
}

this.caseSensitive = caseSensitive ?? false;
this.host = host;
this.hostRegexp = host ? this.#compileHostRegExp(host) : undefined;
this.method = method;
this.path = path;
this.pathRegexp = path
let hostRegexp = host ? this.#compileHostRegExp(host) : {};
let pathRegexp = path
? this.#compileRouteRegExp(path)
: group
? this.#compileMiddlewareRegExp(group)
: this.#compileMiddlewareRegExp("/");

this.caseSensitive = caseSensitive ?? false;
this.host = host;
this.hostRegexp = hostRegexp?.regexp;
this.method = method;
this.path = path;
this.pathRegexp = pathRegexp?.regexp;
this.group = group;
this.name = name;
this.params = path
? this.#getRouteParams(path)
: this.#getRouteParams(group);
this.subdomains = this.#getHostParams(host);
this.params = pathRegexp?.params;
this.subdomains = hostRegexp?.params;
this.callbacks = Array.isArray(callbacks)
? callbacks.map((callback) => {
if (typeof callback !== "function") {
Expand Down Expand Up @@ -165,101 +166,97 @@ module.exports = class Route {

#compileHostRegExp(host) {
try {
let regexp = host
? host
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^.]+?)")
: "";
let { regexp, params } = this.#compileRegExp(host, ".");
if (this.caseSensitive === true) {
return regexp ? new RegExp("^" + regexp + "$") : null;
regexp = regexp ? new RegExp("^" + regexp + "$") : null;
} else {
regexp = regexp ? new RegExp("^" + regexp + "$", "i") : null;
}
return regexp ? new RegExp("^" + regexp + "$", "i") : null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + host + " invalid regular expression");
}
}

#compileRouteRegExp(path) {
try {
let regexp = this.#compileRegExp(path);
let { regexp, params } = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
regexp = regexp
? new RegExp("^/?" + regexp + "/?$")
: regexp === ""
? new RegExp("^/?$")
: null;
} else {
regexp = regexp
? new RegExp("^/?" + regexp + "/?$", "i")
: regexp === ""
? new RegExp("^/?$", "i")
: null;
}
return regexp
? new RegExp("^/?" + regexp + "/?$", "i")
: regexp === ""
? new RegExp("^/?$", "i")
: null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileMiddlewareRegExp(path) {
try {
let regexp = this.#compileRegExp(path);
let { regexp, params } = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
regexp = regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)")
: regexp === ""
? new RegExp("^/?(?=/|$)")
: null;
} else {
regexp = regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)", "i")
: regexp === ""
? new RegExp("^/?(?=/|$)", "i")
: null;
}
return regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)", "i")
: regexp === ""
? new RegExp("^/?(?=/|$)", "i")
: null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileRegExp(path) {
#compileRegExp(path, delimiter = "/") {
try {
return path
? path
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^/]+?)")
: "";
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}
let regexp = [];
let params = [];
path.split(new RegExp("(?<!\\\\)\\" + delimiter)).forEach((e) => {
if (e === "") {
return;
}

#getRouteParams(path) {
let params = path ? path.match(/(?<=\{)([^/]+?)(?=\})/g) : null;
if (!params) {
return undefined;
}
return params.map((e) => e.replace(/\:\((.*)?/, ""));
}
let keys = e.match(/(?<=(?<!\\)\{)(([^\{]|\\{)+?)(?=(?<!\\)\})/g);
if (keys) {
keys.map((e) => {
params.push(e.replace(/\:\((.*)?/, ""));
});
}

#getHostParams(path) {
let params = path ? path.match(/(?<=\{)([^.]+?)(?=\})/g) : null;
if (!params) {
return undefined;
e = e
// Esacep regexp special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Add user defined regexp
.replace(/(?<!\\)\{(([^\{]|\\{)+?)\:(?=(.*)(?<!\\)\})/g, "")
.replace(/(?<=\))\}/g, "")
// Named regexp
.replace(
/(?<!\\)\{(([^\{]|\\{)+?)(?<!\\)\}/g,
"([^\\" + delimiter + "]+?)"
);

regexp.push(e);
});
return { regexp: regexp.join("\\" + delimiter), params: params };
} catch (err) {
console.log(err);
throw new TypeError("Error: " + path + " invalid regular expression");
}
return params.map((e) => e.replace(/\:\((.*)?/, ""));
}
};
135 changes: 66 additions & 69 deletions src/route.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,23 @@ export default class Route {
);
}

this.caseSensitive = caseSensitive ?? false;
this.host = host;
this.hostRegexp = host ? this.#compileHostRegExp(host) : undefined;
this.method = method;
this.path = path;
this.pathRegexp = path
let hostRegexp = host ? this.#compileHostRegExp(host) : {};
let pathRegexp = path
? this.#compileRouteRegExp(path)
: group
? this.#compileMiddlewareRegExp(group)
: this.#compileMiddlewareRegExp("/");

this.caseSensitive = caseSensitive ?? false;
this.host = host;
this.hostRegexp = hostRegexp?.regexp;
this.method = method;
this.path = path;
this.pathRegexp = pathRegexp?.regexp;
this.group = group;
this.name = name;
this.params = path
? this.#getRouteParams(path)
: this.#getRouteParams(group);
this.subdomains = this.#getHostParams(host);
this.params = pathRegexp?.params;
this.subdomains = hostRegexp?.params;
this.callbacks = Array.isArray(callbacks)
? callbacks.map((callback) => {
if (typeof callback !== "function") {
Expand Down Expand Up @@ -165,101 +166,97 @@ export default class Route {

#compileHostRegExp(host) {
try {
let regexp = host
? host
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^.]+?)")
: "";
let { regexp, params } = this.#compileRegExp(host, ".");
if (this.caseSensitive === true) {
return regexp ? new RegExp("^" + regexp + "$") : null;
regexp = regexp ? new RegExp("^" + regexp + "$") : null;
} else {
regexp = regexp ? new RegExp("^" + regexp + "$", "i") : null;
}
return regexp ? new RegExp("^" + regexp + "$", "i") : null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + host + " invalid regular expression");
}
}

#compileRouteRegExp(path) {
try {
let regexp = this.#compileRegExp(path);
let { regexp, params } = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
regexp = regexp
? new RegExp("^/?" + regexp + "/?$")
: regexp === ""
? new RegExp("^/?$")
: null;
} else {
regexp = regexp
? new RegExp("^/?" + regexp + "/?$", "i")
: regexp === ""
? new RegExp("^/?$", "i")
: null;
}
return regexp
? new RegExp("^/?" + regexp + "/?$", "i")
: regexp === ""
? new RegExp("^/?$", "i")
: null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileMiddlewareRegExp(path) {
try {
let regexp = this.#compileRegExp(path);
let { regexp, params } = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
regexp = regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)")
: regexp === ""
? new RegExp("^/?(?=/|$)")
: null;
} else {
regexp = regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)", "i")
: regexp === ""
? new RegExp("^/?(?=/|$)", "i")
: null;
}
return regexp
? new RegExp("^/?" + regexp + "/?(?=/|$)", "i")
: regexp === ""
? new RegExp("^/?(?=/|$)", "i")
: null;
return { regexp, params };
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileRegExp(path) {
#compileRegExp(path, delimiter = "/") {
try {
return path
? path
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^/]+?)")
: "";
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}
let regexp = [];
let params = [];
path.split(new RegExp("(?<!\\\\)\\" + delimiter)).forEach((e) => {
if (e === "") {
return;
}

#getRouteParams(path) {
let params = path ? path.match(/(?<=\{)([^/]+?)(?=\})/g) : null;
if (!params) {
return undefined;
}
return params.map((e) => e.replace(/\:\((.*)?/, ""));
}
let keys = e.match(/(?<=(?<!\\)\{)(([^\{]|\\{)+?)(?=(?<!\\)\})/g);
if (keys) {
keys.map((e) => {
params.push(e.replace(/\:\((.*)?/, ""));
});
}

#getHostParams(path) {
let params = path ? path.match(/(?<=\{)([^.]+?)(?=\})/g) : null;
if (!params) {
return undefined;
e = e
// Esacep regexp special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Add user defined regexp
.replace(/(?<!\\)\{(([^\{]|\\{)+?)\:(?=(.*)(?<!\\)\})/g, "")
.replace(/(?<=\))\}/g, "")
// Named regexp
.replace(
/(?<!\\)\{(([^\{]|\\{)+?)(?<!\\)\}/g,
"([^\\" + delimiter + "]+?)"
);

regexp.push(e);
});
return { regexp: regexp.join("\\" + delimiter), params: params };
} catch (err) {
console.log(err);
throw new TypeError("Error: " + path + " invalid regular expression");
}
return params.map((e) => e.replace(/\:\((.*)?/, ""));
}
}
Loading

0 comments on commit a9aa85a

Please sign in to comment.