黑人生命至上。
支持平等正義倡議.

Express 3.x 不再維護

3.x 中已知和未知的安全和效能問題自上次更新(2015 年 8 月 1 日)以來尚未解決。強烈建議使用最新版本的 Express。

3.x API

express()

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

var express = require('express')
var app = express()

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

app.listen(3000)

應用程式

app.set(name, value)

將設定 name 指定給 value

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

app.get(name)

取得設定 name 的值。

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

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

app.enable(name)

將設定 name 設為 true

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

app.disable(name)

將設定 name 設為 false

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

app.enabled(name)

檢查設定 name 是否已啟用。

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

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

app.disabled(name)

檢查設定 name 是否已停用。

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

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

app.configure([env], callback)

envapp.get('env'),也就是 process.env.NODE_ENV 相符時,有條件地呼叫 callback。此方法基於傳統原因而保留,實際上是 if 陳述式,如下列程式片段所示。若要使用 app.set() 和其他組態方法,不需要這些函式。

// all environments
app.configure(function () {
  app.set('title', 'My Application')
})

// development only
app.configure('development', function () {
  app.set('db uri', 'localhost/dev')
})

// production only
app.configure('production', function () {
  app.set('db uri', 'n.n.n.n/prod')
})

實際上是對下列內容的語法糖

// all environments
app.set('title', 'My Application')

// development only
if (app.get('env') === 'development') {
  app.set('db uri', 'localhost/dev')
}

// production only
if (app.get('env') === 'production') {
  app.set('db uri', 'n.n.n.n/prod')
}

app.use([path], function)

使用指定的 middleware function,並可選擇掛載 path,預設為「/」。

var express = require('express')
var app = express()

// simple logger
app.use(function (req, res, next) {
  console.log('%s %s', req.method, req.url)
  next()
})

// respond
app.use(function (req, res, next) {
  res.send('Hello World')
})

app.listen(3000)

「掛載」路徑會被移除,而且 middleware function 看不到 該路徑。此功能的主要效果是,已掛載的 middleware 可以運作,而不管其「前置」路徑名稱為何,都不需要變更程式碼。

路由會比對緊接在路徑之後、且包含「/」或「.」的任何路徑。例如:app.use('/apple', ...) 會比對 /apple/apple/images/apple/images/news/apple.html/apple.html.txt 等。

以下是一個具體範例,採用使用 express.static() middleware 在 ./public 中提供檔案的典型使用案例

// GET /javascripts/jquery.js
// GET /style.css
// GET /favicon.ico
app.use(express.static(path.join(__dirname, 'public')))

假設您想要使用「/static」為所有靜態檔案加上前置字元,您可以使用「掛載」功能來支援此功能。除非 req.url 包含此前置字元,否則不會呼叫已掛載的 middleware 函式,而當函式被呼叫時,會移除前置字元。這只會影響此函式,後續 middleware 會看到包含「/static」的 req.url,除非它們也已掛載。

// GET /static/javascripts/jquery.js
// GET /static/style.css
// GET /static/favicon.ico
app.use('/static', express.static(path.join(__dirname, 'public')))

使用 app.use()「定義」middleware 的順序非常重要,它們會依序呼叫,因此這會定義 middleware 的優先順序。例如,通常 express.logger() 會是您會使用的第一個 middleware,用來記錄每個要求

app.use(express.logger())
app.use(express.static(path.join(__dirname, 'public')))
app.use(function (req, res) {
  res.send('Hello')
})

現在假設您想要忽略靜態檔案的記錄請求,但繼續記錄在 logger() 之後定義的路由和中間件,您只需將 static() 移到上面

