1. 程式人生 > >express中介軟體,一篇文章就夠了

express中介軟體,一篇文章就夠了

回到目錄

底層:http模組

express目前是最流行的基於Node.js的web開發框架,express框架建立在內建的http模組上,

var http = require('http')
var  app = http.createServer(function(req,res){
    res.writeHead(200,{"Content-type":"text/plain"});
    res.end('hello world')
})

app.listen(3000,'lcoalhost')

上面程式碼的關鍵是使用createServer方法,生成一個HTTP的伺服器例項。該方法接受一個回撥函式,回撥函式的引數分別代表HTTP請求和HTTP迴應的request

response物件

Experss框架的核心是對http模組的再包裝,

var express = require('express')
var port  = process.env.PORT || 3000
var app = express()
app.get('/',fcuntion(req,res){
  res.send('hello world')
})
app.listen(port)

比較http.createServer()方法建立一個app例項和Express的構造方法,生成一個Express例項,兩者的回撥函式都是相同的。Express框架等於在http模組之上,加了一箇中間層

回到目錄

中介軟體

Express是一個自身功能極簡單,完全由路由中介軟體構成的web開發框架,從本質上說,一個Express應用是在呼叫各種中介軟體

中介軟體(middleware)是一個函式,他可以訪問請求物件(request object(req)),響應物件(response object(res))和web應用中處於請求-響應迴圈

Express可以使用如下幾種中介軟體:

- 應用級中介軟體
- 路由級中介軟體
- 錯誤處理中介軟體
- 內建中介軟體
- 第三方中介軟體
回到目錄

應用級中介軟體

應用級中間鍵繫結到app物件使用app.useapp.METHOD()-需要處理http請求的方法,例如GET、PUT、POST

var app = express()

// 沒有掛載路徑的中介軟體,應用中的每個請求都會執行該中介軟體
app.use((req,res,next) => {
    console.log('Time',Dtae.now());
    next(); // 傳遞request物件給下一個中介軟體
})

// 掛載至/user/:id的中介軟體,任何執行/user/:id的請求都會執行它
app.use('/use/:id',(req,res,next) => {
    console.log('Request Type',req.method);
    next();
})

// 路由和控制代碼函式(中介軟體系統),處理指向/user/:id的GET請求
app.get('/user/:id',(req,res,next)=>{
    console.log('USER');
})

$ node app
result

如果我們想要處理掛在至/user/:id的中介軟體的GET請求,我們需要使用next()request物件傳遞給下一個中介軟體

否者:
error 得不到下一個中介軟體處理的它,一直在等待...

最終會丟擲localhost未傳送任何資料的錯誤
error

如何你不想要終止請求-響應迴圈,總是記得通過next()傳遞request物件

如果你想要在中介軟體棧中跳過剩餘中介軟體,呼叫next('route')方法將控制權交給下一個路由

app.get('/user/:id',(req,res,next)=>{
    if(req.params.id==0) next('route')
    else next()
},(req,res,next)=>{
    // 渲染常規頁面
    res.render('regular')
})

// 處理/user/:id,渲染一個id為0的特殊頁面
app.get('/user/:id',(req,res,next)=>{
    res.render('special')
})
回到目錄

路由級中介軟體

路由級中介軟體和應用級中介軟體類似,只不過是它繫結物件為express.Router()

var router = express.Router()

路由級使用router.use()router.VERB()載入

舉個栗子

var app = express()
var router = express.Router()
// 沒有掛載路徑的中介軟體,通過該路由的每個請求都會執行該中介軟體
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
})

// 一箇中間件,顯示任何指向/user/:id的HTTP請求的資訊
router.use('/user/:id',(req,res,next)=>{
    console.log('Request URL',req.originalUrl)
    next()
},(req,res,next)=>{
    console.log('Request Type',req.method)
    next()
})

// 一箇中間件棧,處理指向/user/:id的GET請求
router.get('/user/:id',(req,res,next)=>{
    if(req.params.id == 0) next('router')
    else next()
},(req,res,next)=>{
    res.render('regular')
})

// 處理/user/:id,渲染一個特殊頁面
router.get('user/:id',(req,res,next)=>{
    console.log(req.params.id)
    res.render('special')
})

// 將路由掛載至應用
app.use('/',router)
回到目錄

錯誤處理中介軟體

錯誤處理中介軟體有四個引數,定義錯誤處理中介軟體必須使用這四個引數。即使不需要next物件,也必須在引數中宣告它,否者中介軟體會識別為一個常規中介軟體,不能處理錯誤

舉個栗子:

app.use((err,req,res,next)=>{
    console.error(err.stack)
    res.status(500).send('Something broke')
})

中介軟體返回的響應是隨意的,可以響應一個 HTML 錯誤頁面、一句簡單的話、一個 JSON 字串,或者其他任何您想要的東西。

所以你可能想要像處理常規中介軟體那樣,定義多個錯誤處理中介軟體
,比如您想為使用 XHR 的請求定義一個,還想為沒有使用的定義一個,那麼:

app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)

logErrors 將請求和錯誤資訊寫入標準錯誤輸出、日誌或者類似服務

functionlogErrors(err,req,res,next){
    console.error(err.stack)
    next(err)
}

clientErrorHandler 定義如下(這裡將錯誤直接傳給了next)

functionclientErrorHandler(err,req,res,next){
    if(req.xhr){
        res.status(500).send({error:'Something blew up!'})
    }else{
        next(err)
    }
}

errorHandler 捕獲所有錯誤

functionerrorHandler(err,req,res,next){
    res.status(500)
    res.render('error',{error:err})
}
回到目錄

內建中介軟體

從版本4.x開始,Express不再依賴Content,除了 express.static, Express 以前內建的中介軟體現在已經全部單獨作為模組安裝使用

express.static是 Express 唯一內建的中介軟體。
它基於 serve-static,負責在 Express 應用中提託管靜態資源。

可選options引數擁有如下屬性

屬性 描述 型別 預設值
dotfiles 是否對外輸出檔名以點(.)開頭的檔案。可選值為 “allow”、“deny” 和 “ignore” String "ignore"
etag 是否啟用etag生成 Boolean true
extensions 設定副檔名備份選項 Array [ ]
index 傳送目錄索引檔案,設定為 false 禁用目錄索引。 mixed "index.html"
lastModified 設定 Last-Modified 頭為檔案在作業系統上的最後修改日期 Boolean true
maxAge 毫秒或者其字串格式設定 Cache-Control 頭的 max-age 屬性 Number 0
redirect 當路徑為目錄時,重定向至"/" Boolean true
setHeaders 設定HTTP頭以提供檔案的函式 Function

下面的栗子使用了 express.static 中介軟體,其中的 options 物件經過了精心的設計。

var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
  }
}

app.use(express.static('public', options));

我們總是需要使用express.static指定多個靜態資原始檔,比如:

app.use(express.static('public'))
app.use(express.static('files'))
回到目錄

第三方中介軟體

通過使用第三方中介軟體從而為Express應用增加更多的功能
安裝所需功能的node模組,並在應用中載入,可以在應用級中載入,也可以在路由級中載入

舉個栗子

$ npm install cookie-parser
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')

// 載入用於解析cookie的中介軟體
app.use(cookieParser())