Connect模塊解析 轉載

來自對《了不得的Node.js》一書的學習
Connect
Node.js爲常規的網絡應用提供了基本的API。然而,實際狀況下,絕大部分網絡應用都須要完成一系列相似的操做,這些相似的操做你必定不想每次都重複地基於原始的API去實現。
Connect是一個基於HTTP服務器的工具集,它提供了一種新的組織代碼的方式來與請求、響應對象進行交互,稱爲中間件(middleware)。
中間件具備代碼複用的好處。
案例
  需求:實現一個後臺服務,能響應瀏覽器請求站點目錄下的images下的.jpg圖片,並返回圖片。html

使用HTTP構建一個簡單的網站
建立server.js,實現該服務器的基本功能(解析請求的URL地址,根據不一樣的URL請求,對應不一樣的操做,如:請求.jpg圖片),代碼以下所示:
/**
* 模塊依賴
*/
var http = require('http'),
fs = require('fs');node

/**
* 建立服務器
*/
var server = http.createServer(function(req, res) {
// 檢查URL是否和服務器目錄下的文件匹配,若是匹配,則讀取該文件並展現出來
// 請求.jpg圖片
if('GET' == req.method
&& '/images' == req.url.substr(0, 7)
&& '.jpg' == req.url.substr(-4)) {
// 返回對應圖片
// ...web

} else if('GET' == req.method && '/' == req.url) {
// 發送html文件,默認請求index.html
// ...npm

} else {
// 處理其餘請求,返回404錯誤碼
res.writeHead(404);
res.end('Not found');
}json

});瀏覽器

server.listen(3000);

  接下來的任務,固然是完成處理對應的請求。
2. 首先是請求圖片時,使用fs.stat來檢查文件是否存在。這裏使用Node中的全局常量__dirname來獲取當前服務器所在的路徑。在服務器

// 返回對應圖片
1
代碼下,增長對應操做:網絡

fs.stat(__dirname + req.url, function(err, stat) {
// 若是檢查文件是否存在時發生錯誤,則終止進程併發送HTTP 404狀態碼告知沒法找到請求的圖片。
// 對於stat成功可是路徑所表示的並不是是文件時,也要作此處理。
if(err || !stat.isFile()) {
res.writeHead(404);
res.end('Not Found');
return;
}併發

// 發送圖片資源
});

  接下來解決的問題是,發送圖片資源或文件資源的問題,實際上也是服務器返回響應消息的問題。那麼想一想,如何返回呢?咱們須要設置響應消息的Content-Type頭信息,告訴瀏覽器,如今服務器將返回什麼類型的數據。
3. 對於返回圖片資源或文件資源的操做,區別只於在文件的路徑和Content-Type頭信息的不一樣而已,那麼能夠封裝爲以下方法:app

/**
* 根據文件路徑來獲取文件內容,並添加'Content-Type'頭信息
* @param {[type]} path 文件路徑
* @param {[type]} type Content-Type頭信息
* @return {[type]} [description]
*/
function server(path, type) {
res.writeHead(200, {'Content-Type': type});
fs.createReadStream(path).pipe(res);
}

  在對應 發送圖片資源 的註釋處,添加以下代碼:

// 發送圖片資源
serve(__dirname + req.url, 'application/jpg');

  在對應 發送html文件 的註釋處,添加以下代碼:

// 發送html文件,默認請求index.html
// ...
serve(__dirname + '/index.html', 'text/html');

  server.js完成!
4. 此外,補充一下 index.html 的內容:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用HTTP構建一個簡單的網站</title>
<style>
img {
width: 300px;
}
</style>
</head>
<body>
<h1>My website</h1>
<img src="./images/1.jpg" alt="1.jpg">
<img src="./images/2.jpg" alt="2.jpg">
<img src="./images/3.jpg" alt="3.jpg">
<img src="./images/4.jpg" alt="4.jpg">
</body>
</html>


  簡單的顯示4張圖片(其實對應的就是4個請求.jpg圖片資源的請求)。
5. 運行 node server.js,在瀏覽器中訪問 http://127.0.0.1:3000,就能看到剛實現的網站了!如:

  server.js的完整代碼以下:

/**
* 模塊依賴
*/
var http = require('http'),
fs = require('fs');