app.use(express.static(path.join(__dirname, 'public')))
app.use(express.logger())
app.use(function (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')))

設定

提供下列設定來變更 Express 的行為

  • env 環境模式,預設為 process.env.NODE_ENV 或「development」
  • trust proxy 啟用反向代理支援,預設為停用
  • jsonp callback name 變更預設的回呼名稱 ?callback=
  • json replacer JSON replacer 回呼,預設為 null
  • json spaces JSON 回應的格式化空白,在開發環境中預設為 2,在生產環境中預設為 0
  • case sensitive routing 啟用大小寫敏感性,預設為停用,將「/Foo」和「/foo」視為相同
  • strict routing 啟用嚴格路由,預設情況下,路由器將「/foo」和「/foo/」視為相同
  • view cache 啟用檢視範本編譯快取,在生產環境中預設為啟用
  • view engine 省略時要使用的預設引擎擴充功能
  • views 檢視目錄路徑,預設為「process.cwd() + ‘/views’」

app.engine(ext, callback)

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

預設會根據檔案擴充功能 require() 引擎。例如,如果您嘗試呈現「foo.jade」檔案,Express 會在內部呼叫下列內容,並在後續呼叫中快取 require() 以提升效能。

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

對於未提供 .__express 的引擎,或如果你希望將不同的副檔名「對應」到範本引擎,你可以使用此方法。例如將 EJS 範本引擎對應到「.html」檔案

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

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

有些範本引擎不遵循此慣例,consolidate.js 函式庫是用來將所有節點的熱門範本引擎對應到此慣例,進而讓它們可以在 Express 中無縫運作。

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

app.param([name], callback)

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

以下程式碼片段說明 callback 與中間件非常類似,因此支援非同步作業,但提供參數的附加值,在此稱為 id。然後嘗試載入使用者,指定 req.user,否則將錯誤傳遞給 next(err)

app.param('user', function (req, res, next, id) {
  User.find(id, function (err, user) {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})

或者,你只能傳遞 callback,在這種情況下,你有機會變更 app.param() API。例如,express-params 定義下列 callback,它允許你將參數限制為特定的正規表示式。

此範例稍微進階一點,檢查第二個引數是否為正規表示式,傳回的 callback 與「使用者」參數範例非常類似。

app.param(function (name, fn) {
  if (fn instanceof RegExp) {
    return function (req, res, next, val) {
      var captures
      if ((captures = fn.exec(String(val)))) {
        req.params[name] = captures
        next()
      } else {
        next('route')
      }
    }
  }
})

現在可以使用此方法有效驗證參數,或將它們剖析以提供擷取群組

app.param('id', /^\d+$/)

app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id)
})

app.param('range', /^(\w+)\.\.(\w+)?$/)

app.get('/range/:range', function (req, res) {
  var range = req.params.range
  res.send('from ' + range[1] + ' to ' + range[2])
})

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

app.VERB() 方法提供 Express 中的路由功能,其中 VERB 是 HTTP 動詞之一,例如 app.post()。可以提供多個回呼,所有回呼都以相同的方式處理,且行為就像中間件,只有一個例外,這些回呼可能會呼叫 next('route') 以略過其餘的路由回呼。此機制可用於對路由執行前置條件,然後在沒有理由繼續執行已比對的路由時,將控制權傳遞給後續路由。

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

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

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

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

也可以傳遞多個回呼,這對於重複使用載入資源、執行驗證等中間件很有用。

app.get('/user/:id', user.load, function () {
  // ...
})

這些回呼也可以在陣列中傳遞,這些陣列在傳遞時會直接扁平化

var middleware = [loadForum, loadThread]

app.get('/forum/:fid/thread/:tid', middleware, function () {
  // ...
})

app.post('/forum/:fid/thread/:tid', middleware, function () {
  // ...
})

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

此方法的功能就像 app.VERB() 方法,但它會比對所有 HTTP 動詞。

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

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

或等效於

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

另一個此功能的絕佳範例是白名單「全域」功能。這裡的範例與之前非常類似,但僅限制以「/api」為前綴的路徑

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

app.locals

應用程式本機變數會提供給應用程式內所呈現的所有範本。這對於提供範本的輔助函數以及應用程式層級資料非常有用。

app.locals.title = 'My App'
app.locals.strftime = require('strftime')

app.locals 物件是一個 JavaScript 函數,當以一個物件呼叫時,會將屬性合併到自身,提供一個簡單的方式來將現有物件公開為本機變數。

app.locals({
  title: 'My App',
  phone: '1-250-858-9990',
  email: 'me@myapp.com'
})

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

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

由於 app.locals 物件最終是一個 JavaScript 函數物件,因此您不得重複使用現有 (原生) 命名屬性作為您自己的變數名稱,例如 name, apply, bind, call, arguments, length, constructor

app.locals({ name: 'My App' })

console.log(app.locals.name)
// => return 'app.locals' in place of 'My App' (app.locals is a Function !)
// => if name's variable is used in a template, a ReferenceError will be returned.

可以在許多規格中找到原生命名屬性的完整清單。 JavaScript 規格 介紹了原始屬性,其中一些仍由現代引擎識別,而 EcmaScript 規格 接著建立在它上面,並標準化屬性集,新增新的屬性並移除不建議使用的屬性。如果您有興趣,請查看函數和物件的屬性。

預設情況下,Express 僅公開一個應用程式層級本機變數,settings

app.set('title', 'My App')
// use settings.title in a view

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

使用回呼函式產生一個 view,並回應產生的字串。這是 res.render() 的應用程式層級變體,其他行為方式相同。

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

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

app.routes

app.routes 物件包含所有已定義路由,並由相關的 HTTP 動詞對應。此物件可用於內省功能,例如 Express 內部不只使用它來進行路由,還會提供預設

OPTIONS

除非使用 app.options(),否則會產生行為。您的應用程式或架構也可以透過從此物件中移除路由來移除路由。

console.log(app.routes) 的輸出

{ get:
   [ { path: '/',
       method: 'get',
       callbacks: [Object],
       keys: [],
       regexp: /^\/\/?$/i },
     { path: '/user/:id',
       method: 'get',
       callbacks: [Object],
       keys: [{ name: 'id', optional: false }],
       regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ],
  delete:
   [ { path: '/user/:id',
       method: 'delete',
       callbacks: [Object],
       keys: [Object],
       regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ] }

app.listen()

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

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

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

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

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

app.listen() 方法只是一個方便的方法,定義為,如果您想要使用 HTTPS 或同時提供,請使用上述技巧。

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

要求

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

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.query

此屬性為包含已剖析查詢字串的物件,預設為 {}

// GET /search?q=tobi+ferret
console.dir(req.query.q)
// => 'tobi ferret'

// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
console.dir(req.query.order)
// => 'desc'

console.dir(req.query.shoe.color)
// => 'blue'

console.dir(req.query.shoe.type)
// => 'converse'

req.body

此屬性為包含已剖析要求主體的物件。此功能由 bodyParser() 中介軟體提供,但其他主體剖析中介軟體也可能遵循此慣例。當使用 bodyParser() 時,此屬性預設為 {}

// POST user[name]=tobi&user[email]=tobi@learnboost.com
console.log(req.body.user.name)
// => "tobi"

console.log(req.body.user.email)
// => "tobi@learnboost.com"

// POST { "name": "tobi" }
console.log(req.body.name)
// => "tobi"

req.files

此屬性為已上傳檔案的物件。此功能由 bodyParser() 中介軟體提供,但其他主體剖析中介軟體也可能遵循此慣例。當使用 bodyParser() 時,此屬性預設為 {}

例如,如果一個 檔案 欄位命名為「image」,且已上傳一個檔案,則 req.files.image 將包含下列 File 物件

{ size: 74643,
  path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
  name: 'edge.png',
  type: 'image/png',
  hash: false,
  lastModifiedDate: Thu Aug 09 2012 20:07:51 GMT-0700 (PDT),
  _writeStream:
   { path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
     fd: 13,
     writable: false,
     flags: 'w',
     encoding: 'binary',
     mode: 438,
     bytesWritten: 74643,
     busy: false,
     _queue: [],
     _open: [Function],
     drainable: true },
  length: [Getter],
  filename: [Getter],
  mime: [Getter] }

bodyParser() 中介軟體在內部使用 node-formidable 模組,並接受相同的選項。一個範例是 keepExtensions formidable 選項,預設為 false,在本例中會提供不含「.png」副檔名的檔名「/tmp/8ef9c52abe857867fd0a4e9a819d1876」。若要啟用此選項和其他選項,您可以將它們傳遞給 bodyParser()

app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }))

