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

5.x API

注意:這是早期 beta 文件,可能不完整且仍在開發中。

express()

建立一個 Express 應用程式。express() 函式是由 express 模組匯出的頂層函式。

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

方法

express.json([options])

這是 Express 中的內建中間件函式。它會剖析具有 JSON 酬載的傳入請求,並根據 body-parser 建立。

傳回只會剖析 JSON 且只會查看 Content-Type 標頭與 type 選項相符的請求的中間件。此剖析器接受主體的任何 Unicode 編碼,並支援自動膨脹 gzipdeflate 編碼。

剖析後,會在 request 物件上建立一個包含剖析資料的新 body 物件(即 req.body),或一個空物件({}),如果沒有主體可剖析、Content-Type 不相符,或發生錯誤。

由於 req.body 的形狀基於使用者控制的輸入,此物件中的所有屬性和值都是不可信的,在信任之前應先驗證。例如,req.body.foo.toString() 可能會以多種方式失敗,例如 foo 可能不存在或不是字串,而 toString 可能不是函式,而是字串或其他使用者輸入。

下表說明選用 options 物件的屬性。

屬性 說明 類型 預設值
inflate 啟用或停用處理已壓縮 (壓縮) 的主體;停用時,將拒絕已壓縮的主體。 布林值 true
limit 控制最大要求主體大小。如果這是一個數字,則該值指定位元組數;如果它是一個字串,則該值會傳遞給 bytes 函式庫以進行剖析。 混合 "100kb"
reviver reviver 選項會直接傳遞給 JSON.parse 作為第二個引數。您可以在 MDN 關於 JSON.parse 的文件 中找到有關此引數的更多資訊。 函式 null
strict 啟用或停用僅接受陣列和物件;停用時將接受 JSON.parse 接受的任何內容。 布林值 true
type 這用於確定中間軟體將剖析哪種類型的媒體。此選項可以是字串、字串陣列或函式。如果不是函式,type 選項會直接傳遞給 type-is 函式庫,這可以是副檔名 (例如 json)、MIME 類型 (例如 application/json) 或具有萬用字元的 MIME 類型 (例如 */**/json)。如果是一個函式,type 選項會以 fn(req) 的形式呼叫,如果它傳回真值,則會剖析要求。 混合 "application/json"
verify 如果提供此選項,它會以 verify(req, res, buf, encoding) 的形式呼叫,其中 buf 是原始要求主體的 Buffer,而 encoding 是要求的編碼。剖析可以透過擲回錯誤來中止。 函式 未定義

express.static(root, [options])

這是 Express 中內建的中間件函式。它提供靜態檔案,並基於 serve-static

注意:為獲得最佳結果,使用反向代理快取來改善提供靜態資源的效能。

root 參數指定提供靜態資源的根目錄。此函式會將 req.url 與提供的 root 目錄結合,來決定要提供的檔案。找不到檔案時,它不會傳送 404 回應,而是呼叫 next() 來移至下一個中間件,允許堆疊和後備。

下表說明 options 物件的屬性。另請參閱以下範例

屬性 說明 類型 預設值
dotfiles 決定如何處理點檔(以點「.」開頭的檔案或目錄)。

請參閱以下的 dotfiles
字串 「忽略」
etag 啟用或停用 etag 產生

注意:express.static 始終傳送弱 ETag。
布林值 true
extensions 設定檔案副檔名後備:如果找不到檔案,則搜尋具有指定副檔名的檔案,並提供找到的第一個檔案。範例:['html', 'htm'] 混合 false
fallthrough 讓用戶端錯誤作為未處理的請求而後續處理,否則轉送用戶端錯誤。

請參閱以下的 fallthrough
布林值 true
immutable Cache-Control 回應標頭中啟用或停用 immutable 指令。如果啟用,也應指定 maxAge 選項以啟用快取。immutable 指令將防止受支援的用戶端在 maxAge 選項的生命週期內提出條件式請求,以檢查檔案是否已變更。 布林值 false
index 傳送指定的目錄索引檔案。設定為 false 以停用目錄索引。 混合 「index.html」
lastModified Last-Modified 標頭設定為檔案在作業系統上的最後修改日期。 布林值 true
maxAge 以毫秒數或 ms 格式 的字串設定 Cache-Control 標頭的 max-age 屬性。 數字 0
redirect 當路徑名稱為目錄時,重新導向至尾端的「/」。 布林值 true
setHeaders 用於設定 HTTP 標頭以與檔案一起提供服務的函式。

請參閱下方的 setHeaders
函式  

如需更多資訊,請參閱 在 Express 中提供靜態檔案使用中間件 - 內建中間件

dotfiles

此選項可用的值為

  • 「allow」- 不對點檔進行特殊處理。
  • 「deny」- 拒絕點檔要求,回應 403,然後呼叫 next()
  • 「ignore」- 就像點檔不存在一樣,回應 404,然後呼叫 next()
fallthrough

當此選項為 true 時,用戶端錯誤(例如錯誤要求或對不存在檔案的要求)將導致此中間件僅呼叫 next() 以呼叫堆疊中的下一個中間件。為 false 時,這些錯誤(甚至 404)將呼叫 next(err)

將此選項設定為 true,這樣您就可以將多個實體目錄對應到同一個網路地址,或讓路由填入不存在的檔案。

如果您已將此中間件掛載在專門設計為單一檔案系統目錄的路徑上,請使用 false,這允許短路 404 以減少負擔。此中間件也會回應所有方法。

setHeaders

對於此選項,請指定一個函式來設定自訂回應標頭。必須同步變更標頭。

函式的簽章為

fn(res, path, stat)

引數

  • res回應物件
  • path,正在傳送的檔案路徑。
  • stat,正在傳送的檔案的 stat 物件。

express.static 的範例

以下是使用 express.static 中間件函式搭配詳細選項物件的範例

const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders (res, path, stat) {
    res.set('x-timestamp', Date.now())
  }
}

app.use(express.static('public', options))

express.Router([options])

建立新的 路由器 物件。

const router = express.Router([options])

可選的 options 參數會指定路由器的行為。

屬性 說明 預設值 可用性
caseSensitive 啟用大小寫敏感性。 預設為停用,將「/Foo」和「/foo」視為相同。  
mergeParams 保留父路由的 req.params 值。如果父路由和子路由有衝突的參數名稱,則子路由的值優先。 false 4.5.0+
strict 啟用嚴格路由。 預設為停用,路由器會將「/foo」和「/foo/」視為相同。  

您可以將中間件和 HTTP 方法路由 (例如 getputpost 等) 加入 router,就像加入應用程式一樣。

如需更多資訊,請參閱 Router

express.urlencoded([options])

這是 Express 中內建的中間件函式。它會剖析帶有 urlencoded 酬載的傳入要求,並根據 body-parser 建立。

傳回只會剖析 urlencoded 主體,且只會查看 Content-Type 標頭與 type 選項相符的要求的中間件。此剖析器只接受主體的 UTF-8 編碼,並支援自動膨脹 gzipdeflate 編碼。

在中間件 (即 req.body) 之後,會在 request 物件上建立一個包含剖析資料的新 body 物件,或者如果沒有要剖析的主體、Content-Type 不相符,或發生錯誤,則會建立一個空物件 ({})。此物件將包含鍵值對,其中值可以是字串或陣列 (當 extendedfalse 時),或任何類型 (當 extendedtrue 時)。

由於 req.body 的形狀基於使用者控制的輸入,此物件中的所有屬性和值都是不可信的,在信任之前應先驗證。例如,req.body.foo.toString() 可能會以多種方式失敗,例如 foo 可能不存在或不是字串,而 toString 可能不是函式,而是字串或其他使用者輸入。

下表說明選用 options 物件的屬性。

屬性 說明 類型 預設值
extended 這個選項允許在使用 querystring 函式庫(當 false)或 qs 函式庫(當 true)來解析 URL 編碼資料之間進行選擇。「延伸」語法允許將豐富的物件和陣列編碼成 URL 編碼格式,讓 URL 編碼擁有類似 JSON 的體驗。如需更多資訊,請 參閱 qs 函式庫 布林值 false
inflate 啟用或停用處理已壓縮 (壓縮) 的主體;停用時,將拒絕已壓縮的主體。 布林值 true
limit 控制最大要求主體大小。如果這是一個數字,則該值指定位元組數;如果它是一個字串,則該值會傳遞給 bytes 函式庫以進行剖析。 混合 "100kb"
parameterLimit 這個選項控制 URL 編碼資料中允許的最大參數數目。如果請求包含超過此值的參數,將會產生錯誤。 數字 1000
type 這用於確定中間軟體將解析哪種類型的媒體。這個選項可以是字串、字串陣列或函式。如果非函式,type 選項會直接傳遞給 type-is 函式庫,這可以是副檔名(例如 urlencoded)、MIME 類型(例如 application/x-www-form-urlencoded)或具有萬用字元的 MIME 類型(例如 */x-www-form-urlencoded)。如果為函式,type 選項會以 fn(req) 呼叫,如果回傳真值,則會解析請求。 混合 "application/x-www-form-urlencoded"
verify 如果提供此選項,它會以 verify(req, res, buf, encoding) 的形式呼叫,其中 buf 是原始要求主體的 Buffer,而 encoding 是要求的編碼。剖析可以透過擲回錯誤來中止。 函式 未定義

應用程式

app 物件通常表示 Express 應用程式。透過呼叫 Express 模組所匯出的頂層 express() 函式來建立它

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

app.get('/', (req, res) => {
  res.send('hello world')
})

app.listen(3000)

app 物件有下列方法:

它也具有影響應用程式行為的設定(屬性);如需詳細資訊,請參閱 應用程式設定

Express 應用程式物件可以從 request 物件response 物件 分別作為 req.appres.app 參照。

