const http = require("http");
const url = require('url');
const { METHODS } = http;
// METHODS 为
// [
// 'ACL', 'BIND', 'CHECKOUT',
// 'CONNECT', 'COPY', 'DELETE',
// 'GET', 'HEAD', 'LINK',
// 'LOCK', 'M-SEARCH', 'MERGE',
// 'MKACTIVITY', 'MKCALENDAR', 'MKCOL',
// 'MOVE', 'NOTIFY', 'OPTIONS',
// 'PATCH', 'POST', 'PROPFIND',
// 'PROPPATCH', 'PURGE', 'PUT',
// 'REBIND', 'REPORT', 'SEARCH',
// 'SOURCE', 'SUBSCRIBE', 'TRACE',
// 'UNBIND', 'UNLINK', 'UNLOCK',
// 'UNSUBSCRIBE'
// ]
const createServer = () => {
// 这里取名为 app, 只是为了方便,实际上就是个处理请求的函数
const app = function (req, res) {
// 取出请求的方法
const reqMethod = req.method.toLowerCase();
// 取出请求的路径
const { pathname } = url.parse(req.url, true)
// 中间件中的 next 函数,迭代 handles
let index = 0;
function next(err) {
if(index === app.handles.length) {
// 如果最终没有匹配到任何路由或中间件,那么返回 not found
res.end('not found');
return;
}
// 每次调用 next,就取下一个 layer
const { method, path, handler } = app.handles[index++];
if(err) {
// next 有参数,则认为是错误, 那么跳过中间的中间件和路由,去到错误中间件(函数参数为4)
if(handler.length === 4) {
handler(err, req, res, next);
} else {
// 如果没有匹配到,则继续抛到下一个中间件或路由
next(err);
}
} else {
if (method === 'middleware') {
// 如果是中间件,且匹配到了
if(path === '/' || path === pathname || pathname.startsWidth(path + '/')) {
// 传入 next 函数
console.log('匹配到了');
handler(req, res, next);
} else {
// 没有匹配到,则调用下一个 layer
next()
}
} else {
// 如果方法,路径匹配,则进行处理, 同时处理 all
if( (method === reqMethod || method === 'all') && (pathname === path || path === '*')) {
handler(req, res)
} else {
// 如果没有找到,则调用下一个 layer
next();
}
}
}
}
next();
}
app.handles = []; // 存放 layer: (路由和中间件)
app.listen = function (...args) {
const server = http.createServer(app)
server.listen(...args)
}
// 给 app 添加 get, post 等 http 请求方法
// 每个方法其实给 handles 推送一个 layer
METHODS.forEach(method => {
method = method.toLowerCase();
app[method] = function (path, handler) {
app.handles.push({
method,
path,
handler
})
}
})
app.all = function (path, handler) {
app.handles.push({
method: 'all',
path,
handler
})
}
// 中间件
app.use = function(path, handler) {
// 如果不传 path,那么默认 path 为 '/'
if(typeof handler !== 'function') {
handler = path
path = '/'
}
app.handles.push({
method: 'middleware', // 表示这是一个中间件
path,
handler
})
}
return app
}
module.exports = createServer;