req.param(name)

在存在時傳回參數 name 的值。

// ?name=tobi
req.param('name')
// => "tobi"

// POST name=tobi
req.param('name')
// => "tobi"

// /user/tobi for /user/:name
req.param('name')
// => "tobi"

查詢依下列順序執行

  • req.params
  • req.body
  • req.query

為清楚起見,應優先直接存取 req.bodyreq.paramsreq.query,除非您確實接受來自每個物件的輸入。

req.route

目前相符的 Route,包含多個屬性,例如路由的原始路徑字串、產生的正規表示法等。

app.get('/user/:id?', function (req, res) {
  console.dir(req.route)
})

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

{ path: '/user/:id?',
  method: 'get',
  callbacks: [ [Function] ],
  keys: [ { name: 'id', optional: true } ],
  regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
  params: [ id: '12' ] }

req.cookies

此物件需要 cookieParser() 中介軟體才能使用。它包含使用者代理程式傳送的 Cookie。如果未傳送任何 Cookie,則預設為 {}

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

req.signedCookies

此物件需要 cookieParser(secret) 中介軟體才能使用。它包含使用者代理程式傳送的已簽署 cookie,未簽署且已準備好使用。已簽署的 cookie 會駐留在不同的物件中,以顯示開發人員的意圖;否則,惡意攻擊可能會放置在 req.cookie 值上(很容易偽造)。請注意,簽署 cookie 並不會讓它「隱藏」或加密;這只是防止竄改(因為用於簽署的密碼是私密的)。如果未傳送已簽署的 cookie,它會預設為 {}

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

