1. 程式人生 > >express裡的中介軟體

express裡的中介軟體

前言

vue-cli腳手架+webpack結合的時候,後臺用的是express框架搭建的簡單伺服器,包括熱載入等等,都用到了express中的中介軟體概念。

程式碼大概如下:

// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware) // serve pure static assets var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) app.use(staticPath, express.static('./static'))

上述的app.use()就是用中介軟體

從官方網站摘抄的筆記。

正文(使用中介軟體)

中介軟體(Middleware)是一個函式,它可以訪問請求物件,響應物件,和web應用中處於請求-響應迴圈中的中介軟體,一般被命名為next

的變數。

中介軟體的功能包括:

  • 執行任何程式碼
  • 修改請求和響應物件
  • 終結請求響應迴圈
  • 呼叫堆疊中的下一個中介軟體

如果當前中介軟體沒有終結請求-響應迴圈,則必須呼叫next()方法將控制權交給下一個中介軟體,否則請求就會掛起。

Express應用可使用如下幾種中介軟體:

使用可選擇掛載路徑,可在應用級別或路由級別裝載中介軟體。另外,還可以同時裝在一系列中介軟體函式,從而在一個掛載點上建立一個子中介軟體棧。

應用級中介軟體

應用級中介軟體繫結到 app 物件 使用 app.use() 和 app.METHOD(), 其中, METHOD 是需要處理的 HTTP 請求的方法,例如 GET, PUT, POST 等等,全部小寫。

例子

var app = express();

// 沒有掛載路徑的中介軟體,應用的每個請求都會執行該中介軟體
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// 掛載至 /user/:id 的中介軟體,任何指向 /user/:id 的請求都會執行它
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');
});

// 處理 /user/:id, 打印出使用者 id
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id);
});

如果需要在中介軟體棧中跳過剩餘中介軟體,呼叫 next(‘route’) 方法將控制權交給下一個路由。 注意: next(‘route’) 只對使用 app.VERB() 或 router.VERB() 載入的中介軟體有效。

// 一箇中間件棧,處理指向 /user/:id 的 GET 請求
app.get('/user/:id', function (req, res, next) {
  // 如果 user id 為 0, 跳到下一個路由
  if (req.params.id == 0) next('route');
  // 否則將控制權交給棧中下一個中介軟體
  else next(); //
}, function (req, res, next) {
  // 渲染常規頁面
  res.render('regular');
});

// 處理 /user/:id, 渲染一個特殊頁面
app.get('/user/:id', function (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', 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 請求
router.get('/user/:id', function (req, res, next) {
  // 如果 user id 為 0, 跳到下一個路由
  if (req.params.id == 0) next('route');
  // 負責將控制權交給棧中下一個中介軟體
  else next(); //
}, function (req, res, next) {
  // 渲染常規頁面
  res.render('regular');
});

// 處理 /user/:id, 渲染一個特殊頁面
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// 將路由掛載至應用
app.use('/', router);

錯誤處理中介軟體

錯誤處理中介軟體和其他中介軟體定義類似,只是要使用 4 個引數,而不是 3 個,其簽名如下: (err, req, res, next)。

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

內建中介軟體

express.static(root, [options])

引數root指提供靜態資源的根目錄。
可選的options引數擁有如下屬性。

屬性 描述 型別 預設值
dotfiles 是否對外輸出檔名以點(.)開頭的檔案。可選值為 “allow”、“deny” 和 “ignore” String “ignore”
etag 是否啟用 etag 生成 Boolean true
extensions 設定副檔名備份選項 Array []
index 傳送目錄索引檔案,設定為 false 禁用目錄索引。 Mixed “index.html”
lastModified 設定 Last-Modified 頭為檔案在作業系統上的最後修改日期。可能值為 truefalse Boolean true
maxAge 以毫秒或者其字串格式設定 Cache-Control 頭的 max-age 屬性。 Number 0
redirect 當路徑為目錄時,重定向至 “/”。 Boolean true
setHeaders 設定 HTTP 頭以提供檔案的函式。 Function
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 應用增加更多功能。

安裝所需功能的 node 模組,並在應用中載入,可以在應用級載入,也可以在路由級載入。

下面的例子安裝並載入了一個解析 cookie 的中介軟體: cookie-parser。

$ npm install cookie-parser

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

// 載入用於解析 cookie 的中介軟體
app.use(cookieParser());

原文連結