黑人生命也是命。
支持平等正義倡議.

使用中介軟體

Express 是一個路由和中介軟體網路架構,本身的功能極少:Express 應用程式基本上是一系列中介軟體函式呼叫。

中介軟體函式是可以存取 要求物件 (req)、回應物件 (res) 以及應用程式要求回應週期中下一個中介軟體函式的函式。下一個中介軟體函式通常以名為 next 的變數表示。

中介軟體函式可以執行下列工作

如果目前的 middleware 函式未結束請求-回應週期,它必須呼叫 next() 以將控制權傳遞給下一個 middleware 函式。否則,請求將會掛起。

Express 應用程式可以使用下列類型的 middleware

您可以載入具有選用掛載路徑的應用程式層級和路由器層級 middleware。您也可以同時載入一系列 middleware 函式,這會在掛載點建立 middleware 系統的子堆疊。

應用程式層級的 middleware

使用 app.use()app.METHOD() 函式將應用程式層級 middleware 繫結到 app 物件 的執行個體,其中 METHOD 是 middleware 函式處理的請求的 HTTP 方法(例如 GET、PUT 或 POST),以小寫表示。

此範例顯示沒有掛載路徑的 middleware 函式。當應用程式收到請求時,每次都會執行此函式。

const express = require('express')
const app = express()

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

此範例顯示掛載在 /user/:id 路徑上的 middleware 函式。此函式會在 /user/:id 路徑上針對任何類型的 HTTP 請求執行。

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

此範例顯示路由及其處理函式(middleware 系統)。此函式會處理對 /user/:id 路徑的 GET 請求。

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

以下是載入一系列 middleware 函式到具有掛載路徑的掛載點的範例。它說明了 middleware 子堆疊,會針對對 /user/:id 路徑的任何類型的 HTTP 請求列印請求資訊。

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

路由處理函式讓您能夠為路徑定義多個路由。下方的範例為對 /user/:id 路徑的 GET 請求定義兩個路由。第二個路由不會造成任何問題,但它永遠不會被呼叫,因為第一個路由會結束請求-回應週期。

此範例顯示處理對 /user/:id 路徑的 GET 請求的 middleware 子堆疊。

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

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

若要略過路由器中介軟體堆疊中其餘的中介軟體函式,請呼叫 next('route') 將控制權傳遞至下一個路由。注意:next('route') 僅會在使用 app.METHOD()router.METHOD() 函式載入的中介軟體函式中運作。

此範例顯示處理對 /user/:id 路徑的 GET 請求的 middleware 子堆疊。

app.get('/user/:id', (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()
}, (req, res, next) => {
  // send a regular response
  res.send('regular')
})

// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
  res.send('special')
})

中介軟體也可以宣告在陣列中,以利重複使用。

這個範例顯示一個陣列,其中包含一個中介軟體子堆疊,用於處理對 /user/:id 路徑的 GET 要求

function logOriginalUrl (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}

function logMethod (req, res, next) {
  console.log('Request Type:', req.method)
  next()
}

const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
  res.send('User Info')
})

路由器層級的 middleware

路由層級中介軟體的運作方式與應用程式層級中介軟體相同,但它會繫結至 express.Router() 的執行個體。

const router = express.Router()

使用 router.use()router.METHOD() 函式載入路由層級中介軟體。

下列範例程式碼使用路由層級中介軟體,複製上方顯示的應用程式層級中介軟體系統

const express = require('express')
const app = express()
const router = express.Router()

// a middleware function with no mount path. This code is executed for every request to the router
router.use((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', (req, res, next) => {
  console.log('Request URL:', req.originalUrl)
  next()
}, (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', (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()
}, (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', (req, res, next) => {
  console.log(req.params.id)
  res.render('special')
})

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

若要略過路由器的其餘中介軟體函式,請呼叫 next('router') 將控制權傳遞回路由器執行個體。

此範例顯示處理對 /user/:id 路徑的 GET 請求的 middleware 子堆疊。

const express = require('express')
const app = express()
const router = express.Router()

// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router')
  next()
})

router.get('/user/:id', (req, res) => {
  res.send('hello, user!')
})

// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401)
})

錯誤處理 middleware

錯誤處理中介軟體總是需要 四個 參數。您必須提供四個參數,才能將其識別為錯誤處理中介軟體函式。即使您不需要使用 next 物件,您也必須指定它,以維持簽章。否則,next 物件會被解釋為一般中介軟體,且無法處理錯誤。

定義錯誤處理中介軟體函式的步驟與其他中介軟體函式相同,但參數有四個而不是三個,特別是簽章為 (err, req, res, next))

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

有關錯誤處理中介軟體的詳細資訊,請參閱:錯誤處理

內建 middleware

從 4.x 版開始,Express 不再依賴 Connect。先前包含在 Express 中的中介軟體函式現在位於獨立的模組中;請參閱 中介軟體函式清單

Express 具有下列內建中介軟體函式

第三方 middleware

使用第三方中間件來為 Express 應用程式新增功能。

安裝 Node.js 模組以取得所需的功,然後在應用程式層級或路由器層級載入應用程式。

以下範例說明如何安裝和載入 cookie 剖析中間件函式 cookie-parser

$ npm install cookie-parser
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')

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

如需一般與 Express 搭配使用的第三方中間件函式部分清單,請參閱:第三方中間件