req.get(field)

取得不分大小寫的請求標頭 field。「Referrer」和「Referer」欄位可以互換。

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

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

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

p 別名為 req.header(field)

req.accepts(types)

檢查指定的 types 是否可接受,如果為真,則傳回最佳配對,否則為 undefined - 在這種情況下,您應該回應 406「不可接受」。

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')
// => undefined

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

req.accepted

傳回一個已接受的媒體類型陣列,從最高品質到最低品質排序。

[ { value: 'application/json',
    quality: 1,
    type: 'application',
    subtype: 'json' },
   { value: 'text/html',
     quality: 0.5,
     type: 'text',
     subtype: 'html' } ]

req.is(type)

檢查傳入的請求是否包含「Content-Type」標頭欄位,以及它是否與給定的 MIME type 相符。

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

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

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

req.ip

傳回遠端位址,或當「信任代理程式」已啟用時 - 上游位址。

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

req.ips

當「信任代理程式」為 true 時,剖析「X-Forwarded-For」IP 位址清單並傳回一個陣列,否則會傳回一個空陣列。

例如,如果值為「client, proxy1, proxy2」,您會收到陣列 ["client", "proxy1", "proxy2"],其中「proxy2」是最下游的。

req.path

傳回請求 URL 路徑名稱。

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

req.host

從「Host」標頭欄位傳回主機名稱(不含埠號)。

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

req.fresh

檢查請求是否為最新 - 也稱為 Last-Modified 和/或 ETag 仍相符,表示資源為「最新」。

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

req.stale

檢查請求是否為過期 - 也稱為 Last-Modified 和/或 ETag 不相符,表示資源為「過期」。

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

req.xhr

檢查請求是否已發出,且「X-Requested-With」標頭欄位設定為「XMLHttpRequest」(jQuery 等)。

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

req.protocol

當使用 TLS 請求時,傳回通訊協定字串「http」或「https」。當啟用「信任代理」設定時,將會信任「X-Forwarded-Proto」標頭欄位。如果您在後端執行提供 https 給您的反向代理程式,則可能會啟用此設定。

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

req.secure

檢查是否已建立 TLS 連線。這是

console.dir(req.protocol === 'https')
// => true

req.subdomains

將子網域傳回為陣列。

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

req.originalUrl

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

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

req.acceptedLanguages

傳回已接受語言的陣列,從最高品質到最低品質排序。

Accept-Language: en;q=.5, en-us
// => ['en-us', 'en']

req.acceptedCharsets

傳回已接受字元集的陣列,從最高品質到最低品質排序。

Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
// => ['unicode-1-1', 'iso-8859-5']

req.acceptsCharset(charset)

檢查指定的 charset 是否可接受。

req.acceptsLanguage(lang)

檢查指定的 lang 是否可接受。

req.res

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

回應

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

res.status(code)

Node 的 res.statusCode= 的可串接別名。

res.status(404).sendfile('path/to/404.png')

res.set(欄位, [值])

將標頭 欄位 設定為 ,或傳遞物件以一次設定多個欄位。

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

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

別名為 res.header(欄位, [值])

res.get(欄位)

取得不分大小寫的回應標頭 欄位

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

res.cookie(名稱, 值, [選項])

將 cookie 名稱 設定為 ,可以是轉換為 JSON 的字串或物件。路徑 選項預設為「/」。

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

maxAge 選項是方便的選項,用於設定相對於目前時間的「過期時間」,單位為毫秒。以下範例等同於前一個範例。

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

可以傳遞物件,然後序列化為 JSON,bodyParser() 中介軟體會自動解析。

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

此方法也支援已簽署的 cookie。只要傳遞 已簽署 選項即可。當給定 res.cookie() 時,將使用傳遞給 express.cookieParser(秘密) 的秘密來簽署值。

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

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

res.clearCookie(名稱, [選項])

清除 cookie 名稱路徑 選項預設為「/」。

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

res.redirect([狀態], 網址)

重新導向到指定的 網址,選用的 狀態 碼預設為 302「已找到」。

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