屬性

app.locals

app.locals 物件具有應用程式內部局部變數的屬性,而且會在使用 res.render 呈現的範本中提供。

console.dir(app.locals.title)
// => 'My App'

console.dir(app.locals.email)
// => 'me@myapp.com'

設定後,app.locals 屬性的值會在應用程式的生命週期中持續存在,這與僅在要求的生命週期中有效的 res.locals 屬性相反。

您可以在應用程式內呈現的範本中存取局部變數。這對於提供範本的輔助函式,以及應用程式層級資料很有用。局部變數可透過 req.app.locals 在中間軟體中存取(請參閱 req.app

app.locals.title = 'My App'
app.locals.strftime = require('strftime')
app.locals.email = 'me@myapp.com'

app.mountpath

app.mountpath 屬性包含一個或多個子應用程式已掛載的路徑模式。

子應用程式是 express 的執行個體,可用於處理對路由的要求。

const express = require('express')

const app = express() // the main app
const admin = express() // the sub app

admin.get('/', (req, res) => {
  console.log(admin.mountpath) // /admin
  res.send('Admin Homepage')
})

app.use('/admin', admin) // mount the sub app

它類似於 req 物件的 baseUrl 屬性,但 req.baseUrl 會傳回符合的 URL 路徑,而不是符合的模式。

如果子應用程式掛載在多個路徑模式上,app.mountpath 會傳回它已掛載的模式清單,如下面的範例所示。

const admin = express()

admin.get('/', (req, res) => {
  console.log(admin.mountpath) // [ '/adm*n', '/manager' ]
  res.send('Admin Homepage')
})

const secret = express()
secret.get('/', (req, res) => {
  console.log(secret.mountpath) // /secr*t
  res.send('Admin Secret')
})

admin.use('/secr*t', secret) // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin) // load the 'admin' router on '/adm*n' and '/manager', on the parent app

app.router

應用程式內建的路由器執行個體。這是延遲建立的,在第一次存取時。

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

router.get('/', (req, res) => {
  res.send('hello world')
})

app.listen(3000)

您可以將中間軟體和 HTTP 方法路由新增到 router,就像應用程式一樣。

如需更多資訊,請參閱 Router

事件

app.on('mount', callback(parent))

當子應用程式掛載在父應用程式上時,mount 事件會在子應用程式上觸發。父應用程式會傳遞給 callback 函式。

注意

子應用程式會

  • 不會繼承具有預設值的設定值。您必須在子應用程式中設定值。
  • 繼承沒有預設值的設定值。

詳細資訊,請參閱 應用程式設定

const admin = express()

admin.on('mount', (parent) => {
  console.log('Admin Mounted')
  console.log(parent) // refers to the parent app
})

admin.get('/', (req, res) => {
  res.send('Admin Homepage')
})

app.use('/admin', admin)

方法

app.all(path, callback [, callback ...])

此方法類似標準 app.METHOD() 方法,但它符合所有 HTTP 動詞。

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

範例

以下回呼函式會執行對 /secret 的要求,無論是使用 GET、POST、PUT、DELETE 或任何其他 HTTP 要求方法

app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

app.all() 方法對於特定路徑字首或任意比對的「全域」邏輯對應很有用。例如,如果您將下列程式碼放在所有其他路由定義的最上方,則表示從該點開始的所有路由都需要驗證,並自動載入使用者。請記住,這些回呼不必作為終端點:loadUser 可以執行一項工作,然後呼叫 next() 以繼續比對後續路由。

app.all('*', requireAuthentication, loadUser)

或等效於

app.all('*', requireAuthentication)
app.all('*', loadUser)

另一個範例是白名單「全域」功能。範例類似於上述範例,但只限制以「/api」開頭的路徑

app.all('/api/*', requireAuthentication)

app.delete(path, callback [, callback ...])

使用指定的回呼函式將 HTTP DELETE 要求路由到指定的 path。如需更多資訊,請參閱 路由指南

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

範例

app.delete('/', (req, res) => {
  res.send('DELETE request to homepage')
})

app.disable(name)

將布林設定 name 設為 false,其中 name應用程式設定表格 中的其中一個屬性。對於布林屬性,呼叫 app.set('foo', false) 等同於呼叫 app.disable('foo')

例如

app.disable('trust proxy')
app.get('trust proxy')
// => false

app.disabled(name)

如果布林設定 name 已停用 (false),則傳回 true,其中 name應用程式設定表格 中的其中一個屬性。

app.disabled('trust proxy')
// => true

app.enable('trust proxy')
app.disabled('trust proxy')
// => false

app.enable(name)

將布林設定 name 設為 true,其中 name應用程式設定表格 中的其中一個屬性。對於布林屬性,呼叫 app.set('foo', true) 等同於呼叫 app.enable('foo')

app.enable('trust proxy')
app.get('trust proxy')
// => true

app.enabled(name)

如果設定 name 已啟用 (true),則傳回 true,其中 name應用程式設定表格 中的其中一個屬性。

app.enabled('trust proxy')
// => false

app.enable('trust proxy')
app.enabled('trust proxy')
// => true

app.engine(ext, callback)

將指定的範本引擎 callback 註冊為 ext

預設情況下,Express 會根據檔案副檔名來 require() 引擎。例如,如果你嘗試呈現一個「foo.pug」檔案,Express 會在內部呼叫下列程式碼,並在後續呼叫中快取 require() 以提升效能。

app.engine('pug', require('pug').__express)

對於沒有提供 .__express 的引擎,或是如果你想要將不同的副檔名「對應」到範本引擎,請使用這個方法。

例如,將 EJS 範本引擎對應到「.html」檔案

app.engine('html', require('ejs').renderFile)

在此情況下,EJS 提供了一個 .renderFile() 方法,其簽章與 Express 預期的一樣:(path, options, callback),但請注意,它在內部將此方法別名為 ejs.__express,因此如果你使用「.ejs」副檔名,則不需要執行任何操作。

有些範本引擎不遵循此慣例。consolidate.js 函式庫會將 Node 範本引擎對應到遵循此慣例,因此它們可以與 Express 無縫運作。

const engines = require('consolidate')
app.engine('haml', engines.haml)
app.engine('html', engines.hogan)

app.get(name)

傳回 name 應用程式設定的值,其中 name應用程式設定表格 中的其中一個字串。例如

app.get('title')
// => undefined

app.set('title', 'My Site')
app.get('title')
// => "My Site"

app.get(path, callback [, callback ...])

將 HTTP GET 要求路由到指定的路徑,並使用指定的回呼函數。

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

如需更多資訊,請參閱 路由指南

範例

app.get('/', (req, res) => {
  res.send('GET request to homepage')
})

app.listen(path, [callback])

啟動 UNIX socket,並在指定的 path 上偵聽連線。此方法與 Node 的 http.Server.listen() 相同。

const express = require('express')
const app = express()
app.listen('/tmp/sock')

app.listen([port[, host[, backlog]]][, callback])

在指定的 host 和 port 上繫結並偵聽連線。此方法與 Node 的 http.Server.listen() 相同。

如果埠號省略或為 0,作業系統會指派一個隨機未使用的埠號,這對於自動化工作(例如測試)很有用。

const express = require('express')
const app = express()
app.listen(3000)

express() 回傳的 app 實際上是 JavaScript Function,設計為傳遞給 Node 的 HTTP 伺服器,作為處理要求的回呼函式。這使得可以輕鬆地使用相同的程式碼庫提供 HTTP 和 HTTPS 版本的應用程式,因為應用程式不會繼承這些(它只是一個回呼函式)

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

http.createServer(app).listen(80)
https.createServer(options, app).listen(443)

app.listen() 方法會回傳一個 http.Server 物件,並且(對於 HTTP)是以下內容的便利方法

app.listen = function () {
  const server = http.createServer(this)
  return server.listen.apply(server, arguments)
}

注意:Node 的 http.Server.listen() 方法的所有形式實際上都受支援。

app.METHOD(path, callback [, callback ...])

路由 HTTP 要求,其中 METHOD 是要求的 HTTP 方法,例如 GET、PUT、POST 等,以小寫字母表示。因此,實際的方法是 app.get()app.post()app.put() 等。請參閱以下 路由方法 以取得完整清單。

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

路由方法

Express 支援以下路由方法,對應於同名的 HTTP 方法

  • checkout
  • copy
  • delete
  • get
  • head
  • lock
  • merge
  • mkactivity
  • mkcol
  • move
  • m-search
  • notify
  • options
  • patch
  • post
  • purge
  • put
  • report
  • search
  • subscribe
  • trace
  • unlock
  • unsubscribe

API 文件僅針對最受歡迎的 HTTP 方法 app.get()app.post()app.put()app.delete() 提供明確的條目。不過,上面列出的其他方法運作方式完全相同。

若要路由轉譯為無效 JavaScript 變數名稱的方法,請使用方括號表示法。例如,app['m-search']('/', function ...

如果在 app.get() 之前未針對路徑呼叫 app.head(),則 app.get() 函式會自動針對 HTTP HEAD 方法(除了 GET 方法)呼叫。

方法 app.all() 未衍生自任何 HTTP 方法,並會針對所有 HTTP 要求方法載入指定路徑的 middleware。如需詳細資訊,請參閱 app.all

如需有關路由的詳細資訊,請參閱 路由指南

app.param(name, callback)

將 callback 觸發器新增至 路由參數,其中 name 是參數的名稱或陣列,而 callback 是 callback 函式。callback 函式的參數依序為要求物件、回應物件、下一個 middleware、參數值和參數名稱。

如果 name 是陣列,則會針對在其中宣告的每個參數註冊 callback 觸發器,順序與宣告順序相同。此外,對於除了最後一個以外的每個宣告參數,callback 內部呼叫 next 會呼叫下一個宣告參數的 callback。對於最後一個參數,呼叫 next 會呼叫目前正在處理的路由的下一 middleware,就像 name 僅為字串一樣。

例如,當路由路徑中存在 :user 時,您可以將使用者載入邏輯對應至自動提供 req.user 至路由,或對參數輸入執行驗證。

app.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})

