const http = require('http')
let slice = Array.prototype.slice
class express{
constructor(){
this.routes={
all:[],//用于储存app.use()方法注册的中间件
get:[],//用于储存app.get()方法注册的中间件
post:[]//用于储存app.post()方法注册的中间件
}
}
register(path){
//判断注册的参数个数
let info={}//存储每一次注册的信息
if(typeof path === 'string'){
info.path = path//注册路径
//如果是带有路由string的参数注册,那么就要将第一个路由参数截去,剩下的才是中间件参数
info.stack = slice.call(arguments,1)
}else{
info.path ='/'
//如果不带就不用截取
info.stack = slice.call(arguments,0)//存储中间件参数数组
}
return info
}
use(){
const info = this.register.apply(this,arguments)
//argument获得的就是中间件参数列表
this.routes.all.push(info)
}
get(){
const info = this.register.apply(this,arguments)
this.routes.get.push(info)
}
post(){
const info = this.register.apply(this,arguments)
this.routes.post.push(info)//将注册信息放入存储数组中
}
match(url,method){
let stack = []//中间件堆放栈
if(url === '/favicon.ico'){
return stack//浏览器自带请求直接返回
}
let curRoutes = []
curRoutes = curRoutes.concat(this.routes.all)
curRoutes = curRoutes.concat(this.routes[method])
curRoutes.forEach(item=>{
if(url.indexOf(item.path)===0){
//检测是不是浏览器中输入url的父级路径,如果是就将符合条件的中间件放入栈中
stack = stack.concat(item.stack)
}
})
return stack
}
handle(req,res,stack){
const next = () => {
// 拿到第一个匹配的中间件
const middleware = stack.shift()
if (middleware) {
// 执行中间件函数
middleware(req, res, next)
}
}
next()
}
callback(){
return (req, res) => {
res.json = (data) => {
res.setHeader('Content-type', 'application/json')
res.end(
JSON.stringify(data)
)
}//express中的res.json方法
const url = req.url
const method = req.method.toLowerCase()
const resultList = this.match(url,method)//根据路由来匹配中间件是否执行
this.handle(req, res, resultList)
}
}
listen(...args){//监听端口
let server = http.createServer(this.callback())//回调函数
server.listen(...args)
}
}
module.exports = ()=>{
return new express()
}