Address:https://www.zybuluo.com/XiangZhou/note/208532
Express 4.x API
express
翻譯
api文檔
中文
--
github地址,歡迎大家提交更新赎懦。
express()
express()
用來創(chuàng)建一個Express的程序胁澳。express()
方法是express模塊導出的頂層方法。
var express = require('express');
var app = express();
Methods
express.static(root, [options])
express.static
是Express中唯一的內建中間件悠砚。它以server-static模塊為基礎開發(fā)荆秦,負責托管 Express 應用內的靜態(tài)資源。 參數(shù)root
為靜態(tài)資源的所在的根目錄毙籽。 參數(shù)options
是可選的,支持以下的屬性:
屬性
描述
類型
默認值
dotfiles
是否響應點文件毡庆。供選擇的值有"allow"坑赡,"deny"和"ignore"
String
"ignore"
etag
使能或者關閉etag
Boolean
true
extensions
設置文件延期回退
Boolean
true
index
發(fā)送目錄索引文件烙如。設置false將不發(fā)送。
Mixed
"index.html"
lastModified
設置文件在系統(tǒng)中的最后修改時間到Last-Modified
頭部毅否⊙翘可能的取值有false
和true
。
Boolean
true
maxAge
在Cache-Control頭部中設置max-age
屬性螟加,精度為毫秒(ms)或則一段ms format的字符串
Number
0
redirect
當請求的pathname是一個目錄的時候徘溢,重定向到尾隨"/"
Boolean
true
setHeaders
當響應靜態(tài)文件請求時設置headers的方法
Funtion
如果你想獲得更多關于使用中間件的細節(jié),你可以查閱Serving static files in Express捆探。
Application()
app
對象一般用來表示Express程序然爆。通過調用Express模塊導出的頂層的express()
方法來創(chuàng)建它:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello world!');
});
app.listen(3000);
app
對象具有以下的方法:
路由HTTP請求;具體可以看app.METHOD和app.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
級別的數(shù)據(jù)剧腻。通過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
事件被發(fā)射了讨。父程序對象作為參數(shù),傳遞給回調方法制轰。
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()
方法來繼續(xù)匹配隨后的路由肤无。
app.all('*', requireAuthentication, loadUser);
或者這種相等的形式:
app.all('*', requireAuthentication);
app.all('*', loadUser);
另一個例子是全局的白名單方法。這個例子和前面的很像骇钦,然而它只是限制以/api
開頭的路徑宛渐。
app.all('/api/*', requireAuthentication);
app.delete(path, callback[, callback ...])
路由HTTP DELETE
請求到有特殊回調方法的特殊的路徑。獲取更多的信息眯搭,可以查閱routing guide窥翩。 你可以提供多個回調函數(shù),它們的行為和中間件一樣,除了這些回調可以通過調用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規(guī)定的簽名規(guī)則:(path, options, callback)
挣饥,然而記住在內部它只是ejs.__express
的一個別名,所以你可以在不做任何事的情況下直接使用.ejs
擴展赢织。 一些模板引擎沒有遵循這種規(guī)范亮靴,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瞄桨。 你可以提供多個回調函數(shù)话速,它們的行為和中間件一樣,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調芯侥。你可以使用這個機制來為一個路由設置一些前提條件泊交,如果請求沒能滿足當前路由的處理條件,那么傳遞控制到隨后的路由柱查。
app.get('/', function(req, res) {
res.send('GET request to homepage');
});
app.listen(port, [hostname], [backlog], [callback])
綁定程序監(jiān)聽端口到指定的主機和端口號廓俭。這個方法和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協(xié)議):
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 ...
你可以提供多個回調函數(shù)宠漩,它們的行為和中間件一樣举反,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調。你可以使用這個機制來為一個路由設置一些前提條件扒吁,如果請求沒有滿足當前路由的處理條件火鼻,那么傳遞控制到隨后的路由。
本API文檔把使用比較多的HTTP方法app.get()
雕崩,app.post
魁索,app.put()
,app.delete()
作為一個個單獨的項進行說明盼铁。然而粗蔚,其他上述列出的方法以完全相同的方式工作。
app.all()
是一個特殊的路由方法饶火,它不屬于HTTP協(xié)議中的規(guī)定的方法鹏控。它為一個路徑加載中間件,其對所有的請求方法都有效肤寝。
app.all('/secret', function (req, res) {
console.log('Accessing the secret section...');
next(); // pass control to the next handler
});
app.param([name], callback)
給路由參數(shù)添加回調觸發(fā)器当辐,這里的name
是參數(shù)名或者參數(shù)數(shù)組,function
是回調方法醒陆∑俟梗回調方法的參數(shù)按序是請求對象,響應對象,下個中間件寺晌,參數(shù)值和參數(shù)名世吨。 如果name
是數(shù)組,會按照各個參數(shù)在數(shù)組中被聲明的順序將回調觸發(fā)器注冊下來呻征。還有耘婚,對于除了最后一個參數(shù)的其他參數(shù),在他們的回調中調用next()
來調用下個聲明參數(shù)的回調陆赋。對于最后一個參數(shù)沐祷,在回調中調用next()
將調用位于當前處理路由中的下一個中間件,如果name
只是一個string
那就和它是一樣的(就是說只有一個參數(shù)攒岛,那么就是最后一個參數(shù)赖临,和數(shù)組中最后一個參數(shù)是一樣的)。 例如灾锯,當:user
出現(xiàn)在路由路徑中兢榨,你可以映射用戶加載的邏輯處理來自動提供req.user
給這個路由,或者對輸入的參數(shù)進行驗證顺饮。
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
上的路由具有這個路由參數(shù)時才起作用。 在定義param
的路由上赦肋,param
回調都是第一個被調用的块攒,它們在一個請求-響應循環(huán)中都會被調用一次并且只有一次,即使多個路由都匹配金砍,如下面的例子:
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();
});
當執(zhí)行GET /user/42/3
麦锯,結果如下:
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this mathes too
下面章節(jié)描述的app.param(callback)
在v4.11.0之后被棄用恕稠。
通過只傳遞一個回調參數(shù)給app.param(name, callback)
方法,app.param(naem, callback)
方法的行為將被完全改變扶欣。這個回調參數(shù)是關于app.param(name, callback)
該具有怎樣的行為的一個自定義方法鹅巍,這個方法必須接受兩個參數(shù)并且返回一個中間件。 這個回調的第一個參數(shù)就是需要捕獲的url的參數(shù)名料祠,第二個參數(shù)可以是任一的JavaScript對象骆捧,其可能在實現(xiàn)返回一個中間件時被使用。 這個回調方法返回的中間件決定了當URL中包含這個參數(shù)時所采取的行為髓绽。 在下面的例子中敛苇,app.param(name, callback)
參數(shù)簽名被修改成了app.param(name, accessId)
。替換接受一個參數(shù)名和回調顺呕,app.param()
現(xiàn)在接受一個參數(shù)名和一個數(shù)字枫攀。
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)
參數(shù)簽名保持和原來一樣,但是替換成了一個中間件来涨,定義了一個自定義的數(shù)據(jù)類型檢測方法來檢測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时呀。 你可以提供多個回調函數(shù),它們的行為和中間件一樣晶默,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調谨娜。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒能滿足當前路由的處理條件磺陡,那么傳遞控制到隨后的路由趴梢。
app.post('/', function(req, res) {
res.send('POST request to homepage')
});
app.put(path, callback, [callback ...])
路由HTTP PUT
請求到有特殊回調的特殊路徑。獲取更多的信息币他,可以查閱routing guide坞靶。 你可以提供多個回調函數(shù),它們的行為和中間件一樣蝴悉,除了這些回調可以通過調用next('router')
來繞過剩余的路由回調彰阴。你可以使用這個機制來為一個路由設置一些前提條件,如果請求沒能滿足當前路由的處理條件拍冠,那么傳遞控制到隨后的路由尿这。
app.put('/', function(req, res) {
res.send('PUT request to homepage');
});
app.render(view, [locals], callback)
通過callback
回調返回一個view
渲染之后得到的HTML文本。它可以接受一個可選的參數(shù)庆杜,可選參數(shù)包含了這個view
需要用到的本地數(shù)據(jù)射众。這個方法類似于res.render()
,除了它不能把渲染得到的HTML文本發(fā)送給客戶端晃财。
將app.render()
當作是可以生成渲染視圖字符串的工具方法叨橱。在res.render()
內部,就是使用的app.render()
來渲染視圖。
如果使能了視圖緩存罗洗,那么本地變量緩存就會保留嘉裤。如果你想在開發(fā)的過程中緩存視圖,設置它為true
栖博。在生產環(huán)境中屑宠,視圖緩存默認是打開的。
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
啟用區(qū)分大小寫。
不啟用垄开。對/Foo
和/foo
處理是一樣琴许。
env
String
環(huán)境模型。
process.env.NODE_ENV(NODE_ENV環(huán)境變量)或者"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
當設置了這個值后疑枯,發(fā)送縮進空格美化過的JSON字符串辩块。
Disabled
query parser
Varied
設置值為false
來禁用query parser
,或者設置simple
,extended
神汹,也可以自己實現(xiàn)query string
解析函數(shù)庆捺。simple
基于Node
原生的query
解析古今,querystring屁魏。
"extend"
strict routing
Boolean
啟用嚴格的路由。
不啟用捉腥。對/foo
和/foo/
的路由處理是一樣氓拼。
subdomain offset
Number
用來刪除訪問子域的主機點分部分的個數(shù)
2
trust proxy
Varied
指示app
在一個反向代理的后面,使用x-Forwarded-*
來確定連接和客戶端的IP地址。注意:X-Forwarded-*
頭部很容易被欺騙桃漾,所有檢測客戶端的IP地址是靠不住的坏匪。trust proxy
默認不啟用。當啟用時撬统,Express嘗試通過前端代理或者一系列代理來獲取已連接的客戶端IP地址适滓。req.ips
屬性包含了已連接客戶端IP地址的一個數(shù)組。為了啟動它恋追,需要設置在下面trust proxy options table中定義的值凭迹。trust proxy
的設置實現(xiàn)使用了proxy-addr
包。如果想獲得更多的信息苦囱,可以查閱它的文檔
Disable
views
String or Array
view
所在的目錄或者目錄數(shù)組嗅绸。如果是一個數(shù)組,將按在數(shù)組中的順序來查找view
撕彤。
process.cwd() + '/views'
view cache
Boolean
啟用視圖模板編譯緩存鱼鸠。
在生成環(huán)境默認開啟。
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
功能的實現(xiàn)使用了etag包给僵。如果你需要獲得更多的信息凡人,你可以查閱它的文檔。
Type
Value
Boolean
設置為true
坪哄,啟用weak ETag质蕉。這個是默認設置势篡。設置false
,禁用所有的ETag模暗。
String
如果是strong
禁悠,使能strong ETag。如果是weak
兑宇,啟用weak
ETag碍侦。
Function
客戶自定義ETag
方法的實現(xiàn). 如果你使用這個,請確保你自己知道你在干什么隶糕。
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'
});
在一個路徑上掛載一個中間件之后铃拇,每當請求的路徑的前綴部分匹配了這個路由路徑,那么這個中間件就會被執(zhí)行沈撞。 由于默認的路徑為/
慷荔,中間件掛載沒有指定路徑,那么對于每個請求缠俺,這個中間件都會被執(zhí)行显晶。
// 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
實現(xiàn)了中間件接口少办,你可以像使用其他任一中間件方法那樣使用它們苞慢。
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);
一組中間件
在邏輯上使用一個數(shù)組來組織一組中間件骂维。如果你傳遞一組中間件作為第一個或者唯一的參數(shù),接著你需要指定掛載的路徑贺纲。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
目錄下的靜態(tài)資源:
// GET /style.css etc
app.use(express.static(__dirname + '/public'));
在/static
路徑下掛載中間件來提供靜態(tài)資源托管服務潦刃,只當請求是以/static
為前綴的時候。
// GET /static/style.css etc.
app.use('/static', express.static(express.__dirname + '/public'));
通過在設置靜態(tài)資源中間件之后加載日志中間件來關閉靜態(tài)資源請求的日志懈叹。
app.use(express.static(__dirname + '/public'));
app.use(logger());
托管靜態(tài)資源從不同的路徑乖杠,但./public
路徑比其他更容易被匹配:
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
Request
req
對象代表了一個HTTP請求,其具有一些屬性來保存請求中的一些數(shù)據(jù)澄成,比如query string
胧洒,parameters
,body
墨状,HTTP headers
等等卫漫。在本文檔中,按照慣例肾砂,這個對象總是簡稱為req
(http響應簡稱為res
)列赎,但是它們實際的名字由這個回調方法在那里使用時的參數(shù)決定。 如下例子:
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
程序實例的一個引用储矩,其可以作為中間件使用感耙。 如果你按照這個模式,你創(chuàng)建一個模塊導出一個中間件持隧,這個中間件只在你的主文件中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中保存的是提交的一對對鍵值數(shù)據(jù)。默認情況下逗堵,它是undefined
秉氧,當你使用比如body-parser
和multer
這類解析body
數(shù)據(jù)的中間件時,它是填充的蜒秤。 下面的例子汁咏,給你展示了怎么使用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
中間件的時候梆暖,這個屬性是一個對象,其包含了請求發(fā)送過來的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地址吆你。不然,其就包含一個空的數(shù)組俊犯。這個頭部可以被客戶端或者代理設置妇多。 例如,如果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
一個對象,其包含了一系列的屬性柠衅,這些屬性和在路由中命名的參數(shù)名是一一對應的皮仁。例如,如果你有/user/:name
路由菲宴,name
屬性可作為req.params.name
贷祈。這個對象默認值為{}
。
// GET /user/tj
req.params.name
// => "tj"
當你使用正則表達式來定義路由規(guī)則喝峦,捕獲組的組合一般使用req.params[n]
势誊,這里的n
是第幾個捕獲租。這個規(guī)則被施加在無名通配符匹配谣蠢,比如/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
請求的協(xié)議,一般為http
勋锤,當啟用TLS加密饭玲,則為https
。 當trust proxy
設置一個啟用的參數(shù)叁执,如果存在X-Forwarded-Proto
頭部的話茄厘,其將被信賴和使用矮冬。這個頭部可以被客戶端或者代理設置。
req.ptotocol
// => "http"
req.query
一個對象次哈,為每一個路由中的query string
參數(shù)都分配一個屬性胎署。如果沒有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
中間件的時候趾撵,這個屬性包含的是請求發(fā)過來的簽名cookies
,不簽名的并且為使用做好了準備(這句真不知道怎么翻譯了...)共啃。簽名cookies
駐留在不同的對象中來體現(xiàn)開發(fā)者的意圖占调;不然,一個惡意攻擊可以被施加在req.cookie
值上(它是很容易被欺騙的)移剪。記住究珊,簽名一個cookie
不是把它藏起來或者加密;而是簡單的防止篡改(因為簽名使用的加密是私人的)纵苛。如果沒有發(fā)送簽名的cookie
剿涮,那么這個屬性默認為{}
。
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
req.signedCookies.user
// => "tobi"
為了獲取更多的信息赶站,問題或者關注幔虏,可以參閱cookie-parser。
req.stale
指示這個請求是否是stale
(陳舊的)贝椿,它與req.fresh
是相反的想括。更多信息,可以查看req.fresh烙博。
req.stale
// => true
req.subdomains
請求中域名的子域名數(shù)組瑟蜈。
// Host: "tobi.ferrets.example.com"
req.subdomains
// => ["ferrets", "tobi"]
req.xhr
一個布爾值,如果X-Requested-With
的值為XMLHttpRequest
渣窜,那么其為true
铺根,其指示這個請求是被一個客服端庫發(fā)送,比如jQuery
乔宿。
req.xhr
// => true
Methods
req.accepts(types)
檢查這個指定的內容類型是否被接受位迂,基于請求的Accept
HTTP頭部。這個方法返回最佳匹配,如果沒有一個匹配掂林,那么其返回undefined
(在這個case下臣缀,服務器端應該返回406和"Not Acceptable")。 type
值可以是一個單的MIME type
字符串(比如application/json
)泻帮,一個擴展名比如json
精置,一個逗號分隔的列表,或者一個數(shù)組锣杂。對于一個列表或者數(shù)組脂倦,這個方法返回最佳項(如果有的話)。
// 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頭部的域內容(不區(qū)分大小寫)状知。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
頭部域匹配參數(shù)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
腐晾。
返回當前參數(shù)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
來設置一個默認值藻糖,如果這個參數(shù)在任何一個請求的對象中都不能找到。
直接通過req.params
库车,req.body
懂酱,req.query
取得應該更加的清晰-除非你確定每一個對象的輸入。 Body-parser
中間件必須加載狮含,如果你使用req.param()
剩晴。詳細請看req.body。
Response
res
對象代表了當一個HTTP請求到來時珍坊,Express
程序返回的HTTP響應牺勾。在本文檔中,按照慣例阵漏,這個對象總是簡稱為res
(http請求簡稱為req
)驻民,但是它們實際的名字由這個回調方法在那里使用時的參數(shù)決定。 例如:
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
布爾類型的屬性叹洲,指示這個響應是否已經發(fā)送HTTP頭部柠硕。
app.get('/', function(req, res) {
console.log(res.headersSent); // false
res.send('OK'); // send之后就發(fā)送了頭部
console.log(res.headersSent); // true
});
res.locals
一個對象,其包含了響應的能夠反應出請求的本地參數(shù)和因此只提供給視圖渲染疹味,在請求響應的周期內(如果有的話)--我要翻譯吐了仅叫。否則,其和app.locals
是一樣的糙捺。(不知道翻譯的什么...) 這個參數(shù)在導出請求級別的信息是很有效的诫咱,這些信息比如請求路徑,已認證的用戶洪灯,用戶設置等等坎缭。
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
可以是一個字符串或者數(shù)組。 注意:在res.append()
之后調用app.set()
函數(shù)將重置前面設置的值憎夷。
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
參數(shù)可以是一串字符或者是轉化為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
協(xié)議使用爸业。
signed
Boolean
指示這個cookie應該是簽名的其骄。
res.cookie()所作的都是基于提供的options
參數(shù)來設置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
是一個方便設置過期時間的方便的選項,其以當前時間開始的毫秒數(shù)來計算钧忽。下面的示例和上面的第二條功效一樣毯炮。
res.cookie('rememberme', '1', {'masAge':90000}, "httpOnly":true);
你可以設置傳遞一個對象作為value
的參數(shù)。然后其將被序列化為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])
根據(jù)指定的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="的參數(shù)為path
(通常會出現(xiàn)在瀏覽器的對話框中)剂陡。通過指定filename
參數(shù)來覆蓋默認值鸦列。 當一個錯誤發(fā)生時或者傳輸完成,這個方法將調用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骆姐。用來快速結束請求,沒有任何的數(shù)據(jù)捏题。如果你需要發(fā)送數(shù)據(jù)玻褪,可以使用res.send()和res.json()這類的方法。
res.end();
res.status(404).end();
res.format(object)
進行內容協(xié)商公荧,根據(jù)請求的對象中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');
}
})
除了規(guī)范化的MIME類型之外池户,你也可以使用拓展名來映射這些類型來避免冗長的實現(xiàn):
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響應的頭部咏雌。匹配是區(qū)分大小寫凡怎。
res.get('Content-Type');
// => "text/plain"
res.json([body])
發(fā)送一個json的響應。這個方法和將一個對象或者一個數(shù)組作為參數(shù)傳遞給res.send()
方法的效果相同赊抖。不過统倒,你可以使用這個方法來轉換其他的值到json,例如null
氛雪,undefined
房匆。(雖然這些都是技術上無效的JSON)。
res.json(null);
res.json({user:'tobi'});
res.status(500).json({error:'message'});
res.jsonp([body])
發(fā)送一個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
是以傳入?yún)?shù)的屬性形式提供苗分,連接之后的內容用來填充響應的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
參數(shù)牵辣。
res.location('/foo/bar');
res.location('http://example.com');
res.location('back');
當path
參數(shù)為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文檔發(fā)送給客戶端曲楚。可選的參數(shù)為:
locals
褥符,定義了視圖本地參數(shù)屬性的一個對象龙誊。
callback
,一個回調方法喷楣。如果提供了這個參數(shù)趟大,render
方法將返回錯誤和渲染之后的模板,并且不自動發(fā)送響應铣焊。當有錯誤發(fā)生時逊朽,可以在這個回調內部,調用next(err)
方法曲伊。
本地變量緩存使能視圖緩存叽讳。在開發(fā)環(huán)境中緩存視圖,需要手動設置為true坟募;視圖緩存在生產環(huán)境中默認開啟岛蚤。
// 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])
發(fā)送HTTP響應。 body
參數(shù)可以是一個Buffer
對象懈糯,一個字符串涤妒,一個對象,或者一個數(shù)組赚哗。比如:
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' });
對于一般的非流請求她紫,這個方法可以執(zhí)行許多有用的的任務:比如硅堆,它自動給Content-Length
HTTP響應頭賦值(除非先前定義),也支持自動的HEAD和HTTP緩存更新贿讹。 當參數(shù)是一個Buffer
對象渐逃,這個方法設置Content-Type
響應頭為application/octet-stream
,除非事先提供围详,如下所示:
res.set('Content-Type', 'text/html');
res.send(new Buffer('<p>some html</p>'));
當參數(shù)是一個字符串朴乖,這個方法設置Content-Type
響應頭為text/html
:
res.send('<p>some html</p>');
當參數(shù)是一個對象或者數(shù)組,Express使用JSON格式來表示:
res.send({user:'tobi'});
res.send([1, 2, 3]);
res.sendFile(path [, options] [, fn])
res.sendFile()
從Express v4.8.0
開始支持助赞。
傳輸path
指定的文件买羞。根據(jù)文件的擴展名設置Content-Type
HTTP頭部。除非在options
中有關于root
的設置雹食,path
一定是關于文件的絕對路徑畜普。 下面的表提供了options
參數(shù)的細節(jié):
屬性
描述
默認值
可用版本
maxAge
設置Cache-Control
的max-age
屬性,格式為毫秒數(shù)群叶,或者是ms format的一串字符串
0
root
相對文件名的根目錄
lastModified
設置Last-Modified
頭部為此文件在系統(tǒng)中的最后一次修改時間吃挑。設置false
來禁用它
Enable
4.9.0+
headers
一個對象,包含了文件所在的sever的HTTP頭部街立。(不知道怎么翻譯了)
dotfiles
是否支持點開頭文件名的選項舶衬。可選的值"allow","deny","ignore"
"ignore"
當傳輸完成或者發(fā)生了什么錯誤赎离,這個方法調用fn
回調方法逛犹。如果這個回調參數(shù)指定了和一個錯誤發(fā)生,回調方法必須明確地通過結束請求-響應循環(huán)或者傳遞控制到下個路由來處理響應過程梁剔。 下面是使用了所有參數(shù)的使用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
并且發(fā)送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')
如果一個不支持的狀態(tài)被指定个盆,這個HTTP status依然被設置為statusCode
并且用這個code的字符串作為Body脖岛。
res.sendStatus(2000); // equivalent to res.status(2000).send('2000');
res.set(field [, value])
設置響應對象的HTTP頭部field
為value
。為了一次設置多個值颊亮,那么可以傳遞一個對象為參數(shù)鸡岗。
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路由。 路由自身表現(xiàn)為一個中間件临梗,所以你可以使用它作為app.use()
方法的一個參數(shù)或者作為另一個路由的use()
的參數(shù)涡扼。 頂層的express
對象有一個Router()
方法,你可以使用Router()
來創(chuàng)建一個新的router
對象盟庞。
Router([options])
如下吃沪,可以創(chuàng)建一個路由:
var router = express.Router([options]);
options
參數(shù)可以指定路由的行為,其有下列選擇:
屬性
描述
默認值
可用性
caseSensitive
是否區(qū)分大小寫
默認不啟用什猖。對待/Foo
和/foo
一樣票彪。
mergeParams
保存父路由的res.params
。如果父路由參數(shù)和子路由參數(shù)沖突不狮,子路由參數(shù)優(yōu)先降铸。
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
可以執(zhí)行一個任務无拗,然后調用next()
來將執(zhí)行流程移交到隨后的路由带到。
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()
等等囱嫩。 你可以提供多個回調函數(shù)恃疯,它們的行為和中間件一樣,除了這些回調可以通過調用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)
給路由參數(shù)添加回調觸發(fā)器受神,這里的name
是參數(shù)名,function
是回調方法格侯”翘回調方法的參數(shù)按序是請求對象,響應對象联四,下個中間件撑碴,參數(shù)值和參數(shù)名。雖然name
在技術上是可選的朝墩,但是自Express V4.11.0之后版本不推薦使用(見下面)醉拓。
不像app.param()
,router.param()
不接受一個數(shù)組作為路由參數(shù)。
例如廉嚼,當:user
出現(xiàn)在路由路徑中玫镐,你可以映射用戶加載的邏輯處理來自動提供req.user
給這個路由,或者對輸入的參數(shù)進行驗證怠噪。
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
上的路由具有這個路由參數(shù)時才起作用葛闷。 在定義param
的路由上憋槐,param
回調都是第一個被調用的,它們在一個請求-響應循環(huán)中都會被調用一次并且只有一次淑趾,即使多個路由都匹配阳仔,如下面的例子:
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
`
下面章節(jié)描述的router.param(callback)
在v4.11.0之后被棄用扣泊。
通過只傳遞一個回調參數(shù)給router.param(name, callback)
方法近范,router.param(naem, callback)
方法的行為將被完全改變。這個回調參數(shù)是關于router.param(name, callback)
該具有怎樣的行為的一個自定義方法延蟹,這個方法必須接受兩個參數(shù)并且返回一個中間件评矩。 這個回調的第一個參數(shù)就是需要捕獲的url的參數(shù)名摔踱,第二個參數(shù)可以是任一的JavaScript對象惕医,其可能在實現(xiàn)返回一個中間件時被使用锰提。 這個回調方法返回的中間件決定了當URL中包含這個參數(shù)時所采取的行為惜纸。 在下面的例子中猪勇,router.param(name, callback)
參數(shù)簽名被修改成了router.param(name, accessId)
碟狞。替換接受一個參數(shù)名和回調再姑,router.param()
現(xiàn)在接受一個參數(shù)名和一個數(shù)字备恤。
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)
參數(shù)簽名保持和原來一樣缰儿,但是替換成了一個中間件,定義了一個自定義的數(shù)據(jù)類型檢測方法來檢測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
參數(shù)指定的路徑掛載給定的中間件方法,未指定path
參數(shù),默認值為/
齐蔽。 這個方法類似于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()
定義中間件的順序很重要。中間們是按序被調用的联喘,所以順序決定了中間件的優(yōu)先級华蜒。例如,通常日志是你將使用的第一個中間件耸袜,以便每一個請求都被記錄友多。
var logger = require('morgan');
router.use(logger());
router.use(express.static(__dirname + '/public'));
router.use(function(req, res) {
res.send('Hello');
});
現(xiàn)在為了支持你不希望記錄靜態(tài)文件請求,但為了繼續(xù)記錄那些定義在logger()
之后的路由和中間件堤框。你可以簡單的將static()
移動到前面來解決:
router.use(express.static(__dirname + '/public'));
router.use(logger());
router.use(function(req, res){
res.send('Hello');
});
另外一個確鑿的例子是從不同的路徑托管靜態(tài)文件域滥,你可以將./public
放到前面來獲得更高的優(yōu)先級:
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
router.use()
方法也支持命名參數(shù),以便你的掛載點對于其他的路由而言蜈抓,可以使用命名參數(shù)來進行預加載启绰,這樣做是很有益的。
**1
**1
**1
**1