UNPKG

fc-route

Version:

一个强大轻便的nodejs路由

228 lines (213 loc) 5.76 kB
/* * @Author : lovefc * @Date : 2021-03-17 16:39:17 * @LastEditTime : 2025-04-16 18:19:40 */ const _querystring = require('querystring'); const _url = require('url'); const _fs = require("fs"); const _path = require("path"); class route { // 构造函数 constructor() { this.routeRule = {}; this.params = {}; this.routeCache = {}; this.prefixStr = ''; this.routeSort = 0; this.methods = [ 'HEAD', 'OPTIONS', 'GET', 'PUT', 'PATCH', 'POST', 'DELETE', 'ALL' ]; this.notPage = function (res) { let body = '<html><head><title>404 Not Found</title></head><body style="width:100%;height:100%;top:45%;position:relative;overflow:hidden;"><center><h1>404 Not Found</h1></center></body></html>'; res.writeHead(404, { "Content-Type": "text/html;charset=UTF8" }); res.end(body); } let that = this; for (let i = 0; i < this.methods.length; i++) { let method = this.methods[i].toLowerCase(); // 获取方法 this.routeRule[method] = {}; this[method] = function (rule, callback) { // 检测是不是数组 if (Array.isArray(rule) === true) { for (let i2 in rule) { let rule2 = rule[i2]; rule2 = that.prefixStr + rule2; that.routeRule[method][rule2] = callback; }; } else { if (that.isFun(rule)) { ++that.routeSort; that.routeRule[method][that.routeSort] = rule; } else { rule = that.prefixStr + rule; that.routeRule[method][rule] = callback; } } return that; }; } } // 设定前缀 prefix(prefix) { this.prefixStr = prefix; } use(method, rule, callback) { if (typeof method === 'function') { return this; } this.routeRule[method][rule] = callback; return this; } // http初始化函数 async httpInit(req, res) { let query = this.getParam(req.url); let param = decodeURI(query[0]); // 获取字符串 if (param === '/favicon.ico') { return; } let params = new URLSearchParams(query[1]); const parsed = {}; for (const [key, value] of params) { parsed[key] = value; } this.params = parsed; this.req = req; this.res = res; let method = req.method.toLowerCase(); let routes = Object.assign(this.routeRule.all, this.routeRule[method]); // 合并数组,如果all在前面,那么就会被后面的替换 this.run(routes, param); } // 初始化http http(server) { let that = this; server.on('request', async function (req, res) { await that.httpInit(req, res); }); } // 解析参数 getParam(url) { let query = []; if (url.indexOf("?") != 0) { query = url.split("?"); } return query; } // 运行匹配 run(routeRule, routePath) { let i = 0, rules = []; let reg = /^[0-9]$/; for (let key in routeRule) { if (reg.test(key)) { this.callBack(routeRule[key]); } if (this.match(key, routePath)) { rules[i] = routeRule[key]; if (key.search(/(%|@|:|~|!)/) == -1) { break; } } i++; } rules = rules.reverse(); if (rules[0] && this.isFun(rules[0])) { this.callBack(rules[0]); } else { this.callBack(this.notPage(this.res)); } } // 回调 callBack(call) { try { this.req.params = this.params; this.isFun(call) && call(this.req, this.res); } catch (error) { console.error("错误: " + error.message); this.notPage(this.res); } } // 判断函数 isFun(fun) { return (typeof fun === 'function') ? true : false; } // 判断正则 isReg(reg) { let isReg; try { isReg = eval(reg) instanceof RegExp } catch (e) { isReg = false } return isReg } // 匹配路由 match(rulestr, routePath) { let route = routePath; // 当前路由 // 如果在规则中没遇到一些特殊字符串 if (rulestr.search(/(%|@|:|~|!)/) == -1) { if (route == rulestr) { return true; } return false; } // 判断正则 let match = []; match = this.rules(rulestr); if (route && match) { let patt = new RegExp(eval(match['match']), "g"); // 去头去尾,只吃中间,exec匹配后的后三个键名是固定的,前面的键名也是固定的 let arr = patt.exec(route); if (arr) { let query = arr.slice(1, arr.length); let param = match['param']; Object.keys(param).map(function (key, index) { param[key] = query[index]; }); this.params = Object.assign(this.params, param); return true; } } return false; } // 匹配路由规则 rules(rulestr) { if (this.routeCache[rulestr]) { return this.routeCache[rulestr]; } let rules = { "%": "(\\d+)", // 匹配数字 "@": "([A-za-z]+)", // 匹配大小写字符串 ":": "([A-Za-z0-9@&*%!#-_]+)", // 匹配大小写数字以及&*%!# "!": "([\u4e00-\u9fa5]+)", // 匹配中文 "~": "(|[\u4e00-\u9fa5\A-Za-z0-9@&*%!:#$-_\/]+)", // 匹配所有字符串,此项能匹配以上的所有路由,请放在第二匹配上,第一匹配请不要用,请慎重选择 }; let values = []; let patt = new RegExp(/(%|@|:|~|!)([A-Za-z0-9_-]+)/); // 匹配定义的规则 let str = []; while ((str = patt.exec(rulestr)) != null) { let pament = str[0]; // 全部匹配 let pament2 = str[1]; // 符号 let pament3 = str[2]; // 变量名 if (rules.hasOwnProperty(pament2)) { rulestr = rulestr.replace(pament, rules[pament2]); values[pament3] = pament3; } } let route = []; route['match'] = '/^' + rulestr.replace(/\//g, '\\/') + '$/'; route['param'] = values; this.routeCache[rulestr] = route; return route; } } module.exports = route;