已經完成了Express4.x API中的Requst和Response對象的文檔翻譯。簡單的總結,request對象即表示HTTP請求,包含了請求查詢字符串,參數,內容,HTTP頭等屬性;response對象則表示HTTP響應,即在受到請求時向客戶端發送的HTTP響應數據。Express則基於此提供給咱們一些方法,完成指定的請求和響應。html
技術庫更迭較快,很難使譯文和官方的API保持同步,咱們只有提高本身的英語能力才能更快的適應庫的更新迭代,閱讀到最新資料。
因此我這次翻譯的目的,一是熟悉express文檔,二是鍛鍊本身英語閱讀能力;正則表達式
原文地址:express.comexpress
router
對象是中間件和路由的隔離實例,你能夠把它看作一個僅能執行中間件和路由功能的mini-applaction
,每個Express應用程序實例都有一個內置的路由器json
路由器的行爲相似於中間件自己,因此你能夠把他做爲一個參數傳遞給app.use()
或者做爲參數傳遞給另外一個路由器的use()
方法。Express top-level
對象有一個Router()建立一個新的路由器對象api
建立一個新的路由器對象數組
var router = express.Router([options]);
可選擇的options參數指定路由器的行爲app
Property | Description | Default |
---|---|---|
caseSensitive | 是否啓用大小寫敏感 | 默認狀況下不敏感,以相同的方式對待"/Foo","/foo" |
mergeParams | 從父路由器保存req.params 值,若是子父有衝突的參數名稱,以子路由參數優先 |
false |
strict | 啓用嚴格路由 | 默認狀況下是禁用的,"/foo"和"/foo/"是相同的 |
你能夠像應用程序那樣添加中間件和HTTP方法路由(例如get,put,post等等)函數
// 調用傳遞給次路由的任何請求 router.use(function(req,res,next){ // 一些邏輯,和其餘中間件同樣 next(); }) // 將會處理任何以/events結束的請求 router.get('/events',function(req,res,next){ // .. })
而後你能夠爲你特定的URL使用路由器,用這種方式把你的routes分爲文件甚至是mini-apps
post
app.use('/calendar',router);
這個方法就像router.METHHOD()
,除了他匹配全部的HTTP方法學習
這個方法對於映射特定路徑前綴或任意匹配的"全局"邏輯很是有用。舉個栗子,若是你將如下路由置於全部路由的最前面,它要求從該點的全部路由都須要身份認證,並自動加載user。記住這些回調函數沒必要做爲終點,loadUser
能夠執行任務,而後經過next()
傳遞繼續匹配給後續的路由
router.all('*',requireAuthentication,loadUser);
等價於
router.all('*',requireAuthentication) router.all('*',loadUser)
另外一個例子是white-listed
"global"功能,這裏的例子很是的類似,可是它只限制路徑的前綴"/api"
router.all('/api/*',requireAuthentication);
router.METHOD()
方法在Express中提供路由功能,其中METHOD是HTTP方法之一,例如GET,POST,PUT等等,固然你能夠小寫。因此實際的方法是router.get()
,router.post()
,router.put()
等等
router.get()
函數將會自動的調用HTTP HEAD方法,除了router.head()
在router.get()
以前要求沒有走這條路
你能夠提供多個回調,每一個回調都被平等對待,表現的就像中間件,除了這些回調函數能夠調用next(route)
繞過其他路由回調。您可使用此機制在路由上執行預條件,而後在沒有理由繼續匹配路由的狀況下將控制傳遞給後續路由。
下面片斷展現了最簡單的路由定義,Express將字符串轉化爲正則表達式,在內部用於匹配傳入請求。執行這些匹配時不考慮查詢字符串,例如'GET'將匹配下面路由,像GET/?name='tobi'
router.get('/',function(req,res){ res.send('hello world') })
若是你有很是具體的約束條件,還可使用正則表達式。舉個栗子下面將會匹配"GET /commits/71dbb9c"以及 "GET /commits/71dbb9c..4c084f9".
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/,function(req,res){ var from = req.params[0]; var to = req.params[1] || 'HEAD'; res.send('commit range' + form + '..' + to); })
添加回調觸發到路由參數中,name是參數的名稱,callback是回調函數。雖然name在技術上是可選的,可是從Express v4.11.0沒有它是不推薦使用這種方法的(以下)
不像
app.param()
,router.param()
不接受數組參數
舉個栗子,當:user
在路由路徑中存在時,能夠將用戶加載映射爲自動提供req.user
給這個路由,或者執行驗證的參數輸入
router.param('user',function(req,res,next,id){ //嘗試從用戶模型獲取用戶詳細信息並將其附加到請求對象 User.find(id,function(err,user){ if(err){ next(err); }else if(user){ req.user = user; next(); }else{ next(new Error('fail to load user')) } }) })
該回調方法是在本地路由器上定義他們,它們不是由加載的應用程序或路由器繼承的。所以,定義在路由上的參數回調只有經過router
定義的路由參數纔會觸發
一個回調參數將被稱爲一次請求響應週期,即便參數在多個路徑中匹配,以下面的栗子所示:
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 matchs '); next(); }) router.get('/user/:id',function(req,res){ console.log('and this matchs too '); res.end(); })
將會依次打印:
CAALED ONLY ONCE although this matchs and this matchs too
如下部分描述
router.param(callback)
在v4.11.0將是過期的
router.param(name,callback)
方法的行爲經過僅傳遞一個函數到router.param()
將會徹底改變。此功能是如何實現router.param(name,callback)
的習慣-它接受兩個參數,必須返回一箇中間件
函數返回的中間件決定了URL參數被捕獲時發生的行爲
在下面這個例子中,router.param(name,callback)
簽名被修改成router.param(name, accessId)
。router.param()將會接受一個
name和一個
number而不是一個
name和一個
回調函數`
var express = require('express'); var app = express(); var router = express.Router(); // 定製 `router.param()`的功能 router.param(function(param,option){ return function(req,res,next,val){ if(val == option){ next(); }else{ res.sendStatus(403); } } }) // 使用定製的`router.param()` 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)
簽名是相同的,但不是一箇中間件回調,一個自定義檢查函數定義了驗證用戶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 verbs,使用router.route()
爲了不重複路由命名,從而鍵入錯誤。
在上面router.param()
栗子的基礎上,下面的栗子展現瞭如何使用router.route()
指定HTTP處理方法
var router = express.Router(); router.param('user_id',function(req,res,next,id){ // 示例用戶,可能實際將從db等獲取 req.user = { id:id, name:'TJ' }; next(); }) router.route('/users/:user_id') .all(function(req,res,next){ // .. next() }) .get(function(req,res,next){ res.json(req.user) }) .put(function(req,res){ req.user.name = req.params.name; // 保存用戶等 res.json(req.user) }) .post(function(req,res,next){ next(new Error('not implemented')); }) .delete(function(req,res,next){ next(new Error('not implemented')) });
這個方法再利用單一/users/:user_id
路徑而且爲各類HTTP方法添加處理程序
使用指定中間件函數或者函數,可選的參數是掛載路徑,默認是"/"
這個方法相似於app.use()
。下面展現了一個簡單的示例和用例:
中間件就像是管道,請求在第一個中間件函數定義時開始,併爲它們"向下"匹配每一條路徑處理中間件堆棧處理。
var express = require('express'); var app = express(); var router = express.Router(); router.use(function(req,res){ console.log('%s %s %s',req.method,req.url,req.path); next(); }) // 下面只有當路徑從掛載點開始時,纔會調用這個函數 router.use('/bar',function(req,res,next){ // .. next(); }) // 老是調用 router.use(function(req,res,next){ res.send('Hello world') }); app.use('/foo',router); app.listen(3000);
「掛載」路徑被剝離而且對中間件功能不可見。這個功能的主要做用是:無論它的"prefix前綴"路徑,安裝中間件功能可能沒有代碼的變化
爲了保證您使用router.use()
定義的中間件的重要性。他們按順序調用,所以順序定義中間件優先級。舉個栗子:一般logger
是您將使用的第一個中間件,所以每一個請求都會被記錄
var logger = require('morgan'); router.user(logger()); router.use(express.static(__dirname+'/public')); router.use(function(req,res){ res.send('hello') })
如今假設您忽略了對靜態文件的日誌請求,可是在logger()
以後要繼續記錄路由和中間件定義。你只需簡單的移動express.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()
方法也支持命名參數,這樣,其餘路由器的掛載點能夠經過使用命名參數預加載來獲益。
NOTE:雖然這些中間件功能是經過特定路由器添加的,當他們運行時由他們鏈接到的路徑來定義(而不是路由)。所以,若是路由器的路由匹配,則經過一個路由器添加的中間件能夠運行其餘路由器。舉個栗子,下面顯示安裝在同一路徑上的兩個不一樣的路由器:
var autoRouter = express.Router(); var openRouter = express.Router(); autoRouter.use(require('./authenticate').basic(usersdb)); autoRouter.get('/:user_id/edit',function(req,res,next){ // .. 編輯用戶界面 .. }) openRouter.get('/',function(req,res,next){ // .. 用戶列表 .. }) openRouter.get('/:user_id',function(req,res,next){ // .. 查看用戶 .. }) app.use('/users',authRouter); app.use('/users',openRouter);
儘管authenticate
中間件是經過autoRouter
路由加入的,可是它也將運行在openRouter定義的路由上,由於兩個路由器都掛載在/users
。爲了不這種行爲發生,爲每一個路由器使用不一樣的路徑。
Express文檔中Router部分就完成了,本人學識有限,不免有所紕漏或者理解不當之處,翻譯僅僅是方便我的學習交流使用,無其餘用意,原文地址:expressjs.com