希望大家能夠堅持看下去我這系列的文章,這也是對我的最大的鼓勵與支持,讓我們共同進步,以文會友,相互幫助。好了直接進入今天的主題,
什麼是“Connect”,中間件又當如何理解,帶著問題來看今天的文章。
如何理解 "中間件" ?
我的理解是這樣的,中間件就是類似於一個過濾器的東西,在客戶端和應用程序之間的一個處理請求和響應的的方法。
如果把一個http處理過程比作是污水處理,中間件就像是一層層的過濾網。每個中間件在http處理過程中通過改寫request或(和)response的數據,
狀態,實現了特定的功能。
什麼是 ”Connect“ ?
我們可以把Connec看做一堆中間件的集合。對於每一次請求,Connect將會使用中間件層來過濾請求,其中每一個中間件都可以獲取HTTP請求。
T.J Holowaychuk談到Connect時,他說一共有兩種類型的中間件。其中一種是過濾器:
過濾器處理請求,但是他們並不針對請求進行回應(想想服務器日志)。
第二種類型是供應器,它會針對請求進行回應,你可以根據你的需求使用多個中間件,Http請求將會通過每一個中間件直到其中一個中間件對請求進行回應。
二,Connect內置中間件介紹
下面列舉出幾個主要的中間件,並且實例講述:
(1),cookieParser------cookie解析中間件,解析Cookies的頭通過req.cookies得到cookies。還可以通過req.secret加密cookies。
代碼如下:
var connect = require('./lib/connect') ;
var app = connect()
.use(connect.cookieParser('secret string'))
.use(function (req,res,next){
req.cookies.website="hi,i am bigbear !" ;
res.end(JSON.stringify(req.cookies)) ;
}).listen(8888) ;
(2),session
描述:會話管理中間件
依賴:cookieParser
參數:options
options:
key:Cookies名,默認值為connect.sid
store: session存儲實例
secret: session的cookie加密
cookie: session的cookie配置,默認值為{path: ‘/', httpOnly: true, maxAge: null}
proxy:安全cookie的反向代理,通過x-forwarded-proto實現
Cookie option:
cookie.maxAge: 默認值null,表示當浏覽器關閉後cookie被刪除。
代碼如下:
var connect = require('./lib/connect');
var app = connect()
.use(connect.logger('dev'))
.use(connect.cookieParser())
.use(connect.session({secret: '123', cookie: { maxAge: 60000 }}))
.use(function (req, res, next) {
if(req.session.pv){
res.setHeader('Content-Type', 'text/html');
res.write('views: ' + req.session.pv);
res.end();
req.session.pv++;
}else{
req.session.pv = 1;
res.end('Refresh');
}
})
.listen(8888);
隨著客戶端不斷刷新頁面 "PV" 會不斷增加,服務器端 “Session” 維護數量 。
(3),bodyParser------請求內容解析中間件,支持多種類型application/json,application/x-www-form-urlencoded, multipart/form-data。
代碼如下:
var connect = require('connect');
var app = connect()
.use(connect.bodyParser())
.use(function(req, res) {
res.end('req.body=>' + JSON.stringify(req.body));
})
.listen(8888);
三,再來個對比實例,看看使用中間件的好處。
代碼如下:
/*
* 使用connect實現的靜態文件處理
*/
var connect = require('connect');
connect(connect.static(__dirname + '/public')).listen(//監聽
8888,
function() {
console.log('Connect started on port 8888');
}
);
/*
* 使用node原生api實現
*/
var http = require('http');
http.createServer(
function(req, res) {
var url = require('url');
var fs = require('fs');
var pathname = __dirname + '/public' + url.parse(req.url).pathname;
//讀取本地文件
fs.readFile(
pathname,
function(err, data) {
//異常處理
if (err) {
res.writeHead(500);
res.end('500');
}
else {
res.end(data);
}
}
);
}
).listen(//監聽
8888,
function() {
console.log('Http Server started on port 8888');
}
);
盡管node原生api已經花費這麼些行代碼,但其實仍然留下一個簡單靜態文件服務器的諸多方面未經處理,
比如:404等異常未處理、沒有基本的文件路徑安全驗證(實際上我們可以訪問到整個os文件系統)、全局異常處理等等;
與此同時connect已經將這些問題都處理好了。
四,總結一下
(1),理解中間件流式處理。
代碼如下:
var app = connect();
app.use(connect.staticCache());
app.use(connect.static(__dirname + '/public'));
app.use(connect.cookieParser());
app.use(connect.session());
app.use(connect.query());
app.use(connect.bodyParser());
app.use(connect.csrf());
app.use(function (req, res, next) {
// 中間件
});
app.listen(8888);
(2),原生實現方式與中間件實現之間的差異化。
(3),通過上述的幾個中間件例子,理解用途和使用場景並且參考相關文檔掌握其余中間件的基本使用。