Param 回呼函式是定義在路由中的區域變數。它們不會被掛載的應用程式或路由繼承。因此,定義在 app 上的 param 回呼函式只會由定義在 app 路由上的路由參數觸發。

所有 param 回呼函式都會在任何包含 param 的路由的任何處理常式之前被呼叫,而且它們在一個請求回應週期中只會被呼叫一次,即使該參數在多個路由中相符,如下列範例所示。

app.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE')
  next()
})

app.get('/user/:id', (req, res, next) => {
  console.log('although this matches')
  next()
})

app.get('/user/:id', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42 中,會印出下列內容

CALLED ONLY ONCE
although this matches
and this matches too
app.param(['id', 'page'], (req, res, next, value) => {
  console.log('CALLED ONLY ONCE with', value)
  next()
})

app.get('/user/:id/:page', (req, res, next) => {
  console.log('although this matches')
  next()
})

app.get('/user/:id/:page', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42/3 中,會印出下列內容

CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this matches too

app.path()

傳回應用程式的標準路徑,一個字串。

const app = express()
const blog = express()
const blogAdmin = express()

app.use('/blog', blog)
blog.use('/admin', blogAdmin)

console.log(app.path()) // ''
console.log(blog.path()) // '/blog'
console.log(blogAdmin.path()) // '/blog/admin'

在掛載應用程式的複雜情況中,此方法的行為可能會變得非常複雜:通常最好使用 req.baseUrl 來取得應用程式的標準路徑。

app.post(path, callback [, callback ...])

使用指定的回呼函式將 HTTP POST 請求路由到指定的 path。更多資訊,請參閱 路由指南

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

範例

app.post('/', (req, res) => {
  res.send('POST request to homepage')
})

app.put(path, callback [, callback ...])

使用指定的回呼函式將 HTTP PUT 請求路由到指定的 path。

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

範例

app.put('/', (req, res) => {
  res.send('PUT request to homepage')
})

app.render(view, [locals], callback)

透過 callback 函式傳回檢視的已呈現 HTML。它接受一個選用參數,該參數是一個包含檢視的區域變數的物件。它就像 res.render(),但它無法自行將已呈現的檢視傳送給用戶端。

app.render() 視為一個用於產生已呈現檢視字串的公用程式函式。在內部,res.render() 使用 app.render() 來呈現檢視。

區域變數 cache 保留給啟用檢視快取。如果你想要在開發期間快取檢視,請將它設定為 true;檢視快取在生產環境中預設啟用。

app.render('email', (err, html) => {
  // ...
})

app.render('email', { name: 'Tobi' }, (err, html) => {
  // ...
})

app.route(path)

傳回單一路由的執行個體,然後你可以使用它來處理 HTTP 動詞,並使用選用的中間軟體。使用 app.route() 來避免重複的路由名稱(因此避免拼寫錯誤)。

const app = express()

app.route('/events')
  .all((req, res, next) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get((req, res, next) => {
    res.json({})
  })
  .post((req, res, next) => {
    // maybe add a new event...
  })

app.set(name, value)

將設定 name 指定給 value。您可以儲存任何您想要的數值,但某些名稱可用於設定伺服器的行為。這些特殊名稱列於 應用程式設定表 中。

對布林屬性呼叫 app.set('foo', true) 與呼叫 app.enable('foo') 相同。類似地,對布林屬性呼叫 app.set('foo', false) 與呼叫 app.disable('foo') 相同。

使用 app.get() 擷取設定值。

app.set('title', 'My Site')
app.get('title') // "My Site"

應用程式設定

下表列出應用程式設定。

請注意,子應用程式將

  • 不會繼承具有預設值的設定值。您必須在子應用程式中設定值。
  • 繼承沒有預設值的設定值;這些值在下方表格中明確註明。

例外:子應用程式將繼承 trust proxy 的值,即使它有預設值(為了向後相容);子應用程式在製作環境(當 NODE_ENV 為「製作環境」)中不會繼承 view cache 的值。

屬性類型說明預設值

大小寫敏感路由

布林值

啟用大小寫敏感。啟用後,「/Foo」和「/foo」是不同的路由。停用後,「/Foo」和「/foo」會被視為相同。

注意:子應用程式將繼承此設定的值。

N/A(未定義)

env

字串 環境模式。務必在製作環境中設定為「製作環境」;請參閱 製作環境最佳實務:效能和可靠性

process.env.NODE_ENVNODE_ENV 環境變數)或「開發」如果未設定 NODE_ENV

etag

變數

設定 ETag 回應標頭。有關可能的值,請參閱 etag 選項表

更多關於 HTTP ETag 標頭的資訊.

jsonp 回呼名稱

字串 指定預設的 JSONP 回呼名稱。

“callback”

json 逸出

布林值

啟用從 res.jsonres.jsonpres.send API 逸出 JSON 回應。這會將字元 <>& 逸出為 JSON 中的 Unicode 逸出序列。此功能的目的是在客戶端嗅探 HTML 的回應時,協助 減輕特定類型的持續性 XSS 攻擊

注意:子應用程式將繼承此設定的值。

N/A(未定義)

json 替換器

變數 `JSON.stringify` 使用的 'replacer' 參數

注意:子應用程式將繼承此設定的值。

N/A(未定義)

json 空格

變數 `JSON.stringify` 使用的 'space' 參數。這通常設定為用於縮排美化 JSON 的空格數。

注意:子應用程式將繼承此設定的值。

N/A(未定義)

查詢剖析器

變數

將值設定為 false 以停用查詢剖析,或設定查詢剖析器使用「簡單」、「延伸」或自訂查詢字串剖析函數。

簡單查詢剖析器基於 Node 的原生查詢剖析器 querystring

延伸查詢剖析器基於 qs

自訂查詢字串剖析函數會收到完整的查詢字串,且必須傳回查詢金鑰及其值的物件。

"延伸"

嚴格路由

布林值

啟用嚴格路由。啟用後,路由器會將「/foo」和「/foo/」視為不同路徑。否則,路由器會將「/foo」和「/foo/」視為相同路徑。

注意:子應用程式將繼承此設定的值。

N/A(未定義)

次網域偏移

數字 移除主機中以點分隔的部分數目,以存取次網域。 2

信任代理

變數

表示應用程式位於面向使用者的代理伺服器之後,且使用 X-Forwarded-* 標頭來判斷連線和客戶端 IP 位址。注意:X-Forwarded-* 標頭容易偽造,且偵測到的 IP 位址不可靠。

啟用時,Express 會嘗試判斷透過面向前端的代理伺服器或一系列代理伺服器連線的用戶端 IP 位址。然後,`req.ips` 屬性會包含用戶端連線的 IP 位址陣列。若要啟用,請使用 信任代理伺服器選項表格 中所述的值。

`trust proxy` 設定是使用 proxy-addr 套件實作。如需更多資訊,請參閱其文件。

注意:即使有預設值,子應用程式也會繼承此設定的值。

false(已停用)

檢視

字串或陣列 應用程式檢視的目錄或目錄陣列。如果是陣列,檢視會依據在陣列中出現的順序進行查詢。

process.cwd() + '/views'

檢視快取

布林值

啟用檢視範本編譯快取。

注意:在生產環境中(當 `NODE_ENV` 為「production」時),子應用程式不會繼承此設定的值。

在生產環境中為 true,否則未定義。

檢視引擎

字串 省略時要使用的預設引擎擴充功能。

注意:子應用程式將繼承此設定的值。

N/A(未定義)

x-powered-by

布林值 啟用「X-Powered-By: Express」HTTP 標頭。

true

`trust proxy` 設定的選項

請閱讀 [Express behind proxies]/zh-tw/behind-proxies.html) 以取得更多資訊。

類型
布林值

如果為 true,用戶端的 IP 位址會理解為 X-Forwarded-* 標頭中最左邊的項目。

如果為 false,應用程式會理解為直接面向網際網路,且用戶端的 IP 位址會從 req.connection.remoteAddress 衍生。這是預設設定。

字串
包含逗號分隔值的字串
字串陣列

IP 位址、子網路或 IP 位址陣列,以及要信任的子網路。預先設定的子網路名稱為

  • 回傳路徑 - 127.0.0.1/8, ::1/128
  • 連結本機 - 169.254.0.0/16, fe80::/10
  • 唯一本機 - 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7

設定 IP 位址,方法如下

指定單一子網路

app.set('trust proxy', 'loopback')

指定子網路和位址

app.set('trust proxy', 'loopback, 123.123.123.123')

指定多個子網路為 CSV

app.set('trust proxy', 'loopback, linklocal, uniquelocal')

指定多個子網路為陣列

app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal'])

指定後,IP 位址或子網路會從位址判定程序中排除,且最接近應用程式伺服器的非信任 IP 位址會判定為客戶端 IP 位址。

數字

信任來自前置代理伺服器的第 n 個跳躍作為客戶端。

函式

自訂信任實作。僅在您知道自己在做什麼時使用。

app.set('trust proxy', (ip) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123') return true // trusted IPs
  else return false
})
`etag` 設定的選項

注意:這些設定僅適用於動態檔案,不適用於靜態檔案。 express.static 中介軟體會略過這些設定。

ETag 功能性使用 etag 套件實作。如需更多資訊,請參閱其文件。

類型
布林值

true 啟用弱 ETag。這是預設設定。
false 完全停用 ETag。

