使用中介軟體管理要求生命週期

已完成

Tailwind Traders 想要保護其Web API。 在某些情況下,當要求到達 Web 應用程式時,您可能需要驗證:

  • 驗證:用戶是誰
  • 授權:允許使用者查看或執行哪些動作

要求步驟

請將要求視為一系列步驟來處理。 若使用者必須登入才能處理資源,則步驟可能如下:

  1. 前置處理:在處理要求之前執行程式碼的選擇性步驟。

    例如,判斷使用者是否透過要求標頭傳送適當的認證。 如果認證通過驗證,則將要求送至下一個步驟。 如果記錄失敗,伺服器會傳回 401 HTTP 回應。

  2. 處理:處理要求,例如與某種資料來源 (像是資料庫或 API 端點) 通訊。

    當要求正確要求資源時,這個步驟即會傳回資源。

  3. 後置處理:要求完成之後執行程式碼的選擇性步驟。

    例如,記錄結果以用於監視目的。

Express 架構內建處理這類要求的支援。 若要執行要求的前置處理或後置處理,請使用下列語法格式,在 Express app 對象上實use()作 方法:

app.use((req, res, next) => {})

傳遞至 use() 方法的方法具有下列參數:

  • req:包含要求標頭和呼叫 URL 的傳入要求。 若用戶端使用其要求傳送資料,其中也會包含資料主體。
  • res:回應串流,用於寫入您想要傳回呼叫用戶端的資訊 (例如標頭與資料)。
  • next:堆疊中的下一個中間件函式。 如果未呼叫 函 next() 式,則要求處理會停止。 如果要求成功,您可能會想要呼叫 next() 來變更回應或記錄結果。

要求管線

如果您有受益於前置或後置處理中間件的路由,請在原始程式碼檔案中設定函式,以便:

  • 在實際要求之前定義需要在要求之前執行的中介軟體 (前置處理)。
  • 在實際要求之後定義需要在要求之後執行的中介軟體 (後置處理)。

請查看本範例:

app.use((req, res, next) => {
  // Pre request
})
app.get('/protected-resource', () => {
  // Handle the actual request
})
app.use((req, res, next) => {
  // Post request
})

app.get('/login', () => {})

您也可以將前置處理中介軟體作為要求處理常式的引數執行:

app.get(
  '/<some route>',
 () => {
   // Pre request middleware
 }, () => {
   // Handle the actual request
 })

Express.js 中的中間件函式順序非常重要,因為它們會依程式代碼中定義的順序循序執行。 這表示如果中間件函式放在路由處理程序之後,就不會針對該路由執行。

路由管理最佳做法

以下是管理中間件函式順序的一些最佳做法:

  • 將全域中間件放在最上方:套用至所有路由的中間件函式應該放在程式代碼的頂端,再放置於任何路由處理程式。 這可確保會針對每個要求執行它們。

  • 依特定性排序中間件:應將更特定的中間件函式放在較一般函式之後。 如此一來,一般中間件函式可以處理所有路由的一般工作,而特定中間件函式可以處理特定路由的工作。

  • 最後放置錯誤處理中間件:具有四個自變數的中間件函式會被視為錯誤處理中間件。 它們應該放在中間件堆疊的結尾,所有其他中間件和路由處理程序之後。

以下是範例:

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

// Global middleware
app.use((req, res, next) => {
  console.log('This is a global middleware');
  next();
});

// Route handler
app.get('/', (req, res, next) => {
  console.log('This is a route handler');
  next();
});

// Specific middleware
app.use((req, res, next) => {
  console.log('This is a specific middleware');
  next();
});

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

app.listen(3000);