Node.js 实现路由
可从git.1473.cn查看源码
搭建http服务器
const http = require('http');
const url = require('url');
//启动服务
app.listen = (port, host, callback) => {
http.createServer((req, res) => {
// 获取请求的方法
const method = req.method.toLowerCase()
// 解析url
const urlObj = url.parse(req.url, true)
// 获取path部分
const pathName = urlObj.pathname
// 获取后缀
const ext = path.extname(pathName).slice(1);
// 若有后缀 则是静态文件
if (ext) {
handleStatic(res, _static + pathName, ext) // 详见 下一章 实现目录浏览功能
} else {
// 遍历路由池
passRouter(app.routes, method, pathName)(req, res) // 具体实现在下面
}
}).listen(port, host, ()=>{
console.log(`server start at http://${host}:${port}`)
});
};
app.listen('8100', 'localhost')
实现路由
实现路由池
const app = {};
app.routes = [];
let _static = '.';
// 命令集合
const methods = ['get', 'post', 'put', 'delete', 'options', 'all', 'use'];
// 实现路由池
methods.forEach((method) => {
app[method] = (path, fn) => {
app.routes.push({method, path, fn});
}
});
遍历路由池
// 使用generator函数实现惰性求值
const lazy = function* (arr) {
yield* arr;
}
// routes 路由池
// method 命令
// path 请求路径
const passRouter = (routes, method, path) => (req, res) => {
const lazyRoutes = lazy(routes);
(function next() {
// 当前遍历状态
const it = lazyRoutes.next().value;
if (!it) {
// 已经遍历了所有路由 停止遍历
res.end(`Cannot ${method} ${path}`);
return;
} else if (it.method === 'use' && (it.path === '/' || it.path === path || path.startsWith(it.path.concat('/')))) {
// 匹配到中间件
it.fn(req, res, next);
} else if ((it.method === method || it.method === 'all') && (it.path === path || it.path === "*")) {
// 匹配到路由
it.fn(req, res);
} else {
// 继续匹配
next();
}
})()
}