Express 支援幾種重新導向形式,首先是完全限定的 URI,用於重新導向到不同的網站

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

第二種形式是路徑名稱相對重新導向,例如如果您在 http://example.com/admin/post/new,以下重新導向到 /admin 會將您帶到 http://example.com/admin

res.redirect('/admin')

下一個重新導向是相對於應用程式的 掛載 點。例如,如果您有一個掛載在 /blog 的部落格應用程式,理想情況下它不知道它掛載在哪裡,因此重新導向 /admin/post/new 只會提供給您 http://example.com/admin/post/new,以下掛載相對重新導向會提供給您 http://example.com/blog/admin/post/new

res.redirect('admin/post/new')

路徑名稱相對重定向也是可能的。如果您在http://example.com/admin/post/new,以下重定向會將您帶到http//example.com/admin/post

res.redirect('..')

最後一個特殊情況是back重定向,重定向回參考者 (或引導者),在遺失時預設為/

res.redirect('back')

res.location

設定位置標頭。

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

您可以使用與res.redirect()中相同的urls類型。

例如,如果您的應用程式掛載在/blog,以下會將location標頭設定為/blog/admin

res.location('admin')

res.charset

指定字元集。預設為“utf-8”。

res.charset = 'value'
res.send('<p>some html</p>')
// => Content-Type: text/html; charset=value

res.send([body|status], [body])

傳送回應。

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

此方法執行許多對簡單非串流回應有用的工作,例如自動指定內容長度,除非先前已定義,並提供自動HEAD和 HTTP 快取新鮮度支援。

當給定Buffer時,內容類型會設定為“application/octet-stream”,除非先前已定義,如下所示

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

當給定String時,內容類型預設設定為“text/html”

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

當給定ArrayObject時,Express 會回應 JSON 表示。

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

最後,當給定Number而沒有任何先前提到的主體時,會為您指定回應主體字串。例如,200 會回應文字“OK”,404 會回應“Not Found”,依此類推。

res.send(200)
res.send(404)
res.send(500)

res.json([status|body], [body])

傳送 JSON 回應。當傳遞物件或陣列時,此方法與res.send()相同,但可用於非物件的明確 JSON 轉換 (null、未定義等),儘管這些在技術上不是有效的 JSON。

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

res.jsonp([status|body], [body])

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

res.jsonp(null)
// => null

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

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

預設情況下,JSONP 回呼名稱只是callback,但您可以使用jsonp 回呼名稱設定來變更它。以下是使用相同程式碼的一些 JSONP 回應範例

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

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

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

res.type(type)

將 Content-Type 設定為 type 的 mime 查詢,或當出現「/」時,Content-Type 僅設定為此文字值。

res.type('.html')
res.type('html')
res.type('json')
res.type('application/json')
res.type('png')

p 別名為 res.contentType(type)

res.format(object)

當存在時,對要求的 Accept 標頭欄位執行內容協商。此方法使用 req.accepted,一個依品質值排序的可接受類型陣列,否則會呼叫第一個回呼。當沒有執行配對時,伺服器會回應 406「無法接受」,或呼叫 default 回呼。

當選取回呼時,Content-Type 會為您設定,但您可以在回呼中使用 res.set()res.type() 等變更此設定。

