express 4.x Api 中文版-最新中文詳細解釋

Address:https://www.zybuluo.com/XiangZhou/note/208532

Express 4.x API
express
翻譯
api文檔
中文

--

github地址,歡迎大家提交更新。

express()
express()
用來創建一個Express的程序。express()
方法是express模塊導出的頂層方法。

var express = require('express');

var app = express();

Methods

express.static(root, [options])
express.static
是Express中唯一的內建中間件。它以server-static模塊為基礎開發,負責托管 Express 應用內的靜態資源。 參數root
為靜態資源的所在的根目錄。 參數options
是可選的,支持以下的屬性:
屬性
描述
類型
默認值

dotfiles
是否響應點文件。供選擇的值有"allow","deny"和"ignore"
String
"ignore"

etag
使能或者關閉etag
Boolean
true

extensions
設置文件延期回退
Boolean
true

index
發送目錄索引文件。設置false將不發送。
Mixed
"index.html"

lastModified
設置文件在系統中的最后修改時間到Last-Modified
頭部。可能的取值有false
和true

Boolean
true

maxAge
在Cache-Control頭部中設置max-age
屬性,精度為毫秒(ms)或則一段ms format的字符串
Number
0

redirect
當請求的pathname是一個目錄的時候,重定向到尾隨"/"
Boolean
true

setHeaders
當響應靜態文件請求時設置headers的方法
Funtion

如果你想獲得更多關于使用中間件的細節,你可以查閱Serving static files in Express

Application()
app
對象一般用來表示Express程序。通過調用Express模塊導出的頂層的express()
方法來創建它:

var express = require('express');

var app = express();

app.get('/', function(req, res) {

res.send('hello world!');

});

app.listen(3000);

app
對象具有以下的方法:
路由HTTP請求;具體可以看app.METHODapp.param這兩個例子。
配置中間件;具體請看app.route
渲染HTML視圖;具體請看app.render
注冊模板引擎;具體請看app.engine

它還有一些屬性設置,這些屬性可以改變程序的行為。獲得更多的信息,可以查閱Application settings

Properties

app.locals
app.locals
對象是一個javascript對象,它的屬性就是程序本地的變量。

app.locals.title

// => 'My App'

app.locals.email

// => 'me@myapp.com'

一旦設定,app.locals
的各屬性值將貫穿程序的整個生命周期,與其相反的是res.locals
,它只在這次請求的生命周期中有效。
在程序中,你可以在渲染模板時使用這些本地變量。它們是非常有用的,可以為模板提供一些有用的方法,以及app
級別的數據。通過req.app.locals
(具體查看req.app),Locals可以在中間件中使用。

app.locals.title = 'My App';

app.locals.strftime = require('strftime');

app.locals.email = 'me@myapp.com';

app.mountpath
app.mountpath
屬性是子程序掛載的路徑模式。
一個子程序是一個express
的實例,其可以被用來作為路由句柄來處理請求。

var express = require('express');

var app = express(); // the main app

var admin = express(); // the sub app