字串 如果為「強」,則啟用強 ETag。
如果為「弱」,則啟用弱 ETag。
函式

自訂 ETag 函數實作。僅在您知道自己在做什麼時使用。

app.set('etag', (body, encoding) => {
  return generateHash(body, encoding) // consider the function is defined
})

app.use([路徑,] 回呼 [, 回呼...])

在指定路徑掛載指定的 中介軟體 函數或函數:當請求的路徑基礎與 路徑 相符時,會執行中介軟體函數。

引數

引數 說明 預設值
path 呼叫中介軟體函式的路徑;可以是下列任一項
  • 表示路徑的字串。
  • 路徑模式。
  • 用於比對路徑的正規表示式模式。
  • 上述任一項的組合陣列。
範例,請參閱 路徑範例
'/' (根路徑)
callback 回呼函式;可以是
  • 中介軟體函式。
  • 一系列中介軟體函式(以逗號分隔)。
  • 中介軟體函式的陣列。
  • 上述所有項目的組合。

您可以提供多個回呼函式,它們的行為就像中介軟體,但這些回呼函式可以呼叫 next('route') 以略過其餘的路由回呼函式。您可以使用此機制對路由施加前提條件,然後在沒有理由繼續進行目前路由的情況下,將控制權傳遞給後續路由。

當回呼函式擲回錯誤或傳回已拒絕的承諾時,將自動呼叫 `next(err)`。

由於 routerapp 實作中介軟體介面,因此您可以像使用其他任何中介軟體函式一樣使用它們。

範例,請參閱 中介軟體回呼函式範例

說明

路由會與其路徑後方緊接「/」的任何路徑相符。例如:app.use('/apple', ...) 會與「/apple」、「/apple/images」、「/apple/images/news」等相符。

由於 路徑 預設為「/」,因此未設定路徑而掛載的中介軟體會對應用程式的每個請求執行。
例如,這個中間件函式會執行於應用程式的每個請求

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

注意

子應用程式會

  • 不會繼承具有預設值的設定值。您必須在子應用程式中設定值。
  • 繼承沒有預設值的設定值。

詳細資訊,請參閱 應用程式設定

中間件函式會依序執行,因此中間件包含的順序很重要。

// this middleware will not allow the request to go beyond it
app.use((req, res, next) => {
  res.send('Hello World')
})

// requests will never reach this route
app.get('/', (req, res) => {
  res.send('Welcome')
})

錯誤處理中間件

錯誤處理中間件總是需要四個參數。您必須提供四個參數才能識別它為錯誤處理中間件函式。即使您不需要使用next物件,您也必須指定它來維護簽章。否則,next物件將會被解釋為一般中間件,並且無法處理錯誤。有關錯誤處理中間件的詳細資訊,請參閱:錯誤處理

定義錯誤處理中間件函式的程式碼與其他中間件函式相同,但參數為四個而非三個,特別是簽章(err, req, res, next)

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

路徑範例

下表提供一些用於掛載中間件的有效path值的簡單範例。

類型 範例
路徑

這將比對以/abcd開頭的路徑

app.use('/abcd', (req, res, next) => {
  next()
})
路徑模式

這將比對以/abcd/abd開頭的路徑

app.use('/ab(c?)d', (req, res, next) => {
  next()
})
正規表示法

這將比對以/abc/xyz開頭的路徑

app.use(/\/abc|\/xyz/, (req, res, next) => {
  next()
})
陣列

這將比對以/abcd/xyza/lmn/pqr開頭的路徑

app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], (req, res, next) => {
  next()
})

中間件回呼函式範例

下表提供一些簡單的中間件函式範例,可以用作app.use()app.METHOD()app.all()callback參數。儘管這些範例是針對app.use(),但它們也適用於app.use()app.METHOD()app.all()

用法 範例
單一中間件

您可以在本地定義並掛載中間件函式。

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

路由器是有效的中間件。

const router = express.Router()
router.get('/', (req, res, next) => {
  next()
})
app.use(router)

Express 應用程式是有效的中間件。

const subApp = express()
subApp.get('/', (req, res, next) => {
  next()
})
app.use(subApp)
一系列中間件

您可以在同一個掛載路徑指定多個中間件函式。

const r1 = express.Router()
r1.get('/', (req, res, next) => {
  next()
})

const r2 = express.Router()
r2.get('/', (req, res, next) => {
  next()
})

app.use(r1, r2)
陣列

使用陣列以邏輯方式分組中間件。

const r1 = express.Router()
r1.get('/', (req, res, next) => {
  next()
})

const r2 = express.Router()
r2.get('/', (req, res, next) => {
  next()
})

app.use([r1, r2])
組合

您可以結合上述所有掛載中間件的方法。

function mw1 (req, res, next) { next() }
function mw2 (req, res, next) { next() }

const r1 = express.Router()
r1.get('/', (req, res, next) => { next() })

const r2 = express.Router()
r2.get('/', (req, res, next) => { next() })

const subApp = express()
subApp.get('/', (req, res, next) => { next() })

app.use(mw1, [mw2, r1, r2], subApp)

以下是使用 Express 應用程式中的 express.static 中間件的一些範例。

從應用程式目錄中的「public」目錄為應用程式提供靜態內容

// GET /style.css etc
app.use(express.static(path.join(__dirname, 'public')))

在「/static」掛載中間件,僅在請求路徑加上「/static」前綴時提供靜態內容

// GET /static/style.css etc.
app.use('/static', express.static(path.join(__dirname, 'public')))

在靜態中間件之後載入記錄器中間件,以停用靜態內容請求的記錄

app.use(express.static(path.join(__dirname, 'public')))
app.use(logger())

從多個目錄提供靜態檔案,但優先使用「./public」

app.use(express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'files')))
app.use(express.static(path.join(__dirname, 'uploads')))

請求

req 物件代表 HTTP 請求,並具有請求查詢字串、參數、主體、HTTP 標頭等的屬性。在此文件和慣例中,物件總是稱為 req(而 HTTP 回應為 res),但其實際名稱由您正在使用的回呼函式的參數決定。

例如

app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`)
})

但您也可以

app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`)
})

req 物件是 Node 自有請求物件的加強版本,並支援所有 內建欄位和方法

屬性

在 Express 4 中,req.files 預設不再在 req 物件中提供。若要存取 req.files 物件上的上傳檔案,請使用多部分處理中間件,例如 busboymulterformidablemultipartyconnect-multipartypez

req.app

此屬性持有使用中間件的 Express 應用程式實例的參考。

如果您遵循模式,其中建立一個模組僅匯出中間件函式,並在主檔案中使用 require(),則中間件可以透過 req.app 存取 Express 實例。

例如

// index.js
app.get('/viewdirectory', require('./mymiddleware.js'))
// mymiddleware.js
module.exports = (req, res) => {
  res.send(`The views directory is ${req.app.get('views')}`)
}

req.baseUrl

路由器實例掛載的 URL 路徑。

req.baseUrl 屬性類似於 app 物件的 mountpath 屬性,但 app.mountpath 會傳回已比對的路徑模式。

例如

const greet = express.Router()

greet.get('/jp', (req, res) => {
  console.log(req.baseUrl) // /greet
  res.send('Konichiwa!')
})

app.use('/greet', greet) // load the router on '/greet'

即使您使用路徑模式或一組路徑模式來載入路由器,baseUrl 屬性會傳回已比對的字串,而不是模式。在以下範例中,greet 路由器會在兩個路徑模式上載入。

app.use(['/gre+t', '/hel{2}o'], greet) // load the router on '/gre+t' and '/hel{2}o'

當對 /greet/jp 提出要求時,req.baseUrl 會是「/greet」。當對 /hello/jp 提出要求時,req.baseUrl 會是「/hello」。

req.body

包含在要求主體中提交的資料的鍵值對。預設為 undefined,當您使用主體剖析中間件(例如 body-parsermulter)時,會填入資料。

由於 req.body 的形狀基於使用者控制的輸入,此物件中的所有屬性和值都是不可信的,在信任之前應先驗證。例如,req.body.foo.toString() 可能會以多種方式失敗,例如 foo 可能不存在或不是字串,而 toString 可能不是函式,而是字串或其他使用者輸入。

以下範例顯示如何使用主體剖析中間件來填入 req.body

const app = require('express')()
const bodyParser = require('body-parser')
const multer = require('multer') // v1.0.5
const upload = multer() // for parsing multipart/form-data

app.use(bodyParser.json()) // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

app.post('/profile', upload.array(), (req, res, next) => {
  console.log(req.body)
  res.json(req.body)
})

req.cookies

當使用 cookie-parser 中間件時,此屬性是一個包含要求傳送的 Cookie 的物件。如果要求不包含任何 Cookie,則預設為 {}

// Cookie: name=tj
console.dir(req.cookies.name)
// => "tj"

如果 Cookie 已簽署,您必須使用 req.signedCookies

如需更多資訊、問題或疑慮,請參閱 cookie-parser

req.fresh

當回應在客戶端的快取中仍然「新鮮」時,會傳回 true,否則會傳回 false 以表示客戶端快取現在已過期,且應傳送完整的回應。

當客戶端傳送 Cache-Control: no-cache 要求標頭以表示端對端重新載入要求時,此模組會傳回 false 以透明地處理這些要求。

有關快取驗證運作方式的更多詳細資料,請參閱 HTTP/1.1 快取規格

console.dir(req.fresh)
// => true

req.host

包含從 Host HTTP 標頭衍生的主機。

trust proxy 設定 未評估為 false 時,此屬性將改為從 X-Forwarded-Host 標頭欄位取得值。此標頭可以由客戶端或代理程式設定。

如果要求中有多個 X-Forwarded-Host 標頭,則會使用第一個標頭的值。這包括具有逗號分隔值的單一標頭,其中會使用第一個值。

