StrongLoop 提供的 Express 和 Node.js 訓練課程

這個翻譯StrongLoop / IBM提供.

相對於英文版說明文件,本文件可能已不合時宜。如需最新的更新,請參閱英文版說明文件

使用中介軟體

Express 是一個本身功能極簡的路由與中介軟體 Web 架構:本質上,Express 應用程式是一系列的中介軟體函數呼叫。

中介軟體函數是一些有權存取要求物件 (req)、回應物件 (res) 和應用程式要求/回應循環中之下一個中介軟體函數的函數。下一個中介軟體函數通常以名為 next 的變數表示。

中介軟體函數可以執行下列作業:

如果現行中介軟體函數不會結束要求/回應循環,它必須呼叫 next(),以便將控制權傳遞給下一個中介軟體函數。否則,要求將會停擺。

Express 應用程式可以使用下列類型的中介軟體:

您可以使用選用的裝載路徑,來載入應用程式層次的中介軟體和路由器層次的中介軟體。您也可以一併載入一系列的中介軟體函數,如此會在裝載點建立一個中介軟體系統子堆疊。

應用程式層次的中介軟體

使用 app.use()app.METHOD() 函數,將應用程式層次的中介軟體連結至 app object 實例,其中 METHOD 是中介軟體函數要處理的 HTTP 要求方法(例如 GET、PUT 或 POST),並採小寫。

本例顯示沒有裝載路徑的中介軟體函數。每當應用程式收到要求時,就會執行此函數。


var app = express();

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

本例顯示裝載在 /user/:id 路徑的中介軟體函數。會對 /user/:id 路徑上任何類型的 HTTP 要求,執行此函數。


app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

本例顯示路由和其處理程式函數(中介軟體系統)。此函數會處理指向 /user/:id 路徑的 GET 要求。


app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

下列範例顯示使用裝載路徑在裝載點載入一系列中介軟體函數。其中說明中介軟體子堆疊,這個子堆疊會針對指向 /user/:id 路徑之任何類型的 HTTP 要求,列印其要求資訊。


app.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

路由處理程式可讓您為一個路徑定義多個路由。下列範例為指向 /user/:id 路徑的 GET 要求,定義兩個路由。第二個路由不會造成任何問題,卻絕不會呼叫,因為第一個路由會結束要求/回應循環。

本例顯示中介軟體子堆疊,它處理了指向 /user/:id 路徑的 GET 要求。


app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id);
  next();
}, function (req, res, next) {
  res.send('User Info');
});

// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id);
});

如果要跳過路由器中介軟體堆疊中其餘的中介軟體函數,請呼叫 next('route'),將控制權傳遞給下一個路由。附註next('route') 只適用於使用 app.METHOD()router.METHOD() 函數載入的中介軟體函數。

本例顯示中介軟體子堆疊,它處理了指向 /user/:id 路徑的 GET 要求。


app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id == 0) next('route');
  // otherwise pass the control to the next middleware function in this stack
  else next(); //
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
  res.render('special');
});

路由器層次的中介軟體

路由器層次的中介軟體的運作方式如同應用程式層次的中介軟體,不同之處在於它會連結至 express.Router() 實例。


var router = express.Router();

請利用 router.use()router.METHOD() 函數來載入路由器層次的中介軟體。

下列的程式碼範例是使用路由器層次的中介軟體,抄寫上述針對應用程式層次的中介軟體顯示的中介軟體系統:


var app = express();
var router = express.Router();

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next router
  if (req.params.id == 0) next('route');
  // otherwise pass control to the next middleware function in this stack
  else next(); //
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// mount the router on the app
app.use('/', router);

錯誤處理中介軟體

錯誤處理中介軟體一律會使用四個引數。您必須提供這四個引數,將它識別為錯誤處理中介軟體函數。即使您不需要使用 next 物件也必須指定,以維護簽章。否則,會將 next 物件解譯為一般中介軟體,而無法處理錯誤。

錯誤處理中介軟體函數的定義方式,與其他中介軟體函數相同,差別在於引數是四個而非三個,具體來說,就是使用 (err, req, res, next)) 簽章:


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

如需錯誤處理中介軟體的詳細資料,請參閱:錯誤處理

內建中介軟體

從 4.x 版起,Express 不再相依於 Connect。除了 express.static,Express 先前隨附的所有中介軟體函數現在位於個別的模組中。請檢視中介軟體函數清單

express.static(root, [options])

Express 唯一的內建中介軟體函數是 express.static。此函數以 serve-static 為基礎,負責在 Express 應用程式中提供靜態資產。

root 引數指定提供靜態資產的根目錄。

options 選用物件可具有下列內容:

內容 說明 類型 預設值
dotfiles 用來提供點檔案的選項。可能的值是 “allow”、”deny” 和 “ignore” 字串 “ignore”
etag 啟用或停用 etag 的產生 布林 true
extensions 設定副檔名遞補。 陣列 []
index 傳送目錄索引檔。設定 false,會停用目錄檢索。 混合 “index.html”
lastModified Last-Modified 標頭設為作業系統上檔案的前次修改日期。可能的值是 truefalse 布林 true
maxAge 設定 Cache-Control 標頭的 max-age 內容,以毫秒為單位或 ms 格式的字串 數字 0
redirect 當路徑名稱是目錄時,重新導向至尾端 “/”。 布林 true
setHeaders 用來設定 HTTP 標頭以提供檔案的函數。 函數  

下列範例顯示如何使用 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));

每一個應用程式可有多個靜態目錄:


app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));

如需 serve-static 函數和其選項的詳細資料,請參閱 serve-static 說明文件。

協力廠商中介軟體

使用協力廠商中介軟體,在 Express 應用程式中新增功能。

針對必要的功能安裝 Node.js 模組,然後在應用程式層次或路由器層次將它載入到您的應用程式中。

下列範例說明如何安裝和載入用來剖析 Cookie 的中介軟體函數 cookie-parser


$ npm install cookie-parser


var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

// load the cookie-parsing middleware
app.use(cookieParser());

如需 Express 中常用的部分協力廠商中介軟體函數清單,請參閱:協力廠商中介軟體