summaryrefslogtreecommitdiff
path: root/lib/router.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/router.js')
-rw-r--r--lib/router.js53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/router.js b/lib/router.js
new file mode 100644
index 0000000..fd24693
--- /dev/null
+++ b/lib/router.js
@@ -0,0 +1,53 @@
+"use strict"; // https://github.com/mixu/minimal
+
+const url = require("url");
+const degroup = path => Object.assign(path, path.groups);
+
+class Router {
+ constructor() {
+ this.routes = [];
+ }
+
+ route(req, res) {
+ const pathname = url.parse(req.url).pathname;
+ return this.routes.some(route => {
+ const isMatch = route.method === req.method && route.re.test(pathname);
+ if (isMatch) route.cb(req, res, degroup(route.re.exec(pathname)));
+ return isMatch;
+ });
+ }
+
+ gather(cb, max) { // Handle POST data
+ return (req, res, match) => {
+ let data = "";
+ req.on("data", chunk => {
+ if ((data += chunk).length > (max||1e6)) // ~1MB
+ req.connection.destroy();
+ }).on("end", () => cb(req, res, match, data));
+ };
+ }
+
+ gpost(re, cb, max) {
+ this.post(re, this.gather(cb, max));
+ }
+
+ jpost(re, cb, max) {
+ this.gpost(re, (req, res, match, data) => {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ res.writeHead(400, {"Content-Type": "text/plain"});
+ return res.end("400 Bad Request");
+ }
+
+ cb(req, res, match, data);
+ }, max);
+ }
+}
+
+["get", "post", "put", "delete"].forEach(method =>
+ Router.prototype[method] = function(re, cb) {
+ this.routes.push({method: method.toUpperCase(), cb,
+ re: (re instanceof RegExp)? re : new RegExp(`^${re}$`)})});
+
+module.exports = Router;