简易实现express中间件

2,852 阅读2分钟

大家好我是林三心,用了那么久express,也自己简单实现一下吧(有利于以后观看express源码)

目录结构

// expressDemo2
let http = require('http')
let url = require('url')
let querystring = require('querystring')
var util = require('util');
function createApplication() {
    // app是一个监听函数
    let app = function (req, res) {
        console.log(req.method, url.parse(req.url, true), req.body)
        // 当前请求方法
        let m = req.method.toLocaleLowerCase()
        console.log(m)
        // 当前请求路径
        let { pathname, query } = url.parse(req.url, true)

        // 迭代次数索引
        let index = 0
        // 用next代替for循环
        function next() {
            // 如果全部路由数组都不满足,则返回找不到
            if (index === app.routes.length) {
                return res.end(`can not ${m} ${pathname}`)
            }
            // 处理中间件
            let { path, method, handler } = app.routes[index++]
            if (method === 'middle') {
                // 如果该中间件path是/,匹配全部请求,执行回调,如果相等,执行回调,如果该中间件path被包含在当前url,也执行回调
                if (path === '/' || path === pathname || pathname.startsWith(path + '/')) {
                    handler(req, res, next)
                } else {
                    next()
                }
            } else {
                if ((path === pathname || path === '*') && (method === m || method === 'all')) {
                    // 方法参数单独判断
                    switch (method) {
                        case 'get':
                            req.query = query
                            break
                        case 'post':
                        // 定义了一个post变量,用于暂存请求体的信息
                        // var post = '';

                        // // 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
                        // req.on('data', function (chunk) {
                        //     post += chunk;
                        // });

                        // // 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
                        // req.on('end', function () {
                        //     post = querystring.parse(post);
                        //     console.log(util.inspect(post));
                        // });
                    }
                    handler(req, res, next)
                } else {
                    next()
                }
            }
        }

        next()
        res.end('hello world')
    }

    // 存储所有的请求,以便监听函数调用
    app.routes = []

    // http.METHODS获取restful所有方法
    // console.log(http.METHODS)
    http.METHODS.forEach(method => {
        method = method.toLocaleLowerCase()
        app[method] = function (path, handler) {
            let layer = {
                path,
                method,
                handler
            }
            app.routes.push(layer)
        }
    })

    // 如果没有匹配成功,最终执行all函数所储存的回调
    app.all = function (path, handler) {
        let layer = {
            path,
            method: 'all',
            handler
        }
        app.routes.push(layer)
    }

    app.listen = function () {
        let server = http.createServer(app)
        // arguments就是参数(3000, 'localhost', function() {})
        server.listen(...arguments)
        return server
    }

    return app
}

module.exports = createApplication
// appDemo.js
const expressDemo = require('./expressDemo2')
let app = expressDemo()
// console.log(app)
app.get('/name', (req, res) => {
    console.log(req.query.name)
    res.end('get name')
})
app.post('/name', (req, res) => {
    // console.log(req.body)
    res.end('get name')
})
app.put('/name', (req, res) => {
    console.log(req.query.name)
    res.end('get name')
})
app.delete('/name', (req, res) => {
    console.log(req.query.name)
    res.end('get name')
})

app.listen(9002, 'localhost', () => {
    console.log('林三心在9002')
})

主要要理解“中间件是什么”?express方便在哪里?use方法是用来干嘛的?加油!!!