express
翻譯
api文檔
中文
javascript
--css
express()
用來建立一個Express的程序。express()
方法是express模塊導出的頂層方法。html
var express = require('express');
var app = express();
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。vue
app
對象通常用來表示Express程序。經過調用Express模塊導出的頂層的express()
方法來建立它:java
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello world!');
});
app.listen(3000);
app
對象具備如下的方法:node
它還有一些屬性設置,這些屬性能夠改變程序的行爲。得到更多的信息,能夠查閱Application settings。jquery
app.locals
對象是一個javascript對象,它的屬性就是程序本地的變量。git
app.locals.title
// => 'My App'
app.locals.email
// => 'me@myapp.com'
一旦設定,app.locals
的各屬性值將貫穿程序的整個生命週期,與其相反的是res.locals
,它只在此次請求的生命週期中有效。github
在程序中,你能夠在渲染模板時使用這些本地變量。它們是很是有用的,能夠爲模板提供一些有用的方法,以及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
屬性是子程序掛載的路徑模式。
一個子程序是一個
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('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager' , on the parent app
當子程序被掛載到父程序時,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);
app.all
方法和標準的app.METHOD()
方法類似,除了它匹配全部的HTTP動詞。
對於給一個特殊前綴映射一個全局的邏輯處理,或者無條件匹配,它是頗有效的。例如,若是你把下面內容放在全部其餘的路由定義的前面,它要求全部從這個點開始的路由須要認證和自動加載一個用戶。記住這些回調並非必定是終點:loadUser
能夠在完成了一個任務後,調用next()
方法來繼續匹配隨後的路由。
app.all('*', requireAuthentication, loadUser);
或者這種相等的形式:
app.all('*', requireAuthentication);
app.all('*', loadUser);
另外一個例子是全局的白名單方法。這個例子和前面的很像,然而它只是限制以/api
開頭的路徑。
app.all('/api/*', requireAuthentication);
路由HTTP DELETE
請求到有特殊回調方法的特殊的路徑。獲取更多的信息,能夠查閱routing guide。
你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')
來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是不能知足當前路由的處理條件,那麼你能夠傳遞控制到隨後的路由。
app.delete('/', function(req, res) {
res.send('DELETE request to homepage');
});
設置類型爲布爾的設置名爲name
的值爲false
,此處的name
是app settings table中各屬性的一個。調用app.set('foo', false)
和調用app.disable('foo')
是等價的。
好比:
app.disable('trust proxy');
app.get('trust proxy');
// => false
返回true
若是布爾類型的設置值name
被禁用爲false
,此處的name
是app settings table中各屬性的一個。
app.disabled('trust proxy');
// => true
app.enable('trust proxy');
app.disabled('trust proxy');
// => false
設置布爾類型的設置值name
爲true
,此處的name
是app settings table中各屬性的一個。調用app.set('foo', true)
和調用app.enable('foo')
是等價的。
app.enable('trust proxy');
app.get('trust proxy');
// => true
返回true
若是布爾類型的設置值name
被啓動爲true
,此處的name
是app settings table中各屬性的一個。
app.enabled('trust proxy');
// => false
app.enable('trust proxy');
app.enabled('trust proxy');
// => true
註冊給定引擎的回調,用來渲染處理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);
得到設置名爲name
的app設置的值,此處的name
是app settings table中各屬性的一個。
以下:
app.get('title');
// => undefined
app.set('title', 'My Site');
app.get('title');
// => 'My Site'
路由HTTP GET
請求到有特殊回調的特殊路徑。獲取更多的信息,能夠查閱routing guide。
你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')
來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由。
app.get('/', function(req, res) {
res.send('GET request to homepage');
});
綁定程序監聽端口到指定的主機和端口號。這個方法和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);
};
路由一個HTTP請求,METHOD
是這個請求的HTTP方法,好比GET
,PUT
,POST
等等,注意是小寫的。因此,實際的方法是app.get()
,app.post()
,app.put()
等等。下面有關於方法的完整的表。
獲取更多信息,請看routing guide。
Express支持下面的路由方法,對應與同名的HTTP方法:
|
|
|
若是使用上述方法時,致使了無效的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
});
給路由參數添加回調觸發器,這裏的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
典型的路徑,其是一個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的典型路徑。
路由HTTP POST
請求到有特殊回調的特殊路徑。獲取更多的信息,能夠查閱routing guide。
你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')
來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由。
app.post('/', function(req, res) {
res.send('POST request to homepage')
});
路由HTTP PUT
請求到有特殊回調的特殊路徑。獲取更多的信息,能夠查閱routing guide。
你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')
來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由。
app.put('/', function(req, res) {
res.send('PUT request to homepage');
});
經過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) {
// ...
});
返回一個單例模式的路由的實例,以後你能夠在其上施加各類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...
})
給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 | 若是爲 |
IP addresses | 一個IP地址,子網,或者一組IP地址,和委託子網。下面列出的是一個預先配置的子網名列表。
使用下面方法中的任何一種來設置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 | 設置爲 |
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('/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 /abcd
app.use('/abcd', function (req, res, next) { next(); }) |
Path Pattern | // will match paths starting with /abcd and /abd
app.use('/abc?d', function (req, res, next) { next(); }) // will match paths starting with /abcd, /abbcd, /abbbbbcd and so on app.use('/ab+cd', function (req, res, next) { next(); }) // will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so on app.use('/ab\*cd', function (req, res, next) { next(); }) // will match paths starting with /ad and /abcd app.use('/a(bc)?d', function (req, res, next) { next(); }) |
Regular Expression | // will match paths starting with /abc and /xyz
app.use(/\/abc|\/xyz/, function (req, res, next) { next(); }) |
Array | // will match paths starting with /abcd, /xyza, /lmn, and /pqr
app.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'));
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);
});
在Express 4
中,req.files
默認在req
對象中再也不是可用的。爲了經過req.files
對象來得到上傳的文件,你可使用一個multipart-handling
(多種處理的工具集)中間件,好比busboy
,multer
,formidable
,multipraty
,connect-multiparty
或者pez
。
這個屬性持有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'));
};
一個路由實例掛載的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
返回的是路徑匹配模式。
在請求的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);
});
當使用cookie-parser
中間件的時候,這個屬性是一個對象,其包含了請求發送過來的cookies
。若是請求沒有帶cookies
,那麼其值爲{}
。
// Cookie: name=tj
req.cookies.name
// => "tj"
獲取更多信息,問題,或者關注,能夠查閱cookie-parser。
指示這個請求是不是新鮮的。其和req.stale
是相反的。
當cache-control
請求頭沒有no-cache
指示和下面中的任一一個條件爲true
,那麼其就爲true
:
if-modified-since
請求頭被指定,和last-modified
請求頭等於或者早於modified
響應頭。if-none-match
請求頭是*
。if-none-match
請求頭在被解析進它的指令以後,不匹配etag
響應頭(徹底不知道什麼鬼)。 req.fresh
// => true
包含了源自Host
HTTP頭部的hostname
。
當trust proxy
設置項被設置爲啓用值,X-Forwarded-Host
頭部被使用來代替Host
。這個頭部能夠被客戶端或者代理設置。
// Host: "example.com"
req.hostname
// => "example.com"
當trust proxy
設置項被設置爲啓用值,這個屬性包含了一組在X-Forwarded-For
請求頭中指定的IP地址。否則,其就包含一個空的數組。這個頭部能夠被客戶端或者代理設置。
例如,若是X-Forwarded-For
是client
,proxy1
,proxy2
,req.ips
就是["clinet", "proxy1", "proxy2"]
,這裏proxy2
就是最遠的下游。
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"
一個對象,其包含了一系列的屬性,這些屬性和在路由中命名的參數名是一一對應的。例如,若是你有/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"
包含請求URL的部分路徑。
// example.com/users?sort=desc
req.path
// => "/users"
當在一箇中間件中被調用,掛載點不包含在
req.path
中。你能夠查閱app.use()得到跟多的信息。
請求的協議,通常爲http
,當啓用TLS加密,則爲https
。
當trust proxy
設置一個啓用的參數,若是存在X-Forwarded-Proto
頭部的話,其將被信賴和使用。這個頭部能夠被客戶端或者代理設置。
req.ptotocol
// => "http"
一個對象,爲每個路由中的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"
當前匹配的路由,其爲一串字符。好比:
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}
}
一個布爾值,若是創建的是TLS的鏈接,那麼就爲true
。等價與:
'https' == req.protocol;
當使用cookie-parser
中間件的時候,這個屬性包含的是請求發過來的簽名cookies
,不簽名的而且爲使用作好了準備(這句真不知道怎麼翻譯了...)。簽名cookies
駐留在不一樣的對象中來體現開發者的意圖;否則,一個惡意攻擊能夠被施加在req.cookie
值上(它是很容易被欺騙的)。記住,簽名一個cookie
不是把它藏起來或者加密;而是簡單的防止篡改(由於簽名使用的加密是私人的)。若是沒有發送簽名的cookie
,那麼這個屬性默認爲{}
。
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
req.signedCookies.user
// => "tobi"
爲了獲取更多的信息,問題或者關注,能夠參閱cookie-parser。
指示這個請求是不是stale
(陳舊的),它與req.fresh
是相反的。更多信息,能夠查看req.fresh。
req.stale
// => true
請求中域名的子域名數組。
// Host: "tobi.ferrets.example.com"
req.subdomains
// => ["ferrets", "tobi"]
一個布爾值,若是X-Requested-With
的值爲XMLHttpRequest
,那麼其爲true
,其指示這個請求是被一個客服端庫發送,好比jQuery
。
req.xhr
// => true
檢查這個指定的內容類型是否被接受,基於請求的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。
返回指定的字符集集合中第一個的配置的字符集,基於請求的Accept-Charset
HTTP頭。若是指定的字符集沒有匹配的,那麼就返回false。
獲取更多信息,或者若是你有問題或關注,能夠參閱accepts。
返回指定的編碼集合中第一個的配置的編碼,基於請求的Accept-Encoding
HTTP頭。若是指定的編碼集沒有匹配的,那麼就返回false。
獲取更多信息,或者若是你有問題或關注,能夠參閱accepts。
返回指定的語言集合中第一個的配置的語言,基於請求的Accept-Language
HTTP頭。若是指定的語言集沒有匹配的,那麼就返回false。
獲取更多信息,或者若是你有問題或關注,能夠參閱accepts。
返回指定的請求HTTP頭部的域內容(不區分大小寫)。Referrer
和Referer
的域內容可互換。
req.get('Content-type');
// => "text/plain"
req.get('content-type');
// => "text/plain"
req.get('Something')
// => undefined
其是req.header(field)
的別名。
若是進來的請求的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.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"
按下面給出的順序查找:
可選的,你能夠指定一個defaultValue
來設置一個默認值,若是這個參數在任何一個請求的對象中都不能找到。
直接經過
req.params
,req.body
,req.query
取得應該更加的清晰-除非你肯定每個對象的輸入。Body-parser
中間件必須加載,若是你使用req.param()
。詳細請看req.body。
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);
});
這個屬性持有express
程序實例的一個引用,其能夠在中間件中使用。 res.app
和請求對象中的req.app
屬性是相同的。
布爾類型的屬性,指示這個響應是否已經發送HTTP頭部。
app.get('/', function(req, res) {
console.log(res.headersSent); // false
res.send('OK'); // send以後就發送了頭部
console.log(res.headersSent); // true
});
一個對象,其包含了響應的可以反應出請求的本地參數和所以只提供給視圖渲染,在請求響應的週期內(若是有的話)--我要翻譯吐了。不然,其和app.locals
是同樣的。(不知道翻譯的什麼...)
這個參數在導出請求級別的信息是頗有效的,這些信息好比請求路徑,已認證的用戶,用戶設置等等。
app.use(function(req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
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');
設置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
設置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});
根據指定的name
清除對應的cookie。更多關於options
對象能夠查閱res.cookie()
。
res.cookie('name', 'tobi', {'path':'/admin'});
res.clearCookie('name', {'path':'admin'});
傳輸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.
}
});
結束本響應的過程。這個方法實際上來自Node
核心模塊,具體的是response.end() method of http.ServerResponse。
用來快速結束請求,沒有任何的數據。若是你須要發送數據,可使用res.send()和res.json()這類的方法。
res.end();
res.status(404).end();
進行內容協商,根據請求的對象中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'});
}
})
返回field
指定的HTTP響應的頭部。匹配是區分大小寫。
res.get('Content-Type');
// => "text/plain"
發送一個json的響應。這個方法和將一個對象或者一個數組做爲參數傳遞給res.send()
方法的效果相同。不過,你可使用這個方法來轉換其餘的值到json,例如null
,undefined
。(雖然這些都是技術上無效的JSON)。
res.json(null);
res.json({user:'tobi'});
res.status(500).json({error:'message'});
發送一個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"})
鏈接這些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"
設置響應的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的責任;相應地重定向它。(我也不知道翻譯的什麼...)
重定向來源於指定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');
渲染一個視圖,而後將渲染獲得的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) {
// ...
});
發送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()
從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。
設置響應對象的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');
設置響應對象的HTTP頭部field
爲value
。爲了一次設置多個值,那麼能夠傳遞一個對象爲參數。
res.set('Content-Type', 'text/plain');
res.set({
'Content-Type':'text/plain',
'Content-Length':'123',
'ETag':'123456'
})
其和res.header(field [,value])
效果一致。
使用這個方法來設置響應對象的HTTP status。其是Node中response.statusCode的一個連貫性的別名。
res.status(403).end();
res.status(400).send('Bad Request');
res.status(404).sendFile('/absolute/path/to/404.png');
設置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:
設置Vary
響應頭爲field
,若是已經不在那裏。(不懂什麼意思)
res.vary('User-Agent').render('docs');
一個router
對象是一個單獨的實例關於中間件和路由。你能夠認爲其是一個"mini-application"(迷你程序),其具備操做中間件和路由方法的能力。每一個Express
程序有一個內建的app路由。
路由自身表現爲一箇中間件,因此你可使用它做爲app.use()
方法的一個參數或者做爲另外一個路由的use()
的參數。
頂層的express
對象有一個Router()
方法,你可使用Router()
來建立一個新的router
對象。
以下,能夠建立一個路由:
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);
這個方法和router.METHOD()
方法同樣,除了這個方法會匹配全部的HTTP動做。
這個方法對想映射全局的邏輯處理到特殊的路徑前綴或者任意匹配是十分有用的。好比,若是你放置下面所示的這個路由在其餘路由的前面,那麼其將要求從這個點開始的全部的路由進行驗證操做和自動加載用戶信息。記住,這些全局的邏輯操做,不須要結束請求響應週期:loaduser
能夠執行一個任務,而後調用next()
來將執行流程移交到隨後的路由。
router.all('*', requireAuthentication, loadUser);
相等的形式:
router.all('*', requireAuthentication)
router.all('*', loadUser);
這是一個白名單全局功能的例子。這個例子很像前面的,不過其僅僅做用於以/api
開頭的路徑:
router.all('/api/*', requireAuthentication);
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);
});
給路由參數添加回調觸發器,這裏的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);
});
返回一個單例模式的路由的實例,以後你能夠在其上施加各類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方法。
給可選的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()
方法也支持命名參數,以便你的掛載點對於其餘的路由而言,可使用命名參數來進行預加載,這樣作是頗有益的。