// Host: "example.com:3000"
console.dir(req.host)
// => 'example.com:3000'

// Host: "[::1]:3000"
console.dir(req.host)
// => '[::1]:3000'

req.hostname

包含從 Host HTTP 標頭衍生的主機名稱。

trust proxy 設定 未評估為 false 時,此屬性將改為從 X-Forwarded-Host 標頭欄位取得值。此標頭可以由客戶端或代理程式設定。

如果要求中有多個 X-Forwarded-Host 標頭,則會使用第一個標頭的值。這包括具有逗號分隔值的單一標頭,其中會使用第一個值。

在 Express v4.17.0 之前,X-Forwarded-Host 無法包含多個值或出現多次。

// Host: "example.com:3000"
console.dir(req.hostname)
// => 'example.com'

req.ip

包含要求的遠端 IP 位址。

trust proxy 設定 未評估為 false 時,此屬性的值會從 X-Forwarded-For 標頭最左邊的項目衍生。此標頭可以由客戶端或代理程式設定。

console.dir(req.ip)
// => "127.0.0.1"

req.ips

trust proxy 設定 沒有評估為 false 時,此屬性包含在 X-Forwarded-For 要求標頭中指定的 IP 位址陣列。否則,它包含一個空陣列。此標頭可以由客戶端或代理程式設定。

例如,如果 X-Forwarded-Forclient, proxy1, proxy2,則 req.ips 會是 ["client", "proxy1", "proxy2"],其中 proxy2 是最下游的。

req.method

包含一個字串,對應於要求的 HTTP 方法:GETPOSTPUT,等等。

req.originalUrl

req.url 不是一個原生 Express 屬性,它繼承自 Node 的 http 模組

此屬性很像 req.url;但是,它保留原始要求 URL,允許您自由改寫 req.url 以供內部路由使用。例如,app.use() 的「掛載」功能會改寫 req.url 以移除掛載點。

// GET /search?q=something
console.dir(req.originalUrl)
// => "/search?q=something"

req.originalUrl 在 middleware 和路由器物件中都可用,並且是 req.baseUrlreq.url 的組合。考慮以下範例

// GET 'http://www.example.com/admin/new?sort=desc'
app.use('/admin', (req, res, next) => {
  console.dir(req.originalUrl) // '/admin/new?sort=desc'
  console.dir(req.baseUrl) // '/admin'
  console.dir(req.path) // '/new'
  next()
})

req.params

此屬性是一個物件,包含對應到 命名路由「參數」 的屬性。例如,如果您有路由 /user/:name,則「name」屬性可用為 req.params.name。此物件預設為 {}

// GET /user/tj
console.dir(req.params.name)
// => "tj"

當您對路由定義使用正規表示式時,會在陣列中使用 req.params[n] 提供擷取群組,其中 n 是第 n 個擷取群組。此規則套用於具有字串路由的未命名萬用字元比對,例如 /file/*

// GET /file/javascripts/jquery.js
console.dir(req.params[0])
// => "javascripts/jquery.js"

如果您需要變更 req.params 中的某個金鑰,請使用 app.param 處理常式。變更僅適用於已在路由路徑中定義的 參數

在中間件或路由處理程式中對 req.params 物件所做的任何變更都會重設。

注意:Express 會自動解碼 req.params 中的值(使用 decodeURIComponent)。

req.path

包含請求 URL 的路徑部分。

// example.com/users?sort=desc
console.dir(req.path)
// => "/users"

從中間件呼叫時,掛載點不會包含在 req.path 中。有關更多詳細資訊,請參閱 app.use()

req.protocol

包含請求通訊協定字串:http 或(對於 TLS 請求)https

信任代理設定 的評估結果不為 false 時,此屬性會使用 X-Forwarded-Proto 標頭欄位的數值(如果存在)。此標頭可以由客戶端或代理程式設定。

console.dir(req.protocol)
// => "http"

req.query

此屬性是一個物件,包含路由中每個查詢字串參數的屬性。當 查詢剖析器 設定為停用時,它是一個空的物件 {},否則它就是已設定查詢剖析器的結果。

由於 req.query 的形狀是根據使用者控制的輸入,因此此物件中的所有屬性和值都是不可信的,在信任之前應先驗證。例如,req.query.foo.toString() 可能會以多種方式失敗,例如 foo 可能不存在或不是字串,而 toString 可能不是函式,而是字串或其他使用者輸入。

此屬性的值可以使用 查詢剖析器應用程式設定 設定,以符合應用程式的需求。一個非常流行的查詢字串剖析器是 qs 模組,而且這是預設使用的。qs 模組可以透過許多設定進行設定,而且可能需要使用與預設值不同的設定來填入 req.query

const qs = require('qs')
app.set('query parser',
  (str) => qs.parse(str, { /* custom options */ }))

查看 查詢剖析器應用程式設定 文件以取得其他自訂選項。

req.res

此屬性會保留對應於此請求物件的 回應物件 的參考。

req.route

包含目前相符的路由,一個字串。例如

app.get('/user/:id?', (req, res) => {
  console.log(req.route)
  res.send('GET')
})

前一個程式碼片段的範例輸出

{ path: '/user/:id?',
  stack:
   [ { handle: [Function: userIdHandler],
       name: 'userIdHandler',
       params: undefined,
       path: undefined,
       keys: [],
       regexp: /^\/?$/i,
       method: 'get' } ],
  methods: { get: true } }

req.secure

如果建立 TLS 連線,則為 true 的布林屬性。等同於以下內容

req.protocol === 'https'

req.signedCookies

使用 cookie-parser 中介軟體時,此屬性包含要求傳送的已簽署 cookie,未簽署且可供使用。已簽署的 cookie 位於不同的物件中,以顯示開發人員的意圖;否則,惡意攻擊可能會放置在 req.cookie 值中(容易偽造)。請注意,簽署 cookie 並不會使其「隱藏」或加密;只是防止竄改(因為用於簽署的密碼是私密的)。

如果未傳送已簽署的 cookie,則屬性預設為 {}

// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user)
// => "tobi"

如需更多資訊、問題或疑慮,請參閱 cookie-parser

req.stale

指出要求是否「過期」,與 req.fresh 相反。如需詳細資訊,請參閱 req.fresh

console.dir(req.stale)
// => true

req.subdomains

要求網域名稱中子網域的陣列。

// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains)
// => ["ferrets", "tobi"]

應用程式屬性 subdomain offset 預設為 2,用於判斷子網域區段的開頭。若要變更此行為,請使用 app.set 變更其值。

req.xhr

如果要求的 X-Requested-With 標頭欄位為「XMLHttpRequest」,則為 true 的布林屬性,表示要求是由 jQuery 等用戶端函式庫所發出。

console.dir(req.xhr)
// => true

方法

req.accepts(types)

根據要求的 Accept HTTP 標頭欄位,檢查指定的內容類型是否可接受。此方法會傳回最佳相符項,或者如果沒有任何指定的內容類型可接受,則傳回 false(在此情況下,應用程式應回應 406 "Not Acceptable")。

type 值可以是單一 MIME 類型字串(例如「application/json」)、副檔名(例如「json」)、逗號分隔清單或陣列。對於清單或陣列,此方法會傳回最佳符合項(若有)。

// Accept: text/html
req.accepts('html')
// => "html"

// Accept: text/*, application/json
req.accepts('html')
// => "html"
req.accepts('text/html')
// => "text/html"
req.accepts(['json', 'text'])
// => "json"
req.accepts('application/json')
// => "application/json"

// Accept: text/*, application/json
req.accepts('image/png')
req.accepts('png')
// => false

// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json'])
// => "json"

如需更多資訊,或是有問題或疑慮,請參閱 accepts

req.acceptsCharsets(charset [, ...])

根據要求的 Accept-Charset HTTP 標頭欄位,傳回指定字元集的第一個已接受字元集。如果沒有接受任何指定的字元集,則傳回 false

如需更多資訊,或是有問題或疑慮,請參閱 accepts

req.acceptsEncodings(encoding [, ...])

根據要求的 Accept-Encoding HTTP 標頭欄位,傳回指定編碼的第一個已接受編碼。如果沒有接受任何指定的編碼,則傳回 false

如需更多資訊,或是有問題或疑慮,請參閱 accepts

req.acceptsLanguages(lang [, ...])

根據要求的 Accept-Language HTTP 標頭欄位,傳回指定語言的第一個已接受語言。如果沒有接受任何指定的語言,則傳回 false

如需更多資訊,或是有問題或疑慮,請參閱 accepts

req.get(field)

傳回指定的 HTTP 要求標頭欄位(不分大小寫)。ReferrerReferer 欄位可以互換。

req.get('Content-Type')
// => "text/plain"

req.get('content-type')
// => "text/plain"

req.get('Something')
// => undefined

別名為 req.header(field)

req.is(type)

如果傳入要求的「Content-Type」HTTP 標頭欄位符合 type 參數指定的 MIME 類型,則傳回符合的內容類型。如果要求沒有主體,則傳回 null。否則傳回 false

// With Content-Type: text/html; charset=utf-8
req.is('html') // => 'html'
req.is('text/html') // => 'text/html'
req.is('text/*') // => 'text/*'

// When Content-Type is application/json
req.is('json') // => 'json'
req.is('application/json') // => 'application/json'
req.is('application/*') // => 'application/*'

req.is('html')
// => false

如需更多資訊,或是有問題或疑慮,請參閱 type-is

req.range(size[, options])

Range 標頭剖析器。

size 參數是資源的最大大小。

options 參數是一個物件,可以有下列屬性。

屬性 類型 說明
combine 布林值 指定是否合併重疊和相鄰的範圍,預設為 false。當為 true 時,範圍將會合併,並以在標頭中以這種方式指定的型式傳回。

