nodejs手寫一個(gè)httpserver(一、app/router對象)

先參考(抄襲)一下express的api
app.use(...);
router.get(url,...)
router.post(url,...)
對比原生的node http模塊,express這些API非常好用了,并且use方法,可以把功能代碼拆分出來,比如body-parser router 都是拆成中間件的形式,完成自己的功能的
試著手寫一個(gè)server實(shí)現(xiàn)這些功能,開發(fā)一個(gè)能用一些實(shí)用的API的server,而不是原生NodeAPI

image.png

app

app是傳入HTTP.createServer的handeler,那它肯定是這樣一個(gè)函數(shù)

const app = (req, res) => {
   ...
}

用于執(zhí)行use注冊的中間件,把url分發(fā)給router路由(其實(shí)這是router該干的事,app只處理use的中間件)

實(shí)現(xiàn)app.use

用中間件的時(shí)候,中間件中都有3個(gè)參數(shù),req,res,next,前兩個(gè)簡單,從app作用域就能拿到,那么next()調(diào)用呢,next調(diào)用時(shí),也有3個(gè)參數(shù),reqresnext,其中next是下一環(huán)節(jié)的中間件。
想了半天,給注冊的中間件數(shù)組們一個(gè)排序,創(chuàng)建了一個(gè)next方法按序調(diào)用。。。(應(yīng)該不太對,不過實(shí)現(xiàn)了)

const app = (req, res) => {
    // json api
    res.json = json
    console.log('start', req.method, req.url, req.query)
    // 反著給他們幫定next參數(shù)
    function next(index) {
        console.log('next' + index, req.url, req.query)
        app.actions[index].call(this, req, res, next.bind(this, index + 1))
    }

    app.actions[0](req, res, next.bind(this, 1));
}
app.actions = []

// 實(shí)現(xiàn)注冊中間件
app.use = (handler) => {
    app.actions.push(handler)
}
module.exports = app

// json
function json(object) {
    this.writeHeader(200, { 'Content-Type': 'application/json;charset=UTF-8' })
    this.write(JSON.stringify(object))
    this.end()
}

router

router的功能是用來分發(fā)url給 router.get 或 router.post 注冊的handler
那簡單,用if判斷一下就好了

const router = (req, res, next) => {
    const { method, url } = req
    if (method === 'GET') {
        router.getRoutes[url](req, res, next)
    } else if (method === 'POST') {
        router.postRoutes[url](req, res, next)
    }
}
router.getRoutes = {}
router.postRoutes = {}
router.get = (path, handler) => {
    router.getRoutes[path] = handler
}
router.post = (path, handler) => {
    router.postRoutes[path] = handler
}

module.exports = router

中間件

寫好了app.use,就可以瘋狂的以中間件的形式寫server的功能了

queryString

原始的message.url 是帶著參數(shù)的,要在這個(gè)環(huán)節(jié)給拆出來,用正則表達(dá)式替換就可以了

let { REG_URL } = require('./CONST') ///(?!=\?)(\/.+)\?(.+)/

// 處理querystring中的參數(shù)

module.exports = function (req, res, next) {
    const url = req.url.replace(REG_URL, '$1')
    const querys = req.url.replace(REG_URL, '$2').split('&')
    const query = {}
    querys.forEach(item => {
        const [key, value] = item.split('=')
        query[key] = value
    })
    req.url = url
    req.query = query
    next()
}

body-parser

body-parser太難寫了,看了半天api文檔也沒明白咋取,知道的朋友給我留言,謝謝你們了。
好在寫了app.use,直接use第三方的body-parser模塊就可以實(shí)現(xiàn)了。


image.png

還行,第三方模塊可以用,最基本的流程跑通了

over 沒處理報(bào)錯(cuò)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容