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.use
和app.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');
})
如果我們想要處理掛在至/user/:id
的中介軟體的GET請求,我們需要使用next()
將request
物件傳遞給下一個中介軟體
否者:
得不到下一個中介軟體處理的它,一直在等待...
最終會丟擲localhost未傳送任何資料的錯誤
如何你不想要終止請求-響應迴圈
,總是記得通過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())