??
這一章是《Node.js 實戰(zhàn)》筆記薇宠,但是書中的源碼實現(xiàn)與官方文檔有出入,Connect “自帶”的中間件好像是需要單個獨立導(dǎo)入才能使用。
以下僅作為記錄岂座,實際項目使用待研究驗證。
Connect 自帶的中間件
Connect 自帶的中間件可以滿足常見的Web程序開發(fā)需求:
- 會話管理杭措;
- cookie 解析费什;
- 請求主體解析
- 請求日志
- ...
下面的這些中間件是獨立呈現(xiàn)的,需要npm單獨導(dǎo)入
解析 cookie手素、請求主體和查詢字符串的中間件
cookieParser():解析HTTP cookie
Connect 的 cookie 解析器支持常規(guī)cookie鸳址、簽名cookie和特殊的JSON cookie。
req.cookies默認(rèn)是用常規(guī)未簽名cookie組裝而成的泉懦。如果你想支持session()中間件要求的簽名cookie稿黍,在創(chuàng)建cookieParser()實例時要傳入一個加密用的字符串。
const connect = require('connect');
// 作為參數(shù)傳給cookieParser()的秘鑰用來對cookie簽名和解簽
var app = connect()
.use(connect.cookieParser('tobi is a cook ferret'))
.use(function (req, res) {
console.log(req.cookies);
console.log(req.signedCookies);
res.end('hello\n');
})
.listen(3000);
// 不帶cookie
// curl http://localhost:3000/
// 常規(guī)cookie
// curl http://localhost:3000/ -H "Cookie: foo=bar, bar=baz"
簽名cookie
簽名cookie更適合敏感數(shù)據(jù)崩哩,因為用它可以驗證cookie數(shù)據(jù)的完整性巡球,有助于防止中間人攻擊。有效的簽名cookie放在req.signedCookies對象中邓嘹。
假設(shè)你設(shè)定了一個鍵為name辕漂,值為luna的簽名cookie。cookieParser會將cookie編碼為luna.PQLM0wNvqOQEObZXUkWbS5m6Wlg吴超。每個請求中的哈希值都會檢查钉嘹,如果cookie完好無損地傳上來,它會被解析為req.signedCookies.name:
JSON cookie
特別的JSON cookie帶有前綴j:鲸阻,告訴Connect它是一個串行化的JSON跋涣。 JSON cookie既可以是簽名的缨睡,也可以是未簽名的。
curl http://localhost:3000/ -H 'Cookie: foo=bar, bar=j:{"foo":"bar"}'
設(shè)定出站cookie
cookieParser() 中間件沒有提供任何通過 Set-Cookie 響應(yīng)頭向HTTP客戶端寫出站cookie的功能陈辱。但Connect可以通過 res.setHeader()函數(shù)寫入多個Set-Cookie響應(yīng)頭奖年。
const connect = require('connect');
var app = connect()
.use(function (req, res) {
res.setHeader('Set-Cookie', 'foo=bar'); // 設(shè)定cookie:foo=bar
res.setHeader('Set-Cookie', 'tobi=ferret; Expires=Tue, 08 Jun 2021 10:18:14 GMT'); // 設(shè)定cookie有效期
res.end();
}).listen(3000);
// curl http://localhost:3000/ --head
bodyParser():解析請求主體
bodyParser() 組件為你提供了req.body 屬性,可以用來解析 JSON沛贪、x-www-form-urlencoded 和multipart/form-data請求陋守。如果是 multipart/form-data 請求,比如文件上傳利赋,則還有req.files 對象水评。
var app = connect()
.use(connect.bodyParser())
.use(function(req, res) {
// ...注冊用戶
res.end('Registered new user: ' + req.body.username);
}).listen(3000);
因為 bodyParser() 是根據(jù) Content-Type 解析數(shù)據(jù)的,輸入形式是抽象的媚送,所以你的程序中只需要關(guān)心req.body數(shù)據(jù)對象的結(jié)果中燥。
limit():請求主體的限制
目的:幫助過濾巨型的請求。
query():查詢字符串解析
- bodyParser():解析 POST 請求
- query():解析 GET 請求塘偎。
query中間件可以將請求發(fā)送過來的查詢字符串以JSON格式作為響應(yīng)返回去疗涉。
實現(xiàn) Web 程序核心功能的中間件
- logger():提供靈活的請求日志;
- favicon():幫你處理/favicon.ico請求(favicon 是網(wǎng)站的小圖標(biāo));
- methodOverride():讓沒有能力的客戶端透明地重寫req.method;
- vhost():在一個服務(wù)器上設(shè)置多個網(wǎng)站(虛擬主機);
- session():管理會話數(shù)據(jù)。
處理 Web 程序安全的中間件
- basicAuth():為保護(hù)數(shù)據(jù)提供了HTTP基本認(rèn)證;
- csrf():實現(xiàn)對跨站請求偽造(CSRF)攻擊的防護(hù);
- errorhandler():幫你在開發(fā)過程中進(jìn)行調(diào)試吟秩。
提供靜態(tài)文件服務(wù)的中間件
- static():將文件系統(tǒng)中給定根目錄下的文件返回給客戶端;
- compress():壓縮響應(yīng)咱扣,很適合跟static()一起使用;
- directory():當(dāng)請求的是目錄時,返回那個目錄的列表涵防。