/* * @Author: HonorLee * @Version 2.0 * @LastUpdate 2019/10/11 */ import PATH = require('path'); export default class Router{ private static _midware:any = {}; private static _midwareIndex:Array = []; public static setMidware(rule:RegExp,func:any){ const reg = rule.toString(); if(!Router._midware[reg]){ Router._midware[reg] = {exp:rule,handler:[]}; Router._midwareIndex.push(reg); } Router._midware[reg].handler.push(func); } public static async run(requestData:RequestData){ let method = 'index'; let handlerFile; Object.keys(SYSTEM.MVC.ROUTER_MAP).forEach(path=>{ if(requestData.path && requestData.path.indexOf(path) == 0){ if(SYSTEM.MVC.ROUTER_MAP[path].constructor==String){ requestData.path = `${SYSTEM.MVC.ROUTER_MAP[path]}${requestData.path.replace(path,'')}`; }else if(SYSTEM.MVC.ROUTER_MAP[path].constructor==Object){ if(SYSTEM.MVC.ROUTER_MAP[path].method){ if(requestData.method!=SYSTEM.MVC.ROUTER_MAP[path].method){ if(requestData.res){ requestData.res.statusCode = 400; requestData.res.write('Unauthorized request method!'); requestData.res.end(); } return } } if(SYSTEM.MVC.ROUTER_MAP[path].forward){ requestData.path = `${SYSTEM.MVC.ROUTER_MAP[path].forward}${requestData.path.replace(path,'')}`; } } } }) if(requestData.path == '/'){ handlerFile = '/index.js' }else if(requestData.path && requestData.path.match(/\/$/g)){ handlerFile = `${requestData.path}index.js`; }else if(requestData.path){ try{ FILE.statSync(`${SYSTEM.MVC.PATH.CONTROLLER}${requestData.path}.js`) handlerFile = `${requestData.path}.js`; }catch(e){ const pathArr = requestData.path.split('/'); method = pathArr.pop() || 'index'; const path = pathArr.join('/'); try{ FILE.statSync(`${SYSTEM.MVC.PATH.CONTROLLER}${path}.js`) handlerFile = `${path}.js`; }catch(e){ try{ FILE.statSync(`${SYSTEM.MVC.PATH.CONTROLLER}${path}/index.js`); handlerFile = `${path}/index.js`; }catch(e){ handlerFile = null; } } } }else{ handlerFile = null; } if(method == '__construct') return Router._error(403,'Function __construct can\'t be called outside',requestData.res); if(!handlerFile) return Router._error(404,`No such handler [${requestData.path}]`,requestData.res); handlerFile = `${SYSTEM.MVC.PATH.CONTROLLER}${handlerFile}`; let handlerClass,handler; try { // eslint-disable-next-line @typescript-eslint/no-var-requires handlerClass = require(handlerFile); if(handlerClass.default) handlerClass = handlerClass.default; }catch(e:any){ console.log(e.stack); if(e.code=='MODULE_NOT_FOUND'){ Router._error(404,null,requestData.res); }else{ Router._error(404,e.stack,requestData.res); } return; } try{ handler = new handlerClass(requestData); // const mixHandler = handler; }catch(e:any){ return Router._error(403,e.stack,requestData.res); } // if(handler instanceof CONTROLLER){ // mixHandler = handler; // }else{ // const baseClass = new CONTROLLER(requestData); // mixHandler = Object.assign(baseClass,handler); // } if(typeof handler[method]==='function'){ let returnSometing; if(requestData.path && Router._midwareIndex.length){ for(const reg of Router._midwareIndex){ const match = requestData.path.match(Router._midware[reg].exp); if(match && match.index==0){ for(const func of Router._midware[reg].handler){ const ret = await func.call(handler,handler); if(ret==false) return; } } } } if(typeof handler['__construct']==='function'){ try{ returnSometing = await handler['__construct'].call(handler); }catch(e:any){ LOGGER.error(`Function __construct in [${handlerFile}] called error:`); Router._error(403,e.stack,requestData.res); return; } if(returnSometing == false) return; } if(handler[method].prototype && handler[method].prototype.method && handler[method].prototype.method.toLowerCase()!=requestData.method) return handler.end('Unauthorized request method',400); try{ await handler[method].call(handler,returnSometing); }catch(e:any){ LOGGER.error(`Function [${method}] in [${handlerFile}] called error:`); Router._error(403,e.stack,requestData.res); } }else{ Router._error(404,`No such method [${method}] in handler [${handlerFile}]`,requestData.res); } } private static _error(code:number,errMsg:string|null,res:any){ if(errMsg) LOGGER.error(errMsg); res.writeHead(code, {'Content-Type': 'text/html'}); res.end(`
- ${code} -
`); } // private static _encodeRequestData(req){ // req._GET = Router._encodeObj(req._GET); // req._POST = Router._encodeObj(req._POST); // } // private static _encodeObj(obj){ // let newObj = {}; // Object.keys(obj).forEach(key=>{ // if(typeof(obj[key]==='string')){ // newObj[encodeURI(key)] = encodeURI(obj[key]); // }else{ // newObj[encodeURI(key)] = obj[key]; // } // }) // return newObj; // } } // module.exports = Router;