admin.get('/', function(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
就是一個關于掛載路徑模式項的列表,如下面例子所示。

var admin = express();

admin.get('/', function(req, res) {

console.log(admin.mountpath); // ['adm*n', '/manager']

res.send('Admin Homepage');

});

var secret = express();

secret.get('/', function(req, res) {

console.log(secret.mountpath); // /secr*t

res.send('Admin secret');

});

admin.use('/secrt', secret); // load the 'secret' router on '/secrt', on the 'admin' sub app

app.use(['/admn', '/manager'], admin); // load the 'admin' router on '/admn' and '/manager' , on the parent app

Events

app.on('mount', callback(parent))
當子程序被掛載到父程序時,mount
事件被發射。父程序對象作為參數,傳遞給回調方法。

var admin = express();

admin.on('mount', function(parent) {

console.log('Admin Mounted');

console.log(parent); // refers to the parent app

});

admin.get('/', function(req, res) {

res.send('Admin Homepage');

});

app.use('/admin', admin);

Methods

app.all(path, callback[, callback ...]
app.all
方法和標準的app.METHOD()
方法相似,除了它匹配所有的HTTP動詞。 對于給一個特殊前綴映射一個全局的邏輯處理,或者無條件匹配,它是很有效的。例如,如果你把下面內容放在所有其他的路由定義的前面,它要求所有從這個點開始的路由需要認證和自動加載一個用戶。記住這些回調并不是一定是終點:loadUser
可以在完成了一個任務后,調用next()
方法來繼續匹配隨后的路由。

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

或者這種相等的形式:

app.all('*', requireAuthentication);

app.all('*', loadUser);

另一個例子是全局的白名單方法。這個例子和前面的很像,然而它只是限制以/api
開頭的路徑。

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

app.delete(path, callback[, callback ...])
路由HTTP DELETE
請求到有特殊回調方法的特殊的路徑。獲取更多的信息,可以查閱routing guide。 你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果不能滿足當前路由的處理條件,那么你可以傳遞控制到隨后的路由。

app.delete('/', function(req, res) {

res.send('DELETE request to homepage');

});

app.disable(name)
設置類型為布爾的設置名為name
的值為false
,此處的name
app settings table中各屬性的一個。調用app.set('foo', false)
和調用app.disable('foo')
是等價的。 比如:

app.disable('trust proxy');

app.get('trust proxy');

// => false

app.disabled(name)
返回true
如果布爾類型的設置值name
被禁用為false
,此處的name
app settings table中各屬性的一個。

app.disabled('trust proxy');

// => true

app.enable('trust proxy');

app.disabled('trust proxy');

// => false

app.enable(name)
設置布爾類型的設置值name
為true
,此處的name
app settings table中各屬性的一個。調用app.set('foo', true)
和調用app.enable('foo')
是等價的。

app.enable('trust proxy');

app.get('trust proxy');

// => true

app.enabled(name)
返回true
如果布爾類型的設置值name
被啟動為true
,此處的name
app settings table中各屬性的一個。

app.enabled('trust proxy');

// => false

app.enable('trust proxy');

app.enabled('trust proxy');

// => true

app.engine(ext, callback)
注冊給定引擎的回調,用來渲染處理ext文件。 默認情況下,Express需要使用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.get(name)
獲得設置名為name
的app設置的值,此處的name
app settings table中各屬性的一個。 如下:

app.get('title');

// => undefined

app.set('title', 'My Site');

app.get('title');

// => 'My Site'

app.get(path, callback [, callback ...])
路由HTTP GET
請求到有特殊回調的特殊路徑。獲取更多的信息,可以查閱routing guide。 你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒能滿足當前路由的處理條件,那么傳遞控制到隨后的路由。

app.get('/', function(req, res) {

res.send('GET request to homepage');

});

app.listen(port, [hostname], [backlog], [callback])
綁定程序監聽端口到指定的主機和端口號。這個方法和Node
中的http.Server.listen()是一樣的。

var express = require('express');

var app = express();

app.listen(3000);

通過調用express()
返回得到的app
實際上是一個JavaScript的Function
,被設計用來作為一個回調傳遞給Node HTTP servers
來處理請求。這樣,其就可以很簡便的基于同一份代碼提供http和https版本,所以app沒有從這些繼承(它只是一個簡單的回調)。

var express = require('express');

var https = require('https');

var http = require('http');

http.createServer(app).listen(80);

https.createServer(options, app).listen(443);

app.listen()
方法是下面所示的一個便利的方法(只針對HTTP協議):

app.listen = function() {

var server = http.createServer(this);

return server.listen.apply(server, arguments);

};

app.METHOD(path, callback [, callback ...])
路由一個HTTP請求,METHOD
是這個請求的HTTP方法,比如GET
,PUT
,POST
等等,注意是小寫的。所以,實際的方法是app.get()
,app.post()
,app.put()
等等。下面有關于方法的完整的表。 獲取更多信息,請看routing guide。 Express支持下面的路由方法,對應與同名的HTTP方法:
checkout
connect
copy
delete
get
head
lock
merge
mkactivity

mkcol
move
m-search
notify
options
patch
post
propfind
proppatch

purege
put
report
search
subscribe
trace
unlock
unsubscribe

如果使用上述方法時,導致了無效的javascript的變量名,可以使用中括號符號,比如,app['m-search']('/', function ...

你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒有滿足當前路由的處理條件,那么傳遞控制到隨后的路由。
本API文檔把使用比較多的HTTP方法app.get()
,app.post
,app.put()
,app.delete()
作為一個個單獨的項進行說明。然而,其他上述列出的方法以完全相同的方式工作。

app.all()
是一個特殊的路由方法,它不屬于HTTP協議中的規定的方法。它為一個路徑加載中間件,其對所有的請求方法都有效。

app.all('/secret', function (req, res) {

console.log('Accessing the secret section...');

next(); // pass control to the next handler

});

app.param([name], callback)
給路由參數添加回調觸發器,這里的name
是參數名或者參數數組,function
是回調方法。回調方法的參數按序是請求對象,響應對象,下個中間件,參數值和參數名。 如果name
是數組,會按照各個參數在數組中被聲明的順序將回調觸發器注冊下來。還有,對于除了最后一個參數的其他參數,在他們的回調中調用next()
來調用下個聲明參數的回調。對于最后一個參數,在回調中調用next()
將調用位于當前處理路由中的下一個中間件,如果name
只是一個string
那就和它是一樣的(就是說只有一個參數,那么就是最后一個參數,和數組中最后一個參數是一樣的)。 例如,當:user
出現在路由路徑中,你可以映射用戶加載的邏輯處理來自動提供req.user
給這個路由,或者對輸入的參數進行驗證。

app.param('user', function(req, res, next, id) {

User.find(id, function(error, user) {

if (err) {

next(err);

}

else if (user){

req.user = user;

} else {

next(new Error('failed to load user'));

}

});

});

對于Param
的回調定義的路由來說,他們是局部的。它們不會被掛載的app或者路由繼承。所以,定義在app
上的Param
回調只有是在app
上的路由具有這個路由參數時才起作用。 在定義param
的路由上,param
回調都是第一個被調用的,它們在一個請求-響應循環中都會被調用一次并且只有一次,即使多個路由都匹配,如下面的例子:

app.param('id', function(req, res, next, id) {

console.log('CALLED ONLY ONCE');

next();

});

app.get('/user/:id', function(req, res, next) {

console.log('although this matches');

next();

});

app.get('/user/:id', function(req, res) {

console.log('and this mathces too');

res.end();

});

當GET /user/42
,得到下面的結果:

CALLED ONLY ONCE

although this matches

and this matches too

app.param(['id', 'page'], function(req, res, next, value) {

console.log('CALLED ONLY ONCE with', value);

next();

});

app.get('/user/:id/:page', function(req. res, next) {

console.log('although this matches');

next();

});

app.get('/user/:id/:page', function (req, res, next) {

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 mathes too

下面章節描述的app.param(callback)
在v4.11.0之后被棄用。

通過只傳遞一個回調參數給app.param(name, callback)
方法,app.param(naem, callback)
方法的行為將被完全改變。這個回調參數是關于app.param(name, callback)
該具有怎樣的行為的一個自定義方法,這個方法必須接受兩個參數并且返回一個中間件。 這個回調的第一個參數就是需要捕獲的url的參數名,第二個參數可以是任一的JavaScript對象,其可能在實現返回一個中間件時被使用。 這個回調方法返回的中間件決定了當URL中包含這個參數時所采取的行為。 在下面的例子中,app.param(name, callback)
參數簽名被修改成了app.param(name, accessId)
。替換接受一個參數名和回調,app.param()
現在接受一個參數名和一個數字。

var express = require('express');

var app = express();

app.param(function(param, option){

return function(req, res, next, val) {

if (val == option) {

next();

}

else {

res.sendStatus(403);

}

}

});

app.param('id', 1337);

app.get('/user/:id', function(req, res) {

res.send('Ok');

});

app.listen(3000, function() {

console.log('Ready');

});

在這個例子中,app.param(name, callback)
參數簽名保持和原來一樣,但是替換成了一個中間件,定義了一個自定義的數據類型檢測方法來檢測user id
的類型正確性。

app.param(function(param, validator) {

return function(req, res, next, val) {

if (validator(val)) {

next();

}

else {

res.sendStatus(403);

}

}

});

app.param('id', function(candidate) {

return !isNaN(parseFloat(candidate)) && isFinite(candidate);

});

在使用正則表達式來,不要使用.
。例如,你不能使用/user-.+/
來捕獲user-gami
,用使用[\s\S]
或者[\w\>W]
來代替(正如/user-[\s\S]+/
)。
//captures '1-a_6' but not '543-azser-sder'

router.get('/[0-9]+-[[\w]]*', function);

//captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'

router.get('/[0-9]+-[[\S]]*', function);

//captures all (equivalent to '.*')

router.get('[[\s\S]]*', function);

app.path()
通過這個方法可以得到app
典型的路徑,其是一個string

var app = express()

, blog = express()

, blogAdmin = express();

app.use('/blog', blog);

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

console.log(app.path()); // ''

console.log(blog.path()); // '/blog'

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

如果app
掛載很復雜下,那么這個方法的行為也會很復雜:一種更好用的方式是使用req.baseUrl
來獲得這個app的典型路徑。

app.post(path, callback, [callback ...])
路由HTTP POST
請求到有特殊回調的特殊路徑。獲取更多的信息,可以查閱routing guide。 你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒能滿足當前路由的處理條件,那么傳遞控制到隨后的路由。

app.post('/', function(req, res) {

res.send('POST request to homepage')

});

app.put(path, callback, [callback ...])
路由HTTP PUT
請求到有特殊回調的特殊路徑。獲取更多的信息,可以查閱routing guide。 你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒能滿足當前路由的處理條件,那么傳遞控制到隨后的路由。

app.put('/', function(req, res) {

res.send('PUT request to homepage');

});

app.render(view, [locals], callback)
通過callback
回調返回一個view
渲染之后得到的HTML文本。它可以接受一個可選的參數,可選參數包含了這個view
需要用到的本地數據。這個方法類似于res.render()
,除了它不能把渲染得到的HTML文本發送給客戶端。
將app.render()
當作是可以生成渲染視圖字符串的工具方法。在res.render()
內部,就是使用的app.render()
來渲染視圖。
如果使能了視圖緩存,那么本地變量緩存就會保留。如果你想在開發的過程中緩存視圖,設置它為true
。在生產環境中,視圖緩存默認是打開的。

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

// ...

});

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

// ...

});

app.route(path)
返回一個單例模式的路由的實例,之后你可以在其上施加各種HTTP動作的中間件。使用app.route()
來避免重復路由名字(因此錯字錯誤)--說的意思應該是使用app.router()
這個單例方法來避免同一個路徑多個路由實例。

var app = express();

app.route('/events')

.all(function(req, res, next) {

// runs for all HTTP verbs first

// think of it as route specific middleware!

})

.get(function(req, res, next) {

res.json(...);

})

.post(function(req, res, next) {

// maybe add a new event...

})

app.set(name, value)
給name
設置項賦value
值,name
app settings table中屬性的一項。 對于一個類型是布爾型的屬性調用app.set('foo', ture)
等價于調用app.enable('foo')
。同樣的,調用app.set('foo', false)
等價于調用app.disable('foo')
。 可以使用app.get()
來取得設置的值:

app.set('title', 'My Site');

app.get('title'); // 'My Site'

Application Settings 如果name
是程序設置之一,它將影響到程序的行為。下邊列出了程序中的設置。
Property
Type
Value
Default

case sensitive routing
Boolean
啟用區分大小寫。
不啟用。對/Foo
和/foo
處理是一樣。

env
String
環境模型。
process.env.NODE_ENV(NODE_ENV環境變量)或者"development"

etag
Varied
設置ETag
響應頭。可取的值,可以查閱etag options table。更多關于HTTP ETag header
weak

jsonp callback name
String
指定默認JSONP回調的名稱。
?callback=

json replacer
String
JSON替代品回調
null

json spaces
Number
當設置了這個值后,發送縮進空格美化過的JSON字符串。
Disabled

query parser
Varied
設置值為false
來禁用query parser
,或者設置simple
,extended
,也可以自己實現query string
解析函數。simple
基于Node
原生的query
解析,querystring
"extend"

strict routing
Boolean
啟用嚴格的路由。
不啟用。對/foo
和/foo/
的路由處理是一樣。

subdomain offset
Number
用來刪除訪問子域的主機點分部分的個數
2

trust proxy
Varied
指示app
在一個反向代理的后面,使用x-Forwarded-*
來確定連接和客戶端的IP地址。注意:X-Forwarded-*
頭部很容易被欺騙,所有檢測客戶端的IP地址是靠不住的。trust proxy
默認不啟用。當啟用時,Express嘗試通過前端代理或者一系列代理來獲取已連接的客戶端IP地址。req.ips
屬性包含了已連接客戶端IP地址的一個數組。為了啟動它,需要設置在下面trust proxy options table中定義的值。trust proxy
的設置實現使用了proxy-addr
包。如果想獲得更多的信息,可以查閱它的文檔
Disable

views
String or Array
view
所在的目錄或者目錄數組。如果是一個數組,將按在數組中的順序來查找view

process.cwd() + '/views'

view cache
Boolean
啟用視圖模板編譯緩存。
在生成環境默認開啟。

view engine
String
省略時,默認的引擎被擴展使用。

x-powered-by
Boolean
啟用X-Powered-By:Express
HTTP頭部
true

Options for trust proxy
settings
查閱Express behind proxies來獲取更多信息。
Type
Value

Boolean
如果為true
,客戶端的IP地址作為X-Forwarded-*
頭部的最左邊的條目。如果為false
,可以理解為app
直接與英特網直連,客戶端的IP地址衍生自req.connection.remoteAddress
。false
是默認設置。

IP addresses
一個IP地址,子網,或者一組IP地址,和委托子網。下面列出的是一個預先配置的子網名列表。
loopback - 127.0.0.1/8
, ::1/128

linklocal - 169.254.0.0/16
, fe80::/10

uniquelocal - 10.0.0.0/8
, 172.16.0.0/12
, 192.168.0.0/16
, fc00::/7

使用下面方法中的任何一種來設置IP地址:
app.set('trust proxy', 'loopback') // specify a single subnet app.set('trust proxy', 'loopback, 123.123.123.123') // specify a subnet and an address app.set('trust proxy', 'loopback, linklocal, uniquelocal') // specify multiple subnets as CSV app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']) // specify multiple subnets as an array

當指定IP地址之后, 這個IP地址或子網會被設置了這個IP地址或子網的app排除在外, 最靠近程序服務的沒有委托的地址將被看做客戶端IP地址。

Number
信任從反向代理到app中間小于等于n跳的連接為客戶端。

Function
客戶自定義委托代理信任機制。如果你使用這個,請確保你自己知道你在干什么。
app.set('trust proxy', function (ip) { if (ip === '127.0.0.1' || ip === '123.123.123.123') return true; // trusted IPs else return false; })

Options for etag
settings
ETag
功能的實現使用了etag包。如果你需要獲得更多的信息,你可以查閱它的文檔。
Type
Value

Boolean
設置為true
,啟用weak ETag。這個是默認設置。設置false
,禁用所有的ETag。

String
如果是strong
,使能strong ETag。如果是weak
,啟用weak
ETag。

Function
客戶自定義ETag方法的實現. 如果你使用這個,請確保你自己知道你在干什么。
app.set('etag', function (body, encoding) { return generateHash(body, encoding); // consider the function is defined })

app.use([path,], function [, function...])
掛載中間件方法到路徑上。如果路徑未指定,那么默認為"/"。
一個路由將匹配任何路徑如果這個路徑以這個路由設置路徑后緊跟著"/"。比如:app.use('/appale', ...)
將匹配"/apple","/apple/images","/apple/images/news"等。
中間件中的req.originalUrl
是req.baseUrl
和req.path
的組合,如下面的例子所示。
app.use('/admin', function(req, res, next) {

// GET 'http://www.example.com/admin/new'

console.log(req.originalUrl); // '/admin/new'

console.log(req.baseUrl); // '/admin'

console.log(req.path);// '/new'

});

在一個路徑上掛載一個中間件之后,每當請求的路徑的前綴部分匹配了這個路由路徑,那么這個中間件就會被執行。 由于默認的路徑為/
,中間件掛載沒有指定路徑,那么對于每個請求,這個中間件都會被執行。

// this middleware will be executed for every request to the app.

app.use(function(req, res, next) {

console.log('Time: %d', Date.now());

next();

});

中間件方法是順序處理的,所以中間件包含的順序是很重要的。

// this middleware will not allow the request to go beyond it

app.use(function(req, res, next) {

res.send('Hello World');

});

// this middleware will never reach this route

app.use('/', function(req, res) {

res.send('Welcome');

});

路徑可以是代表路徑的一串字符,一個路徑模式,一個匹配路徑的正則表達式,或者他們的一組集合。
下面是路徑的簡單的例子。

Type
Example

Path
// will match paths starting with /abcdapp.use('/abcd', function (req, res, next) { next();})

Path Pattern
// will match paths starting with /abcd and /abdapp.use('/abc?d', function (req, res, next) { next();})// will match paths starting with /abcd, /abbcd, /abbbbbcd and so onapp.use('/ab+cd', function (req, res, next) { next();})// will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so onapp.use('/ab*cd', function (req, res, next) { next();})// will match paths starting with /ad and /abcdapp.use('/a(bc)?d', function (req, res, next) { next();})

Regular Expression
// will match paths starting with /abc and /xyzapp.use(//abc|/xyz/, function (req, res, next) { next();})

Array
// will match paths starting with /abcd, /xyza, /lmn, and /pqrapp.use(['/abcd', '/xyza', //lmn|/pqr/], function (req, res, next) { next();})

方法可以是一個中間件方法,一系列中間件方法,一組中間件方法或者他們的集合。由于router
和app
實現了中間件接口,你可以像使用其他任一中間件方法那樣使用它們。
Usage
Example

單個中間件
你可以局部定義和掛載一個中間件。app.use(function (req, res, next) { next();})

一個router
是有效的中間件。var router = express.Router();router.get('/', function (req, res, next) { next();})app.use(router);

一個Express
程序是一個有效的中間件。var subApp = express();subApp.get('/', function (req, res, next) { next();})app.use(subApp);

一系列中間件
對于一個相同的掛載路徑,你可以掛載超過一個的中間件。var r1 = express.Router();r1.get('/', function (req, res, next) { next();})var r2 = express.Router();r2.get('/', function (req, res, next) { next();})app.use(r1, r2);

一組中間件
在邏輯上使用一個數組來組織一組中間件。如果你傳遞一組中間件作為第一個或者唯一的參數,接著你需要指定掛載的路徑。var r1 = express.Router();r1.get('/', function (req, res, next) { next();})var r2 = express.Router();r2.get('/', function (req, res, next) { next();})app.use('/', [r1, r2]);

組合
你可以組合下面的所有方法來掛載中間件。function mw1(req, res, next) { next(); }function mw2(req, res, next) { next(); }var r1 = express.Router();r1.get('/', function (req, res, next) { next(); });var r2 = express.Router();r2.get('/', function (req, res, next) { next(); });var subApp = express();subApp.get('/', function (req, res, next) { next(); });app.use(mw1, [mw2, r1, r2], subApp);

下面是一些例子,在Express
程序中使用express.static
中間件。 為程序托管位于程序目錄下的public
目錄下的靜態資源:

// GET /style.css etc

app.use(express.static(__dirname + '/public'));

在/static
路徑下掛載中間件來提供靜態資源托管服務,只當請求是以/static
為前綴的時候。

// GET /static/style.css etc.

app.use('/static', express.static(express.__dirname + '/public'));

通過在設置靜態資源中間件之后加載日志中間件來關閉靜態資源請求的日志。

app.use(express.static(__dirname + '/public'));

app.use(logger());

托管靜態資源從不同的路徑,但./public
路徑比其他更容易被匹配:

app.use(express.static(__dirname + '/public'));

app.use(express.static(__dirname + '/files'));

app.use(express.static(__dirname + '/uploads'));

Request
req
對象代表了一個HTTP請求,其具有一些屬性來保存請求中的一些數據,比如query string
,parameters
,body
,HTTP headers
等等。在本文檔中,按照慣例,這個對象總是簡稱為req
(http響應簡稱為res
),但是它們實際的名字由這個回調方法在那里使用時的參數決定。 如下例子:

app.get('/user/:id', function(req, res) {

res.send('user' + req.params.id);

});

其實你也可以這樣寫:

app.get('/user/:id', function(request, response) {

response.send('user' + request.params.id);

});

Properties
在Express 4
中,req.files
默認在req
對象中不再是可用的。為了通過req.files
對象來獲得上傳的文件,你可以使用一個multipart-handling
(多種處理的工具集)中間件,比如busboy
,multer
,formidable
,multipraty
,connect-multiparty
或者pez

req.app
這個屬性持有express
程序實例的一個引用,其可以作為中間件使用。 如果你按照這個模式,你創建一個模塊導出一個中間件,這個中間件只在你的主文件中require()
它,那么這個中間件可以通過req.app
來獲取express的實例。 例如:

// index.js

app.get("/viewdirectory", require('./mymiddleware.js'));

// mymiddleware.js

module.exports = function(req, res) {

res.send('The views directory is ' + req.app.get('views'));

};

req.baseUrl
一個路由實例掛載的Url路徑。

var greet = express.Router();

greet.get('/jp', function(req, res) {

console.log(req.baseUrl); // greet

res.send('Konichiwa!');

});

app.use('/greet', greet);

即使你使用的路徑模式或者一系列路徑模式來加載路由,baseUrl
屬性返回匹配的字符串,而不是路由模式。下面的例子,greet
路由被加載在兩個路徑模式上。

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

當一個請求路徑是/greet/jp
,baseUrl
是/greet
,當一個請求路徑是/hello/jp
,req.baseUrl
是/hello
。 req.baseUrl
和app
對象的mountpath屬性相似,除了app.mountpath
返回的是路徑匹配模式。

req.body
在請求的body中保存的是提交的一對對鍵值數據。默認情況下,它是undefined
,當你使用比如body-parser
和multer
這類解析body
數據的中間件時,它是填充的。 下面的例子,給你展示了怎么使用body-parser
中間件來填充req.body

var app = require('express');

var bodyParser = require('body-parser');

var multer = require('multer');// v1.0.5

var 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(), function(req, res, next) {

console.log(req.body);

res.json(req.body);

});

req.cookies
當使用cookie-parser
中間件的時候,這個屬性是一個對象,其包含了請求發送過來的cookies
。如果請求沒有帶cookies
,那么其值為{}

// Cookie: name=tj

req.cookies.name

// => "tj"

獲取更多信息,問題,或者關注,可以查閱cookie-parser

req.fresh
指示這個請求是否是新鮮的。其和req.stale
是相反的。 當cache-control
請求頭沒有no-cache
指示和下面中的任一一個條件為true
,那么其就為true

if-modified-since
請求頭被指定,和last-modified
請求頭等于或者早于modified
響應頭。
if-none-match
請求頭是*

if-none-match
請求頭在被解析進它的指令之后,不匹配etag
響應頭(完全不知道什么鬼)。

req.fresh

// => true

req.hostname
包含了源自Host
HTTP頭部的hostname
。 當trust proxy
設置項被設置為啟用值,X-Forwarded-Host
頭部被使用來代替Host
。這個頭部可以被客戶端或者代理設置。

// Host: "example.com"

req.hostname

// => "example.com"

req.ips
當trust proxy
設置項被設置為啟用值,這個屬性包含了一組在X-Forwarded-For
請求頭中指定的IP地址。不然,其就包含一個空的數組。這個頭部可以被客戶端或者代理設置。 例如,如果X-Forwarded-For
是client
,proxy1
,proxy2
,req.ips
就是["clinet", "proxy1", "proxy2"]
,這里proxy2
就是最遠的下游。

req.originalUrl
req.url
不是一個原生的Express
屬性,它繼承自Node's http module

這個屬性很像req.url
;然而,其保留了原版的請求鏈接,允許你自由地重定向req.url
到內部路由。比如,app.use()
的mounting
特點可以重定向req.url
跳轉到掛載點。

// GET /search?q=something

req.originalUrl

// => "/search?q=something"

req.params
一個對象,其包含了一系列的屬性,這些屬性和在路由中命名的參數名是一一對應的。例如,如果你有/user/:name
路由,name
屬性可作為req.params.name
。這個對象默認值為{}

// GET /user/tj

req.params.name

// => "tj"

當你使用正則表達式來定義路由規則,捕獲組的組合一般使用req.params[n]
,這里的n
是第幾個捕獲租。這個規則被施加在無名通配符匹配,比如/file/*
的路由:

// GET /file/javascripts/jquery.js

req.params[0]

// => "javascripts/jquery.js"

req.path
包含請求URL的部分路徑。

// example.com/users?sort=desc

req.path

// => "/users"

當在一個中間件中被調用,掛載點不包含在req.path
中。你可以查閱app.use()獲得跟多的信息。

req.protocol
請求的協議,一般為http
,當啟用TLS加密,則為https
。 當trust proxy
設置一個啟用的參數,如果存在X-Forwarded-Proto
頭部的話,其將被信賴和使用。這個頭部可以被客戶端或者代理設置。

req.ptotocol

// => "http"

req.query
一個對象,為每一個路由中的query string
參數都分配一個屬性。如果沒有query string
,它就是一個空對象,{}

// GET /search?q=tobi+ferret

req.query.q

// => "tobi ferret"

// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse

req.query.order

// => "desc"

req.query.shoe.color

// => "blue"

req.query.shoe.type

// => "converse"

req.route
當前匹配的路由,其為一串字符。比如:

app.get('/user/:id?', function userIdHandler(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
。等價與:

'https' == req.protocol;

req.signedCookies
當使用cookie-parser
中間件的時候,這個屬性包含的是請求發過來的簽名cookies
,不簽名的并且為使用做好了準備(這句真不知道怎么翻譯了...)。簽名cookies
駐留在不同的對象中來體現開發者的意圖;不然,一個惡意攻擊可以被施加在req.cookie
值上(它是很容易被欺騙的)。記住,簽名一個cookie
不是把它藏起來或者加密;而是簡單的防止篡改(因為簽名使用的加密是私人的)。如果沒有發送簽名的cookie
,那么這個屬性默認為{}

// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3

req.signedCookies.user

// => "tobi"

為了獲取更多的信息,問題或者關注,可以參閱cookie-parser

req.stale
指示這個請求是否是stale
(陳舊的),它與req.fresh
是相反的。更多信息,可以查看req.fresh

req.stale

// => true

req.subdomains
請求中域名的子域名數組。

// Host: "tobi.ferrets.example.com"

req.subdomains

// => ["ferrets", "tobi"]

req.xhr
一個布爾值,如果X-Requested-With
的值為XMLHttpRequest
,那么其為true
,其指示這個請求是被一個客服端庫發送,比如jQuery

req.xhr

// => true

Methods

req.accepts(types)
檢查這個指定的內容類型是否被接受,基于請求的Accept
HTTP頭部。這個方法返回最佳匹配,如果沒有一個匹配,那么其返回undefined
(在這個case下,服務器端應該返回406和"Not Acceptable")。 type
值可以是一個單的MIME type
字符串(比如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']);

// => "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頭部的域內容(不區分大小寫)。Referrer
和Referer
的域內容可互換。

req.get('Content-type');

// => "text/plain"

req.get('content-type');

// => "text/plain"

req.get('Something')

// => undefined

其是req.header(field)
的別名。

req.is(type)
如果進來的請求的Content-type
頭部域匹配參數type
給定的MIME type
,那么其返回true
。否則返回false

// 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

獲取更多信息,或者如果你有問題或關注,可以參閱type-is

req.param(naem, [, defaultValue])
過時的。可以在適合的情況下,使用req.params
,req.body
或者req.query

返回當前參數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
可選的,你可以指定一個defaultValue
來設置一個默認值,如果這個參數在任何一個請求的對象中都不能找到。
直接通過req.params
,req.body
,req.query
取得應該更加的清晰-除非你確定每一個對象的輸入。 Body-parser
中間件必須加載,如果你使用req.param()
。詳細請看req.body

Response
res
對象代表了當一個HTTP請求到來時,Express
程序返回的HTTP響應。在本文檔中,按照慣例,這個對象總是簡稱為res
(http請求簡稱為req
),但是它們實際的名字由這個回調方法在那里使用時的參數決定。 例如:

app.get('/user/:id', function(req, res) {

res.send('user' + req.params.id);

});

這樣寫也是一樣的:

app.get('/user/:id', function(request, response) {

response.send('user' + request.params.id);

});

Properties

res.app
這個屬性持有express
程序實例的一個引用,其可以在中間件中使用。 res.app
和請求對象中的req.app
屬性是相同的。

res.headersSent
布爾類型的屬性,指示這個響應是否已經發送HTTP頭部。

app.get('/', function(req, res) {

console.log(res.headersSent); // false

res.send('OK'); // send之后就發送了頭部

console.log(res.headersSent); // true

});

res.locals
一個對象,其包含了響應的能夠反應出請求的本地參數和因此只提供給視圖渲染,在請求響應的周期內(如果有的話)--我要翻譯吐了。否則,其和app.locals
是一樣的。(不知道翻譯的什么...) 這個參數在導出請求級別的信息是很有效的,這些信息比如請求路徑,已認證的用戶,用戶設置等等。

app.use(function(req, res, next) {

res.locals.user = req.user;

res.locals.authenticated = !req.user.anonymous;

next();

});

Methods

res.append(field [, value])
res.append()方法在Expresxs
4.11.0以上版本才支持。

在指定的field
的HTTP頭部追加特殊的值value
。如果這個頭部沒有被設置,那么將用value
新建這個頭部。value
可以是一個字符串或者數組。 注意:在res.append()
之后調用app.set()
函數將重置前面設置的值。

res.append('Lind', ['http://localhost', 'http://localhost:3000']);

res.append('Set-Cookie', 'foo=bar;Path=/;HttpOnly');

res.append('Warning', '199 Miscellaneous warning');

res.attachment([filename])
設置HTTP響應的Content-Disposition
頭內容為"attachment"。如果提供了filename
,那么將通過res.type()
獲得擴展名來設置Content-Type
,并且設置Content-Disposition
內容為"filename="parameter。

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])
設置name
和value
的cookie
,value
參數可以是一串字符或者是轉化為json字符串的對象。 options是一個對象,其可以有下列的屬性。
屬性
類型
描述

domain
String
設置cookie的域名。默認是你本app的域名。

expires
Date
cookie的過期時間,GMT格式。如果沒有指定或者設置為0,則產生新的cookie。

httpOnly
Boolean
這個cookie只能被web服務器獲取的標示。

maxAge
String
是設置過去時間的方便選項,其為過期時間到當前時間的毫秒值。

path
String
cookie的路徑。默認值是/

secure
Boolean
標示這個cookie只用被HTTPS
協議使用。

signed
Boolean
指示這個cookie應該是簽名的。

res.cookie()所作的都是基于提供的options
參數來設置Set-Cookie
頭部。沒有指定任何的options
,那么默認值在RFC6265
中指定。

使用實例:

res.cookie('name', 'tobi', {'domain':'.example.com', 'path':'/admin', 'secure':true});

res.cookie('remenberme', '1', {'expires':new Date(Date.now() + 90000), 'httpOnly':true});

maxAge
是一個方便設置過期時間的方便的選項,其以當前時間開始的毫秒數來計算。下面的示例和上面的第二條功效一樣。

res.cookie('rememberme', '1', {'masAge':90000}, "httpOnly":true);

你可以設置傳遞一個對象作為value
的參數。然后其將被序列化為Json字符串,被bodyParser()
中間件解析。

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

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

當我們使用cookie-parser
中間件的時候,這個方法也支持簽名的cookie。簡單地,在設置options
時包含signed
選項為true
。然后res.cookie()
將使用傳遞給cookieParser(secret)
的密鑰來簽名這個值。

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

res.clearCookie(name [,options])
根據指定的name
清除對應的cookie。更多關于options
對象可以查閱res.cookie()

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

res.clearCookie('name', {'path':'admin'});

res.download(path, [,filename], [,fn])
傳輸path
指定文件作為一個附件。通常,瀏覽器提示用戶下載。默認情況下,Content-Disposition
頭部"filename="的參數為path
(通常會出現在瀏覽器的對話框中)。通過指定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) {

// Handle error, but keep in mind the response may be partially-sent

// so check res.headersSent

if (err) {

} else {

// decrement a download credit, etc.

}

});

res.end([data] [, encoding])
結束本響應的過程。這個方法實際上來自Node
核心模塊,具體的是response.end() method of http.ServerResponse。用來快速結束請求,沒有任何的數據。如果你需要發送數據,可以使用res.send()res.json()這類的方法。

res.end();

res.status(404).end();

res.format(object)
進行內容協商,根據請求的對象中Accept
HTTP頭部指定的接受內容。它使用req.accepts()來選擇一個句柄來為請求服務,這些句柄按質量值進行排序。如果這個頭部沒有指定,那么第一個方法默認被調用。當不匹配時,服務器將返回406
"Not Acceptable",或者調用default
回調。 Content-Type
請求頭被設置,當一個回調方法被選擇。然而你可以改變他,在這個方法中使用這些方法,比如res.set()
或者res.type()
。 下面的例子,將回復{"message":"hey"}
,當請求的對象中Accept
頭部設置成"application/json"或者"/json"(不過如果是/*
,然后這個回復就是"hey")。

res.format({

'text/plain':function() {

res.send('hey')'

},

'text/html':function() {

res.send('<p>hey</p>');

},

'application/json':function() {

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

},

'default':function() {

res.status(406).send('Not Acceptable');

}

})

除了規范化的MIME類型之外,你也可以使用拓展名來映射這些類型來避免冗長的實現:

res.format({

text:function() {

res.send('hey');

},

html:function() {

res.send('<p>hey</p>');

},

json:function() {

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

}

})

res.get(field)
返回field
指定的HTTP響應的頭部。匹配是區分大小寫。

res.get('Content-Type');

// => "text/plain"

res.json([body])
發送一個json的響應。這個方法和將一個對象或者一個數組作為參數傳遞給res.send()
方法的效果相同。不過,你可以使用這個方法來轉換其他的值到json,例如null
,undefined
。(雖然這些都是技術上無效的JSON)。

res.json(null);

res.json({user:'tobi'});

res.status(500).json({error:'message'});

res.jsonp([body])
發送一個json的響應,并且支持JSONP。這個方法和res.json()
效果相同,除了其在選項中支持JSONP回調。

res.jsonp(null)

// => null

res.jsonp({user:'tobi'})

// => {"user" : "tobi"}

res.status(500).jsonp({error:'message'})

// => {"error" : "message"}

默認情況下,jsonp的回調方法簡單寫作callback
。可以通過jsonp callback name設置來重寫它。 下面是一些例子使用JSONP響應,使用相同的代碼:

// ?callback=foo

res.jsonp({user:'tobo'})

// => foo({"user":"tobi"})

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

// ?cb=foo

res.status(500).jsonp({error:'message'})

// => foo({"error":"message"})

res.links(links)
連接這些links
,links
是以傳入參數的屬性形式提供,連接之后的內容用來填充響應的Link HTTP頭部。

res.links({

next:'http://api.example.com/users?page=2',

last:'http://api.example.com/user?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');

當path
參數為back
時,其具有特殊的意義,其指定URL為請求對象的Referer
頭部指定的URL。如果請求中沒有指定,那么其即為"/"。
Express傳遞指定的URL字符串作為回復給瀏覽器響應中的Location
頭部的值,不檢測和操作,除了當是back
這個case時。瀏覽器有推導預期URL從當前的URL或者指定的URL,和在Location
指定的URL的責任;相應地重定向它。(我也不知道翻譯的什么...)

res.redirect([status,] path)
重定向來源于指定path
的URL,以及指定的HTTP status codestatus
。如果你沒有指定status
,status code默認為"302 Found"。

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
,那么下面將重定向到http://example.com/admim
:

res.redirect('/admin');

重定向也可以相對于當前的URL。比如,來之于http://example.com/blog/admin/
(注意結尾的/
),下面將重定向到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])
渲染一個視圖,然后將渲染得到的HTML文檔發送給客戶端。可選的參數為:
locals
,定義了視圖本地參數屬性的一個對象。
callback
,一個回調方法。如果提供了這個參數,render
方法將返回錯誤和渲染之后的模板,并且不自動發送響應。當有錯誤發生時,可以在這個回調內部,調用next(err)
方法。
本地變量緩存使能視圖緩存。在開發環境中緩存視圖,需要手動設置為true;視圖緩存在生產環境中默認開啟。

// send the rendered view to the client

res.render('index');

// if a callback is specified, the render HTML string has to be sent explicitly

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

res.send(html);

});

// pass a local variable to the view

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

// ...

});

res.send([body])
發送HTTP響應。 body
參數可以是一個Buffer
對象,一個字符串,一個對象,或者一個數組。比如:

res.send(new Buffer('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(new Buffer('<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頭部。除非在options
中有關于root
的設置,path
一定是關于文件的絕對路徑。 下面的表提供了options
參數的細節:
屬性
描述
默認值
可用版本

maxAge
設置Cache-Control
的max-age
屬性,格式為毫秒數,或者是ms format的一串字符串
0

root
相對文件名的根目錄

lastModified
設置Last-Modified
頭部為此文件在系統中的最后一次修改時間。設置false
來禁用它
Enable
4.9.0+

headers
一個對象,包含了文件所在的sever的HTTP頭部。(不知道怎么翻譯了)

dotfiles
是否支持點開頭文件名的選項。可選的值"allow","deny","ignore"
"ignore"

當傳輸完成或者發生了什么錯誤,這個方法調用fn
回調方法。如果這個回調參數指定了和一個錯誤發生,回調方法必須明確地通過結束請求-響應循環或者傳遞控制到下個路由來處理響應過程。 下面是使用了所有參數的使用res.sendFile()
的例子:

app.get('/file/:name', function(req, res, next) {

var options = {

root:__dirname + '/public',

dotfile:'deny',

headers:{

'x-timestamp':Date.now(),

'x-sent':true

}

};

var fileName = req.params.name;

res.sendFile(fileName, options, function(err) {

if (err) {

console.log(err);

res.status(err.status).end();

}

else {

console.log('sent', fileName);

}

});

});

res.sendFile
提供了文件服務的細粒度支持,如下例子說明:

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

var uid = req.params.uid

, file = req.params.file;

req.user.mayViewFilesFrom(uid, function(yes) {

if (yes) {

res.sendFile('/upload/' + uid + '/' + file);

}

else {

res.status(403).send('Sorry! you cant see that.');

}

});

})

獲取更多信息,或者你有問題或者關注,可以查閱send

res.sendStatus(statusCode)
設置響應對象的HTTP status code
為statusCode
并且發送statusCode
的相應的字符串形式作為響應的Body。

res.sendStatus(200); // equivalent to res.status(200).send('OK');

res.sendStatus(403); // equivalent to res.status(403).send('Forbidden');

res.sendStatus(404); // equivalent to res.status(404).send('Not Found');

res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')

如果一個不支持的狀態被指定,這個HTTP status依然被設置為statusCode
并且用這個code的字符串作為Body。

res.sendStatus(2000); // equivalent to res.status(2000).send('2000');

More about HTTP Status Codes

res.set(field [, value])
設置響應對象的HTTP頭部field
為value
。為了一次設置多個值,那么可以傳遞一個對象為參數。

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

res.set({

'Content-Type':'text/plain',

'Content-Length':'123',

'ETag':'123456'

})

其和res.header(field [,value])
效果一致。

res.status(code)
使用這個方法來設置響應對象的HTTP status。其是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頭部為MIME type,如果這個指定的type能夠被mime.lookup確定。如果type
包含/
字符,那么設置Content-Type
為type
(我已經暈了)。

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
響應頭為field
,如果已經不在那里。(不懂什么意思)

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

Router
一個router
對象是一個單獨的實例關于中間件和路由。你可以認為其是一個"mini-application"(迷你程序),其具有操作中間件和路由方法的能力。每個Express
程序有一個內建的app路由。 路由自身表現為一個中間件,所以你可以使用它作為app.use()
方法的一個參數或者作為另一個路由的use()
的參數。 頂層的express
對象有一個Router()
方法,你可以使用Router()
來創建一個新的router
對象。

Router([options])
如下,可以創建一個路由:

var router = express.Router([options]);

options
參數可以指定路由的行為,其有下列選擇:
屬性
描述
默認值
可用性

caseSensitive
是否區分大小寫
默認不啟用。對待/Foo
和/foo
一樣。

mergeParams
保存父路由的res.params
。如果父路由參數和子路由參數沖突,子路由參數優先。
false
4.5.0+

strict
使能嚴格路由。
默認不啟用,/foo
和/foo/
被路由一樣對待處理

你可以將router
當作一個程序,可以在其上添加中間件和HTTP路由方法(例如get
,put
,post
等等)。

// invoked for any requests passed to this router

router.use(function(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', function(req, res, next) {

// ..

});

你可以在一個特別的根URL上掛載一個路由,這樣你就以將你的各個路由放到不同的文件中或者甚至是mini的程序。

// only requests to /calendar/* will be sent to our "router"

app.use('/calendar', router);

Methods

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
中的METHOD是小寫的。所以,實際的方法是router.get()
,router.put()
,router.post()
等等。 你可以提供多個回調函數,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒有滿足當前路由的處理條件,那么傳遞控制到隨后的路由。 下面的片段可能說明了最簡單的路由定義。Experss轉換path字符串為正則表達式,用于內部匹配傳入的請求。在匹配的時候,是不考慮Query strings
,例如,"GET /"將匹配下面的路由,"GET /?name=tobi"也是一樣的。

router.get('/', function(req, res) {

res.send('Hello World');

});

如果你對匹配的path有特殊的限制,你可以使用正則表達式,例如,下面的可以匹配"GET /commits/71dbb9c"和"GET /commits/71bb92..4c084f9"。

router.get(/^/commits/(\w+)(?:..(\w+))?$/, function(req, res) {

var from = req.params[0];

var to = req.params[1];

res.send('commit range ' + from + '..' + to);

});

router.param(name, callback)
給路由參數添加回調觸發器,這里的name
是參數名,function
是回調方法。回調方法的參數按序是請求對象,響應對象,下個中間件,參數值和參數名。雖然name
在技術上是可選的,但是自Express V4.11.0之后版本不推薦使用(見下面)。
不像app.param()
,router.param()
不接受一個數組作為路由參數。

例如,當:user
出現在路由路徑中,你可以映射用戶加載的邏輯處理來自動提供req.user
給這個路由,或者對輸入的參數進行驗證。

router.param('user', function(req, res, next, id) {

User.find(id, function(error, user) {

if (err) {

next(err);

}

else if (user){

req.user = user;

} else {

next(new Error('failed to load user'));

}

});

});

對于Param
的回調定義的路由來說,他們是局部的。它們不會被掛載的app或者路由繼承。所以,定義在router
上的param
回調只有是在router
上的路由具有這個路由參數時才起作用。 在定義param
的路由上,param
回調都是第一個被調用的,它們在一個請求-響應循環中都會被調用一次并且只有一次,即使多個路由都匹配,如下面的例子:

router.param('id', function(req, res, next, id) {

console.log('CALLED ONLY ONCE');

next();

});

router.get('/user/:id', function(req, res, next) {

console.log('although this matches');

next();

});

router.get('/user/:id', function(req, res) {

console.log('and this mathces 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(naem, callback)
方法的行為將被完全改變。這個回調參數是關于router.param(name, callback)
該具有怎樣的行為的一個自定義方法,這個方法必須接受兩個參數并且返回一個中間件。 這個回調的第一個參數就是需要捕獲的url的參數名,第二個參數可以是任一的JavaScript對象,其可能在實現返回一個中間件時被使用。 這個回調方法返回的中間件決定了當URL中包含這個參數時所采取的行為。 在下面的例子中,router.param(name, callback)
參數簽名被修改成了router.param(name, accessId)
。替換接受一個參數名和回調,router.param()
現在接受一個參數名和一個數字。

var express = require('express');

var app = express();

var router = express.Router();

router.param(function(param, option){

return function(req, res, next, val) {

if (val == option) {

next();

}

else {

res.sendStatus(403);

}

}

});

router.param('id', 1337);

router.get('/user/:id', function(req, res) {

res.send('Ok');

});

app.use(router);

app.listen(3000, function() {

console.log('Ready');

});

在這個例子中,router.param(name. callback)
參數簽名保持和原來一樣,但是替換成了一個中間件,定義了一個自定義的數據類型檢測方法來檢測user id
的類型正確性。

router.param(function(param, validator) {

return function(req, res, next, val) {

if (validator(val)) {

next();

}

else {

res.sendStatus(403);

}

}

});

router.param('id', function(candidate) {

return !isNaN(parseFloat(candidate)) && isFinite(candidate);

});

router.route(path)
返回一個單例模式的路由的實例,之后你可以在其上施加各種HTTP動作的中間件。使用app.route()
來避免重復路由名字(因此錯字錯誤)--后面這句不知道說的什么鬼,大概的意思就是避免同一個路徑有兩個路由實例。 構建在上面的router.param()
例子之上,下面的代碼展示了怎么使用router.route()
來指定各種HTTP方法的處理句柄。

var router = express.Router();

router.param('user_id', function(req, res, next, id) {

// sample user, would actually fetch from DB, etc...

req.user = {

id:id,

name:"TJ"

};

next();

});

router.route('/users/:user_id')

.all(function(req, res, next) {

// runs for all HTTP verbs first

// think of it as route specific middleware!

next();

})

.get(function(req, res, next) {

res.json(req.user);

})

.put(function(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(function(req, res, next) {

next(new Error('not implemented'));

})

.delete(function(req, res, next) {

next(new Error('not implemented'));

})

這種方法重復使用單個/usrs/:user_id
路徑來添加了各種的HTTP方法。

router.use([path], [function, ...] function)
給可選的path
參數指定的路徑掛載給定的中間件方法,未指定path
參數,默認值為/
。 這個方法類似于app.use()
。一個簡單的例子和用例在下面描述。查閱app.use()獲得更多的信息。 中間件就像一個水暖管道,請求在你定義的第一個中間件處開始,順著中間件堆棧一路往下,如果路徑匹配則處理這個請求。

var express = require('express');

var app = express();

var router = express.Router();

// simple logger for this router`s requests

// all requests to this router will first hit this middleware

router.use(function(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 form the mount ponit

router.use('/bar', function(req, res, next) {

// ... maybe some additional /bar logging ...

next();

})

// always be invoked

router.use(function(req, res, next) {

res.send('hello world');

})

app.use('/foo', router);

app.listen(3000);

對于中間件function
,掛載的路徑是被剝離的和不可見的。關于這個特性主要的影響是對于不同的路徑,掛載相同的中間件可能對代碼不做改動,盡管其前綴已經改變。 你使用router.use()
定義中間件的順序很重要。中間們是按序被調用的,所以順序決定了中間件的優先級。例如,通常日志是你將使用的第一個中間件,以便每一個請求都被記錄。

var logger = require('morgan');

router.use(logger());

router.use(express.static(__dirname + '/public'));

router.use(function(req, res) {

res.send('Hello');

});

現在為了支持你不希望記錄靜態文件請求,但為了繼續記錄那些定義在logger()
之后的路由和中間件。你可以簡單的將static()
移動到前面來解決:

router.use(express.static(__dirname + '/public'));

router.use(logger());

router.use(function(req, res){

res.send('Hello');

});

另外一個確鑿的例子是從不同的路徑托管靜態文件,你可以將./public
放到前面來獲得更高的優先級:

app.use(express.static(__dirname + '/public'));

app.use(express.static(__dirname + '/files'));

app.use(express.static(__dirname + '/uploads'));

router.use()
方法也支持命名參數,以便你的掛載點對于其他的路由而言,可以使用命名參數來進行預加載,這樣做是很有益的。

**1
**1
**1
**1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容