當 Accept 標頭欄位設定為「application/json」或「/json」時,以下範例會回應 { "message": "hey" },但如果給定「/*」,則「hey」將會是回應。

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

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

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

除了正規化的 MIME 類型外,您也可以使用對應到這些類型的 extname,提供一個簡潔許多的實作

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

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

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

res.attachment([filename])

將 Content-Disposition 標頭欄位設定為「attachment」。如果給定 filename,則 Content-Type 會自動根據 extname 透過 res.type() 設定,且 Content-Disposition 的「filename=」參數會設定。

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

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

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

傳輸給定 path 的檔案。

根據檔案名稱的副檔名自動預設 Content-Type 回應標頭欄位。當傳輸完成或發生錯誤時,會呼叫回呼 fn(err)

選項

  • maxAge 以毫秒為單位,預設為 0
  • root 相對檔案名稱的根目錄

此方法提供細緻的檔案提供支援,如下列範例所示

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

  req.user.mayViewFilesFrom(uid, function (yes) {
    if (yes) {
      res.sendfile('/uploads/' + uid + '/' + file)
    } else {
      res.send(403, 'Sorry! you cant see that.')
    }
  })
})

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

將檔案傳輸至 路徑 作為「附件」,瀏覽器通常會提示使用者下載。Content-Disposition 的「filename=」參數,也就是會顯示在瀏覽器對話框中的參數,預設會設定為 路徑,不過你可以提供替代的 檔名

當發生錯誤或傳輸完成時,會呼叫選用的回呼 fn。此方法使用 res.sendfile() 傳輸檔案。

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

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

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

加入指定的 連結 以填入「連結」回應標頭欄位。

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

p 產生

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

res.locals

回應的區域變數會限定在要求中,因此只有在該要求 / 回應週期中呈現的檢視才能使用,如果有任何檢視的話。否則,此 API 與 app.locals 相同。

此物件對於公開要求層級資訊(例如要求路徑名稱、經過驗證的使用者、使用者設定等)很有用。

app.use(function (req, res, next) {
  res.locals.user = req.user
  res.locals.authenticated = !req.user.anonymous
  next()
})

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

使用回呼呈現 檢視,回應呈現的字串。當發生錯誤時,會在內部呼叫 next(err)。當提供回呼時,會傳遞可能的錯誤和呈現的字串,而且不會執行自動回應。

res.render('index', function (err, html) {
  // ...
})

res.render('user', { name: 'Tobi' }, function (err, html) {
  // ...
})

res.req

此屬性包含對應於此回應物件的 要求物件 的參考。

中間件

basicAuth()

基本驗證中介軟體,將 req.user 填入使用者名稱。

簡單的使用者名稱和密碼

app.use(express.basicAuth('username', 'password'))

回呼驗證

app.use(express.basicAuth(function (user, pass) {
  return user === 'tj' && pass === 'wahoo'
}))

非同步回呼驗證,接受 fn(err, user),在此情況下,req.user 會是傳遞的使用者物件。

app.use(express.basicAuth(function (user, pass, fn) {
  User.authenticate({ user: user, pass: pass }, fn)
}))

bodyParser()

要求主體剖析中介軟體,支援 JSON、URL 編碼和多部分要求。此中介軟體只是 json()urlencoded()multipart() 中介軟體的包裝器。

app.use(express.bodyParser())

// is equivalent to:
app.use(express.json())
app.use(express.urlencoded())
app.use(express.multipart())

基於安全性考量,如果應用程式不需要上傳檔案,最好停用檔案上傳功能。為此,請僅使用必要的中間件,亦即不要使用 bodyParsermultipart() 中間件

app.use(express.json())
app.use(express.urlencoded())

如果應用程式需要上傳檔案,您應該設定 處理這些檔案的策略

compress()

使用 gzip / deflate 壓縮回應資料。此中間件應置於堆疊中「較高」的位置,以確保所有回應都能壓縮。

app.use(express.logger())
app.use(express.compress())
app.use(express.methodOverride())
app.use(express.bodyParser())

cookieParser()

剖析 Cookie 標頭欄位,並使用 cookie 名稱作為鍵值,將物件填入 req.cookies。您也可以選擇透過傳遞 secret 字串來啟用簽署 cookie 支援功能。

app.use(express.cookieParser())
app.use(express.cookieParser('some secret'))

cookieSession()

提供基於 cookie 的工作階段,並填入 req.session。此中間件採用下列選項

  • key cookie 名稱,預設為 connect.sess
  • secret 防止 cookie 遭竄改
  • cookie 工作階段 cookie 設定,預設為 { path: '/', httpOnly: true, maxAge: null }
  • proxy 設定安全 cookie 時信任反向代理程式(透過「x-forwarded-proto」)
app.use(express.cookieSession())

若要清除 cookie,只需在回應之前將工作階段指定為 null

req.session = null

csrf()

CSRF 保護中間件。

預設情況下,此中間件會產生名為「_csrf」的 token,此 token 應加入到會變更狀態的請求中,例如隱藏的表單欄位、查詢字串等。此 token 會與 req.csrfToken() 進行驗證。

預設的 value 函式會檢查 bodyParser() 中間件產生的 req.bodyquery() 產生的 req.query,以及「X-CSRF-Token」標頭欄位。

此中間件需要工作階段支援,因此應新增在 session() 的下方。

directory()

目錄提供中間件,提供指定的 path。此中間件可以與 static() 配對使用,以提供檔案,提供功能齊全的檔案瀏覽器。

app.use(express.directory('public'))
app.use(express.static('public'))

此中間件接受下列選項

  • hidden 顯示隱藏的(點)檔案。預設為 false。
  • icons 顯示圖示。預設為 false。
  • filter 將此篩選函式套用至檔案。預設為 false。