將會傳回範圍陣列或表示解析錯誤的負數。

  • -2 表示標頭字串格式錯誤
  • -1 表示無法滿足的範圍
// parse header from request
const range = req.range(1000)

// the type of the range
if (range.type === 'bytes') {
  // the ranges
  range.forEach((r) => {
    // do something with r.start and r.end
  })
}

回應

res 物件代表 Express 應用程式在收到 HTTP 要求時所傳送的 HTTP 回應。

在此文件和慣例中,物件總是稱為 res(而 HTTP 要求為 req),但其實際名稱是由您正在使用的回呼函式的參數所決定。

例如

app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`)
})

但您也可以

app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`)
})

res 物件是 Node 自身回應物件的加強版本,並支援所有 內建欄位和方法

屬性

res.app

此屬性持有使用中間件的 Express 應用程式實例的參考。

res.app 與要求物件中的 req.app 屬性相同。

res.headersSent

布林屬性,表示應用程式是否為回應傳送 HTTP 標頭。

app.get('/', (req, res) => {
  console.log(res.headersSent) // false
  res.send('OK')
  console.log(res.headersSent) // true
})

res.locals

使用此屬性來設定可於使用 res.render 呈現的範本中存取的變數。設定在 res.locals 上的變數在單一要求-回應循環中可用,且不會在要求之間共用。

若要讓區域變數在要求之間的範本呈現中使用,請改用 app.locals

這個屬性可用於將請求層級資訊(例如請求路徑名稱、經過驗證的使用者、使用者設定等)公開給應用程式內部所呈現的範本。

app.use((req, res, next) => {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user
  res.locals.authenticated = !req.user.anonymous
  next()
})

res.req

這個屬性持有與這個回應物件相關的請求物件的參考。

方法

res.append(field [, value])

res.append() 受 Express v4.11.0+ 支援

將指定的附加到 HTTP 回應標頭欄位。如果標頭尚未設定,則會使用指定的數值建立標頭。參數可以是字串或陣列。

注意:在 res.append() 之後呼叫 res.set() 會重設先前設定的標頭值。

res.append('Link', ['<https://127.0.0.1/>', '<https://127.0.0.1:3000/>'])
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')
res.append('Warning', '199 Miscellaneous warning')

res.attachment([filename])

將 HTTP 回應Content-Disposition 標頭欄位設定為「附件」。如果提供檔名,則會透過 res.type() 依據副檔名設定內容類型,並設定 Content-Disposition 的「檔名=」參數。

res.attachment()
// Content-Disposition: attachment

res.attachment('path/to/logo.png')
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png

res.cookie(name, value [, options])

將 Cookie 的名稱設定為參數可以是字串或轉換為 JSON 的物件。

options 參數是一個物件,可以有下列屬性。

屬性 類型 說明
domain 字串 Cookie 的網域名稱。預設為應用程式的網域名稱。
encode 函式 用於 Cookie 值編碼的同步函式。預設為 encodeURIComponent
expires 日期 Cookie 在 GMT 中的到期日。如果未指定或設定為 0,則會建立一個工作階段 Cookie。
httpOnly 布林值 標記 Cookie 只能由網路伺服器存取。
maxAge 數字 設定相對於目前時間的到期時間(以毫秒為單位)的便利選項。
path 字串 Cookie 的路徑。預設為「/」。
secure 布林值 標記 Cookie 只能與 HTTPS 一起使用。
已簽署 布林值 指出是否應簽署 cookie。
sameSite 布林值或字串 「SameSite」Set-Cookie 屬性的值。更多資訊請參閱 https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1.1

res.cookie() 所做的所有事,就是設定 HTTP Set-Cookie 標頭,並提供選項。任何未指定的選項,預設值為 RFC 6265 中所述的值。

例如

res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true })
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })

encode 選項讓您可以選擇用於 cookie 值編碼的函式。不支援非同步函式。

範例用例:您需要為組織中的另一個網站設定網域範圍的 cookie。這個其他網站(不在您的管理控制之下)不使用 URI 編碼的 cookie 值。

// Default encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com' })
// Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'

// Custom encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com', encode: String })
// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'

maxAge 選項是設定「expires」的便捷選項,相對於目前時間以毫秒為單位。下列範例等同於上述第二個範例。

res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })

您可以傳遞一個物件作為 value 參數;然後它會序列化為 JSON,並由 bodyParser() 中介軟體進行剖析。

res.cookie('cart', { items: [1, 2, 3] })
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 })

使用 cookie-parser 中介軟體時,此方法也支援已簽署的 cookie。只需包含設定為 truesigned 選項即可。然後 res.cookie() 會使用傳遞給 cookieParser(secret) 的機密來簽署值。

res.cookie('name', 'tobi', { signed: true })

稍後您可以透過 req.signedCookies 物件存取此值。

res.clearCookie(name [, options])

清除由 name 指定的 cookie。有關 options 物件的詳細資訊,請參閱 res.cookie()

Web 瀏覽器和其他相容的用戶端只會在給定的 options 與給予 res.cookie() 的相同(排除 expiresmaxAge)時清除 cookie。

res.cookie('name', 'tobi', { path: '/admin' })
res.clearCookie('name', { path: '/admin' })

res.download(path [, filename] [, options] [, fn])

Express v4.16.0 起支援選擇性的 options 參數。

path 中的檔案傳輸為「附件」。通常,瀏覽器會提示使用者下載。預設情況下,Content-Disposition 標頭的「filename=」參數會從 path 參數中取得,但可用 filename 參數覆寫。如果 path 是相對路徑,則會根據處理程序的目前工作目錄為基礎。

下表提供 options 參數的詳細資料。

Express v4.16.0 起支援選擇性的 options 參數。

屬性 說明 預設值 可用性
maxAge 以毫秒或 ms 格式 的字串設定 Cache-Control 標頭的 max-age 屬性 0 4.16+
lastModified Last-Modified 標頭設定為檔案在作業系統上的最後修改日期。設定為 false 以停用。 已啟用 4.16+
headers 包含要與檔案一起提供的 HTTP 標頭的物件。Content-Disposition 標頭會被 filename 參數覆寫。   4.16+
dotfiles 提供 dotfiles 的選項。可能的值為「allow」、「deny」、「ignore」。 「忽略」 4.16+
acceptRanges 啟用或停用接受範圍要求。 true 4.16+
cacheControl 啟用或停用設定 Cache-Control 回應標頭。 true 4.16+
immutable Cache-Control 回應標頭中啟用或停用 immutable 指令。如果啟用,也應指定 maxAge 選項以啟用快取。immutable 指令將防止受支援的用戶端在 maxAge 選項的生命週期內提出條件式請求,以檢查檔案是否已變更。 false 4.16+

傳輸完成或發生錯誤時,此方法會呼叫回呼函式 fn(err)。如果指定了回呼函式,且發生錯誤,回呼函式必須明確處理回應程序,方法是結束請求回應循環,或將控制權傳遞給下一個路由。

res.download('/report-12345.pdf')

res.download('/report-12345.pdf', 'report.pdf')