/**
* 建立服務器
*/
var server = http.createServer(function(req, res) {
// 檢查URL是否和服務器目錄下的文件匹配,若是匹配,則讀取該文件並展現出來
// 請求.jpg圖片
if('GET' == req.method
&& '/images' == req.url.substr(0, 7)
&& '.jpg' == req.url.substr(-4)) {
// 返回對應圖片
// ...
fs.stat(__dirname + req.url, function(err, stat) {
// 若是檢查文件是否存在時發生錯誤,則終止進程併發送HTTP 404狀態碼告知沒法找到請求的圖片。
// 對於stat成功可是路徑所表示的並不是是文件時,也要作此處理。
if(err || !stat.isFile()) {
res.writeHead(404);
res.end('Not Found');
return;
}

// 發送圖片資源
serve(__dirname + req.url, 'application/jpg');
});

} else if('GET' == req.method && '/' == req.url) {
// 發送html文件,默認請求index.html
// ...
// console.log(__dirname);
serve(__dirname + '/index.html', 'text/html');
} else {
// 處理其餘請求,返回404錯誤碼
res.writeHead(404);
res.end('Not found');
}


/**
* 根據文件路徑來獲取文件內容,並添加'Content-Type'頭信息
* @param {[type]} path 文件路徑
* @param {[type]} type Content-Type頭信息
* @return {[type]} [description]
*/
function serve(path, type) {
res.writeHead(200, {'Content-Type': type});
fs.createReadStream(path).pipe(res);
}
});

server.listen(3000);


經過Connect實現一個簡單的網站
  接下來這個例子是要實現一個網站,該例子展現了建立網站時一些常見的任務:
  - 託管靜態文件。
  - 處理錯誤以及損壞或者不存在的URL。
  - 處理不一樣類型的請求。
  基於http模塊API之上的Connect,提供了一些工具方法可以讓這些重複性的處理便於實現,以致於讓開發者可以更加專一在應用自己。
1. 初始化項目——npm init,建立package.json文件,並在其中聲明對「connect」模塊的依賴:

{
"name": "my-website",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"connect": "1.8.7"
}
}

  使用 npm install 命令安裝依賴。
2. 在server.js中使用use()方法來添加static中間件。(中間件是什麼呢?我也不清楚耶,快看到下一節了。中間件,其實就是一個簡單的JavaScript函數。)

/**
* 模塊依賴
*/
var connect = require('connect');

/**
* 建立服務器
*/
var server = connect.createServer();

/**
* 處理靜態文件
* 這裏,咱們配置static中間件——經過傳遞一些參數給connect.static方法,該方法自己會返回一個方法
* (被返回的方法應該是中間件吧~)
*/
server.use(connect.static(__dirname + '/website'));

server.listen(3000);

  運行 node server.js(啊?這就行了?!剛寫一堆,如今用了Connect模塊就幾行而已了?沒錯,是的)。試着在瀏覽器訪問,成功見到index.html的樣子了!那咱們訪問不存在的url呢(事實上,Connect會幫咱們處理404的狀況),例如,咱們能夠訪問 /test 來驗證。瀏覽器將顯示以下結果:

Cannot GET /test
1
  注:記得把index.html 和 images文件夾等靜態資源放置到項目目錄下的website文件夾下。

中間件
  在沒有使用中間件的狀況下,處理請求的這些代碼都放在一個簡單的事件處理器中(createServer的回調函數中),這將會是一個很是複雜的處理過程。而使用中間件後會將應用拆分爲更小單元(讓代碼有更強大的表達能力),還可以實現很好的重用性。
  如以前用HTTP方式所寫的應用,使用中間件模式能夠寫成這樣(固然這裏也仍然須要到Connect模塊啦) server-http.js:

/**
* 模塊依賴
*/
var connect = require('connect');
var fs = require('fs');
var serve =
/**
* 根據文件路徑來獲取文件內容,並添加'Content-Type'頭信息
* @param {[type]} path 文件路徑
* @param {[type]} type Content-Type頭信息
* @return {[type]} [description]
*/
function (res, fs, path, type) {
res.writeHead(200, {'Content-Type': type});
fs.createReadStream(path).pipe(res);
};

/**
* 建立服務器
*/
var server = connect.createServer();

server.use(function(req, res, next) {
// 檢查URL是否和服務器目錄下的文件匹配,若是匹配,則讀取該文件並展現出來
// 請求.jpg圖片
if('GET' == req.method
&& '/images' == req.url.substr(0, 7)
&& '.jpg' == req.url.substr(-4)) {
// 返回對應圖片
// ...
fs.stat(__dirname + req.url, function(err, stat) {
// 若是檢查文件是否存在時發生錯誤,則終止進程併發送HTTP 404狀態碼告知沒法找到請求的圖片。
// 對於stat成功可是路徑所表示的並不是是文件時,也要作此處理。
if(err || !stat.isFile()) {
res.writeHead(404);
res.end('Not Found');
return;
}

// 發送圖片資源
serve(res, __dirname + '/website' + req.url, 'application/jpg');
});

} else {
// 交給其餘的中間件去處理
next();
}
});

server.use(function(req, res, next) {
if('GET' == req.method && '/' == req.url) {
// 發送html文件,默認請求index.html
// ...
// console.log(__dirname);
serve(res, __dirname + '/website/index.html', 'text/html');
} else {
// 交給其餘的中間件去處理
next();
}
});

server.use(function(req, res, next) { // 處理其餘請求,返回404錯誤碼 res.writeHead(404); res.end('Not found');});

相關文章
相關標籤/搜索