res.download('/report-12345.pdf', 'report.pdf', (err) => {
  if (err) {
    // Handle error, but keep in mind the response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
})

res.end([data] [, encoding])

結束回應程序。此方法實際上來自 Node 核心,特別是 http.ServerResponse 的 response.end() 方法

用於快速結束回應,而無任何資料。如果您需要回應資料,請改用 res.send()res.json() 等方法。

res.end()
res.status(404).end()

res.format(object)

在請求物件上對 Accept HTTP 標頭執行內容協商(如果存在)。它使用 req.accepts() 根據可接受類型按其品質值排序,為請求選擇處理常式。如果未指定標頭,則呼叫第一個回呼。如果找不到匹配項,伺服器會回應 406「不可接受」,或呼叫 default 回呼。

當選擇回呼時,會設定 Content-Type 回應標頭。不過,您可以在回呼中使用 res.set()res.type() 等方法來變更它。

Accept 標頭欄位設定為「application/json」或「*/json」時(不過如果是「*/*」,則回應會是「hey」),以下範例會回應 { "message": "hey" }

res.format({
  'text/plain' () {
    res.send('hey')
  },

  'text/html' () {
    res.send('<p>hey</p>')
  },

  'application/json' () {
    res.send({ message: 'hey' })
  },

  default () {
    // log the request and respond with 406
    res.status(406).send('Not Acceptable')
  }
})

除了正規化的 MIME 類型外,您還可以對應到這些類型的副檔名,以實作較不冗長的版本

res.format({
  text () {
    res.send('hey')
  },

  html () {
    res.send('<p>hey</p>')
  },

  json () {
    res.send({ message: 'hey' })
  }
})

res.get(field)

傳回 field 指定的 HTTP 回應標頭。比對不分大小寫。

res.get('Content-Type')
// => "text/plain"

res.json([body])

傳送 JSON 回應。此方法傳送一個回應(具有正確的內容類型),該回應是使用 JSON.stringify() 將參數轉換為 JSON 字串。

參數可以是任何 JSON 類型,包括物件、陣列、字串、布林值、數字或 null,您也可以使用它將其他值轉換為 JSON。

res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })

res.jsonp([body])

傳送支援 JSONP 的 JSON 回應。此方法與 res.json() 相同,但它選擇加入 JSONP 回呼支援。

res.jsonp(null)
// => callback(null)

res.jsonp({ user: 'tobi' })
// => callback({ "user": "tobi" })

res.status(500).jsonp({ error: 'message' })
// => callback({ "error": "message" })

預設情況下,JSONP 回呼名稱僅為 callback。使用 jsonp 回呼名稱 設定覆寫此名稱。

以下是使用相同程式碼的一些 JSONP 回應範例

// ?callback=foo
res.jsonp({ user: 'tobi' })
// => foo({ "user": "tobi" })

app.set('jsonp callback name', 'cb')

// ?cb=foo
res.status(500).jsonp({ error: 'message' })
// => foo({ "error": "message" })

加入提供為參數屬性的 links,以填入回應的 Link HTTP 標頭欄位。

例如,下列呼叫

res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5'
})

產生下列結果

Link: <http://api.example.com/users?page=2>; rel="next",
      <http://api.example.com/users?page=5>; rel="last"

res.location(path)

將回應 Location HTTP 標頭設定為指定的 path 參數。

res.location('/foo/bar')
res.location('http://example.com')
res.location('back')

「back」的 path 值具有特殊意義,它指的是請求的 Referer 標頭中指定的 URL。如果未指定 Referer 標頭,它指的是「/」。

在編碼 URL(如果尚未編碼)後,Express 會在 Location 標頭中將指定的 URL 傳遞給瀏覽器,而不會進行任何驗證。

瀏覽器負責從目前的 URL 或參考 URL,以及 Location 標頭中指定的 URL,推導出預期的 URL;並據此重新導向使用者。

res.redirect([status,] path)

重新導向到從指定的 path 推導出的 URL,並具有指定的 status,一個對應於 HTTP 狀態碼 的正整數。如果未指定,status 預設為「302 已找到」。

res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')

重新導向可以是完全限定的 URL,用於重新導向到不同的網站

res.redirect('http://google.com')

重新導向可以是相對於主機名稱根目錄的。例如,如果應用程式位於 http://example.com/admin/post/new,下列會重新導向到 URL http://example.com/admin

res.redirect('/admin')

重新導向可以相對於目前的 URL。例如,從 http://example.com/blog/admin/(注意尾斜線),以下會重新導向到 URL http://example.com/blog/admin/post/new

res.redirect('post/new')

http://example.com/blog/admin(沒有尾斜線)重新導向到 post/new,會重新導向到 http://example.com/blog/post/new

如果您發現上述行為令人困惑,請將路徑區段視為目錄(帶有尾斜線)和檔案,這樣就會開始有意義了。

路徑相關的重新導向也是可能的。如果您在 http://example.com/admin/post/new,以下會重新導向到 http://example.com/admin/post

res.redirect('..')

back 重新導向會將要求重新導向回 referer,當 referer 遺失時,預設為 /

res.redirect('back')

res.render(view [, locals] [, callback])

呈現 view 並將呈現的 HTML 字串傳送給用戶端。選用參數

  • locals,一個物件,其屬性定義檢視的局部變數。
  • callback,一個回呼函式。如果提供,方法會同時傳回可能的錯誤和呈現的字串,但不會執行自動回應。當發生錯誤時,方法會在內部呼叫 next(err)

view 參數是一個字串,是呈現的檢視檔案的檔案路徑。這可以是絕對路徑,或相對於 views 設定的路徑。如果路徑不包含檔案副檔名,則 view engine 設定會決定檔案副檔名。如果路徑包含檔案副檔名,則 Express 會載入指定範本引擎的模組(透過 require())並使用載入模組的 __express 函式呈現它。

如需更多資訊,請參閱 在 Express 中使用範本引擎

注意:view 參數會執行檔案系統作業,例如從磁碟讀取檔案和評估 Node.js 模組,因此出於安全性考量,不應包含來自最終使用者的輸入。

本機變數 cache 可啟用檢視快取。將其設定為 true,以在開發期間快取檢視;預設會在製作環境中啟用檢視快取。

// send the rendered view to the client
res.render('index')

// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', (err, html) => {
  res.send(html)
})

// pass a local variable to the view
res.render('user', { name: 'Tobi' }, (err, html) => {
  // ...
})

res.send([body])

傳送 HTTP 回應。

body 參數可以是 Buffer 物件、字串物件布林值陣列。例如

res.send(Buffer.from('whoop'))
res.send({ some: 'json' })
res.send('<p>some html</p>')
res.status(404).send('Sorry, we cannot find that!')
res.status(500).send({ error: 'something blew up' })

此方法會執行許多對非串流回應有用的工作:例如,它會自動指派 Content-Length HTTP 回應標頭欄位,並提供自動 HEAD 和 HTTP 快取新穎性支援。

當參數是 Buffer 物件時,此方法會將 Content-Type 回應標頭欄位設定為「application/octet-stream」,除非先前已定義如下所示

res.set('Content-Type', 'text/html')
res.send(Buffer.from('<p>some html</p>'))

當參數是 字串時,此方法會將 Content-Type 設定為「text/html」

res.send('<p>some html</p>')

當參數是 陣列物件時,Express 會回應 JSON 表示。

res.send({ user: 'tobi' })
res.send([1, 2, 3])

res.sendFile(path [, options] [, fn])

res.sendFile() 受 Express v4.8.0 以上版本支援。

傳輸位於指定 path 的檔案。根據檔名副檔名設定 Content-Type 回應 HTTP 標頭欄位。除非在選項物件中設定 root 選項,否則 path 必須是檔案的絕對路徑。

此 API 提供存取執行中檔案系統資料的功能。請確保 (a) 將 path 參數建構為絕對路徑時,如果其中包含使用者輸入,則必須安全,或 (b) 將 root 選項設定為目錄的絕對路徑,以包含存取權。

提供 root 選項時,允許 path 參數為相對路徑,包括包含 ..。Express 會驗證以 path 提供的相對路徑會在指定的 root 選項中解析。

下表提供 options 參數的詳細資料。

屬性 說明 預設值 可用性
maxAge 以毫秒或 ms 格式 的字串設定 Cache-Control 標頭的 max-age 屬性 0  
root 相對檔案名稱的根目錄。    
lastModified Last-Modified 標頭設定為檔案在作業系統上的最後修改日期。設定為 false 以停用。 已啟用 4.9.0+
headers 包含要與檔案一起提供的 HTTP 標頭的物件。    
dotfiles 提供 dotfiles 的選項。可能的值為「allow」、「deny」、「ignore」。 「忽略」  
acceptRanges 啟用或停用接受範圍要求。 true 4.14+
cacheControl 啟用或停用設定 Cache-Control 回應標頭。 true 4.14+
immutable Cache-Control 回應標頭中啟用或停用 immutable 指令。如果啟用,也應指定 maxAge 選項以啟用快取。immutable 指令將防止受支援的用戶端在 maxAge 選項的生命週期內提出條件式請求,以檢查檔案是否已變更。 false 4.16+

傳輸完成或發生錯誤時,此方法會呼叫回呼函式 fn(err)。如果指定了回呼函式,且發生錯誤,回呼函式必須明確處理回應程序,方法是結束請求回應循環,或將控制權傳遞給下一個路由。

以下是使用 res.sendFile 及其所有參數的範例。

app.get('/file/:name', (req, res, next) => {
  const options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  }

  const fileName = req.params.name
  res.sendFile(fileName, options, (err) => {
    if (err) {
      next(err)
    } else {
      console.log('Sent:', fileName)
    }
  })
})

以下範例說明如何使用 res.sendFile 提供精細的檔案提供支援

app.get('/user/:uid/photos/:file', (req, res) => {
  const uid = req.params.uid
  const file = req.params.file

  req.user.mayViewFilesFrom(uid, (yes) => {
    if (yes) {
      res.sendFile(`/uploads/${uid}/${file}`)
    } else {
      res.status(403).send("Sorry! You can't see that.")
    }
  })
})

如需更多資訊,或如果您有任何問題或疑慮,請參閱 send

res.sendStatus(statusCode)

將回應 HTTP 狀態碼設定為 statusCode,並將註冊的狀態訊息傳送為文字回應主體。如果指定了未知的狀態碼,回應主體將僅為代碼號碼。

res.sendStatus(404)

某些版本的 Node.js 會在將 res.statusCode 設定為無效的 HTTP 狀態碼(超出 100599 的範圍)時擲回例外。請參閱所使用 Node.js 版本的 HTTP 伺服器文件。

更多關於 HTTP 狀態碼

res.set(field [, value])

將回應的 HTTP 標頭 field 設定為 value。若要一次設定多個欄位,請傳遞一個物件作為參數。

res.set('Content-Type', 'text/plain')

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345'
})

別名為 res.header(field [, value])

res.status(code)

設定回應的 HTTP 狀態。它是 Node 的 response.statusCode 的可串接別名。

res.status(403).end()
res.status(400).send('Bad Request')
res.status(404).sendFile('/absolute/path/to/404.png')

res.type(type)

Content-Type HTTP 標頭設定為由指定的 type 所決定的 MIME 類型。如果 type 包含 “/” 字元,則將 Content-Type 設定為 type 的確切值,否則假設它為檔案副檔名,並使用 express.static.mime.lookup() 方法在對應中查詢 MIME 類型。

res.type('.html') // => 'text/html'
res.type('html') // => 'text/html'
res.type('json') // => 'application/json'
res.type('application/json') // => 'application/json'
res.type('png') // => image/png:

res.vary(field)

如果 Vary 回應標頭中尚未存在該欄位,則將該欄位新增至其中。

res.vary('User-Agent').render('docs')

路由器

router 物件是中介軟體和路由的獨立執行個體。您可以將它視為一個「迷你應用程式」,只能執行中介軟體和路由功能。每個 Express 應用程式都有一個內建的應用程式路由器。

路由器本身就像中介軟體一樣,因此您可以將它用作 app.use() 的引數,或作為另一個路由器的 use() 方法的引數。

頂層 express 物件有一個 Router() 方法,用於建立新的 router 物件。

建立路由器物件後,您可以像應用程式一樣,向其中新增中介軟體和 HTTP 方法路由(例如 getputpost 等)。例如

// invoked for any requests passed to this router
router.use((req, res, next) => {
  // .. some logic here .. like any other middleware
  next()
})

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', (req, res, next) => {
  // ..
})

您可以在特定根 URL 中使用路由器,將路由區分到檔案中,甚至區分到迷你應用程式中。

// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router)

方法

router.all(path, [callback, ...] callback)

此方法就像 router.METHOD() 方法,只不過它符合所有 HTTP 方法(動詞)。

此方法對於對應特定路徑前綴或任意符合項的「全域」邏輯非常有用。例如,如果您將下列路由置於所有其他路由定義的最上方,則會要求從該點開始的所有路由都需要驗證,並自動載入使用者。請記住,這些回呼不必作為終點作用;loadUser 可以執行一項工作,然後呼叫 next() 以繼續符合後續路由。

router.all('*', requireAuthentication, loadUser)

或等效於

router.all('*', requireAuthentication)
router.all('*', loadUser)

另一個範例是白名單「全域」功能。此範例與之前很像,但它只限制以「/api」為字首的路徑

router.all('/api/*', requireAuthentication)

router.METHOD(path, [callback, ...] callback)

router.METHOD() 方法提供 Express 中的路由功能,其中 METHOD 是 HTTP 方法之一,例如 GET、PUT、POST 等,以小寫表示。因此,實際的方法為 router.get()router.post()router.put() 等。

如果在 router.get() 之前未針對路徑呼叫 router.head(),則除了 GET 方法之外,router.get() 函式也會自動針對 HTTP HEAD 方法呼叫。

您可以提供多個回呼,所有回呼都以相同方式處理,而且表現得就像中介軟體一樣,只不過這些回呼可能會呼叫 next('route') 以略過其餘的路由回呼。您可以使用這個機制對路由執行前置條件,然後在沒有理由繼續進行已配對的路由時將控制權傳遞給後續路由。

下列程式碼片段說明最簡單的路由定義。Express 會將路徑字串轉換為正規表示式,用於內部比對傳入的請求。執行這些比對時不會考慮查詢字串,例如「GET /」會比對下列路由,而「GET /?name=tobi」也會比對。

router.get('/', (req, res) => {
  res.send('hello world')
})

您也可以使用正規表示式,這在您有非常具體的限制時很有用,例如下列範例會比對「GET /commits/71dbb9c」以及「GET /commits/71dbb9c..4c084f9」。

router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, (req, res) => {
  const from = req.params[0]
  const to = req.params[1] || 'HEAD'
  res.send(`commit range ${from}..${to}`)
})

您可以使用 next 基本元件根據特定程式狀態在不同的中介軟體函式之間實作流程控制。使用字串 'router' 呼叫 next 會導致略過該路由器上所有其餘的路由回呼。

下列範例說明 next('router') 的用法。

function fn (req, res, next) {
  console.log('I come here')
  next('router')
}
router.get('/foo', fn, (req, res, next) => {
  console.log('I dont come here')
})
router.get('/foo', (req, res, next) => {
  console.log('I dont come here')
})
app.get('/foo', (req, res) => {
  console.log(' I come here too')
  res.end('good')
})

router.param(name, callback)

將回呼觸發器新增至路由參數,其中 name 為參數名稱,而 callback 為回呼函式。儘管技術上 name 是選用的,但從 Express v4.11.0 開始,不使用此方法會被視為已棄用(請見下方)。

回呼函式的參數為

  • req,要求物件。
  • res,回應物件。
  • next,表示下一個中介軟體函式。
  • name 參數的值。
  • 參數的名稱。

app.param() 不同,router.param() 不接受路由參數陣列。

例如,當路由路徑中存在 :user 時,您可以將使用者載入邏輯對應至自動提供 req.user 至路由,或對參數輸入執行驗證。

router.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})

參數回呼函式是定義它們的路由器本地的。它們不會被掛載的應用程式或路由器繼承。因此,在 router 上定義的參數回呼只會由在 router 路由上定義的路由參數觸發。

即使參數在多個路由中相符,參數回呼在請求回應週期中只會被呼叫一次,如下列範例所示。

router.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE')
  next()
})

router.get('/user/:id', (req, res, next) => {
  console.log('although this matches')
  next()
})

router.get('/user/:id', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42 中,會印出下列內容

CALLED ONLY ONCE
although this matches
and this matches too

下列區段說明 router.param(callback),它在 v4.11.0 中已棄用。

router.param(name, callback) 方法的行為可以透過僅傳遞函式至 router.param() 而完全改變。此函式是 router.param(name, callback) 應如何運作的客製化實作 - 它接受兩個參數,且必須傳回中介軟體。

此函式的第一個參數是應擷取的 URL 參數名稱,第二個參數可以是任何用於傳回中介軟體實作的 JavaScript 物件。

函式傳回的中介軟體決定擷取 URL 參數時會發生什麼事。

在此範例中,router.param(name, callback) 簽章修改為 router.param(name, accessId)router.param() 現在會接受名稱和數字,而不是接受名稱和回呼。

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

// customizing the behavior of router.param()
router.param((param, option) => {
  return (req, res, next, val) => {
    if (val === option) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

// using the customized router.param()
router.param('id', 1337)

// route to trigger the capture
router.get('/user/:id', (req, res) => {
  res.send('OK')
})

app.use(router)

app.listen(3000, () => {
  console.log('Ready')
})

在此範例中,router.param(name, callback) 簽章保持不變,但已定義自訂資料類型檢查函式來驗證使用者 ID 的資料類型,而不是中間軟體回呼。

router.param((param, validator) => {
  return (req, res, next, val) => {
    if (validator(val)) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

router.param('id', (candidate) => {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate)
})

router.route(path)

傳回單一路由的執行個體,然後您可以使用它來處理 HTTP 動詞(搭配選用中間軟體)。使用 router.route() 來避免重複路由命名,進而避免輸入錯誤。

根據上述 router.param() 範例,下列程式碼顯示如何使用 router.route() 來指定各種 HTTP 方法處理常式。

const router = express.Router()

router.param('user_id', (req, res, next, id) => {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id,
    name: 'TJ'
  }
  next()
})

router.route('/users/:user_id')
  .all((req, res, next) => {
  // runs for all HTTP verbs first
  // think of it as route specific middleware!
    next()
  })
  .get((req, res, next) => {
    res.json(req.user)
  })
  .put((req, res, next) => {
  // just an example of maybe updating the user
    req.user.name = req.params.name
    // save user ... etc
    res.json(req.user)
  })
  .post((req, res, next) => {
    next(new Error('not implemented'))
  })
  .delete((req, res, next) => {
    next(new Error('not implemented'))
  })

此方法會重複使用單一 /users/:user_id 路徑,並為各種 HTTP 方法新增處理常式。

注意:當您使用 router.route() 時,中間軟體排序會根據建立路由的時間為依據,而不是根據將方法處理常式新增至路由的時間為依據。基於此目的,您可以將方法處理常式視為屬於新增至該處理常式的路由。

router.use([path], [function, ...] function)

使用指定的選用掛載路徑 path(預設為「/」)的中間軟體函式或函式。

此方法類似於 app.use()。下方說明簡單的範例和使用案例。如需更多資訊,請參閱 app.use()

中間軟體就像水管:要求會從定義的第一個中間軟體函式開始,並針對它們符合的每個路徑向下處理中間軟體堆疊。

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

// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use((req, res, next) => {
  console.log('%s %s %s', req.method, req.url, req.path)
  next()
})

// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', (req, res, next) => {
  // ... maybe some additional /bar logging ...
  next()
})

// always invoked
router.use((req, res, next) => {
  res.send('Hello World')
})

app.use('/foo', router)

app.listen(3000)

「掛載」路徑會被移除,而且中間軟體函式不會看到它。此功能的主要效用是,掛載的中間軟體函式可以運作,而不用變更程式碼,不論其「前置」路徑名稱為何。

使用 router.use() 定義中間件的順序非常重要。它們會按順序呼叫,因此順序會定義中間件的優先順序。例如,記錄器通常是你會使用的第一個中間件,這樣每個請求都會記錄下來。

const logger = require('morgan')

router.use(logger())
router.use(express.static(path.join(__dirname, 'public')))
router.use((req, res) => {
  res.send('Hello')
})

現在假設你想要忽略對靜態檔案的記錄請求,但要繼續記錄在 logger() 之後定義的路由和中間件。你只需將呼叫移到 express.static() 的頂端,然後再新增記錄器中間件

router.use(express.static(path.join(__dirname, 'public')))
router.use(logger())
router.use((req, res) => {
  res.send('Hello')
})

另一個範例是從多個目錄提供檔案,讓「./public」優先於其他目錄

app.use(express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'files')))
app.use(express.static(path.join(__dirname, 'uploads')))

router.use() 方法也支援命名參數,以便其他路由器的掛載點可以受益於使用命名參數進行預載入。

注意:雖然這些中間件函式是透過特定路由器新增的,但它們的執行時機是由它們附加的路徑(而非路由器)定義的。因此,透過一個路由器新增的中間件可能會執行於其他路由器,如果其路由相符的話。例如,這個程式碼顯示兩個不同的路由器掛載在同一路徑上

const authRouter = express.Router()
const openRouter = express.Router()

authRouter.use(require('./authenticate').basic(usersdb))

authRouter.get('/:user_id/edit', (req, res, next) => {
  // ... Edit user UI ...
})
openRouter.get('/', (req, res, next) => {
  // ... List users ...
})
openRouter.get('/:user_id', (req, res, next) => {
  // ... View user ...
})

app.use('/users', authRouter)
app.use('/users', openRouter)

即使驗證中間件是透過 authRouter 新增的,它也會執行於 openRouter 定義的路由上,因為兩個路由器都掛載在 /users 上。若要避免這種行為,請為每個路由器使用不同的路徑。