Express4.x API (一):application (譯)

寫在前面

Express文檔核心的四大部分app,request,response,router,基本上已經完成。簡單的總結css

  1. 經過調用express()返回獲得的app其實是一個JavaScript的Function,它是一個Express的應用實例;app對象具備HTTP請求,配置中間件,渲染HTML視圖,註冊模板引擎這四大功能。它還有一些屬性設置,這些屬性能夠改變程序的行爲html

  2. request對象即表示HTTP請求,包含了請求查詢字符串,參數,內容,HTTP頭等屬性node

  3. response對象則表示HTTP響應,即在受到請求時向客戶端發送的HTTP響應數據正則表達式

  4. 每一個Express程序有一個內建的app路由,頂層的express對象有一個Router()方法,你可使用Router()來建立一個新的router對象,你能夠把它當作一個mini-application,它具備操做路由和中間件的能力,有些方法和app類同express

技術庫更迭較快,很難使譯文和官方的API保持同步,咱們只有提高本身的英語能力才能更快的適應庫的更新迭代,閱讀到最新資料。
因此我這次翻譯的目的,一是熟悉express文檔,二是鍛鍊本身英語閱讀能力;json

原文地址:express.comapi

Application

app對象是指一個Express應用程序,經過調用的頂層的express()函數創造它數組

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.router
  • 渲染HTML視圖;例如:app.render
  • 註冊模板引擎;例如:app.engine

他還具備影響應用程序行爲的設置(屬性);得到更多的信息,見Application settingsapp

Properties

app.locals

app.locals是一個JavaScript對象,它的屬性是應用程序中的局部變量

app.locals.title  // "My App"

app.locals.email  // "me@myapp.com"

一旦設置,app.locals屬性的值將會貫穿整個生命週期。對比res.locals屬性的特性,res.locals僅適用於請求的生命週期

你能夠訪問應用程序中呈現的模板中的本地變量,這對於想模板提供協助函數以及app-level很是有用。可是請注意,您不能訪問中間件的局部變量

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();  // 主要的應用程序
var admin = express();  // 子應用程序

admin.get('/',function(req,res){
    console.log(admin.mountpath)  // admin
    res.send('Admin Homepage');
})

app.use('/admin',admin) // 掛載子應用程序

這相似於req對象中的baseUrl屬性,除了baseUrl返回匹配的URL路徑,而不是匹配的模式(s).

若是子應用程序掛載在多個路徑模式上,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); 
app.use(['/adm*n', '/manager'], admin);

Events

app.on('mount',callback(parent))

當子程序被掛載到父程序時,mount事件被髮射。父程序對象做爲參數,傳遞給回調方法。

var admin = express();

admin.on('mount',function(parent){
    console.log('Admin Mount');
    console.log(parent);   // 指父應用程序
})

admin.get('/',function(req,res){
    res.send('Admin homePage');
});

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

Methods

app.all(path,callback[,callback ...])

app.all方法和標準的app.METHOD()方法相似,除了它匹配全部的HTTP動詞。對於給一個特殊前綴映射一個全局的邏輯處理,或者無條件匹配,它是頗有效的。例如,若是你把下面內容放在全部其餘的路由定義的前面,它要求全部從這個點開始的路由須要認證和自動加載一個用戶。這些回調並不必定是終點:loadUser能夠在完成了上一個任務後,調用next()來繼續匹配隨後的路由。

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

或者這種相等的形式:

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

另外一個例子是全局白名單的方法(white-listed 「global」 functionality)。這個例子和前面很像,然而它只是限制以/api開頭的路徑。

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

app.delete(path, callback [, callback ...])

路由HTTP DELETE請求到有特殊回調方法的特殊的路徑。獲取更多的信息,能夠查閱routing guide

你能夠提供多個回調函數,他們的做用和中間件同樣,除了這些回調能夠經過調用next('router')來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是不能知足當前路由的處理條件,那麼你能夠傳遞控制到隨後的路由。

app.delete('/',function(req,res){
    res.send('DELETE request to homepage');
})

app.disable(name)

將設置名爲name的值爲false,此處的name是app settings table中各屬性的一個。調用app.set('foo',false)和app.disable('foo')是等價的

app.disable('trust proxy');
app.get('trust proxy');   // false

app.disabled(name)

若是name被禁用則返回true,此處的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)

若是name可用則返回true,此處的name是app settings table中各屬性的一個。

app.enabled('trust proxy')   // false
app.enable('trust proxy')   
app.enabled('trust proxy')   // true

app.engine(ext,callback)

註冊給定引擎的回調,用來渲染ext文件。默認狀況下,Express須要使用require()來加載基於文件擴展的引擎。例如,若是你嘗試渲染一個foo.jade文件,Express在內部調用下面內容,同時緩存require()結果供隨後來調用去提升性能

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

使用下面這種方法,來處理沒有辦法開箱即用的.express方法的模板,或者你但願使用不一樣的擴展名。

舉個栗子,使用ejs模板引擎來渲染.html文件:

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

在這個例子中,ejs提供了一個.renderFile方法,這個方法知足了Express規定的簽名規則:(path, options, callback),然而記住在內部它只是ejs.__express的一個別名,因此你能夠在不作任何事的狀況下直接使用.ejs擴展。一些模板引擎沒有遵循這種規範,consolidate.js庫映射模板引擎如下面的使用方式,因此他們能夠無縫的和Express工做。

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

app.get(name)

得到設置名爲name的app設置的值,此處的name是app settings table中各屬性的一個。 以下:

app.get('title');  // => undefined
app.set('title','My site');
app.get('title')  // 'My site'

app.get(path, callback [, callback ...])

使用指定的回調函數將HTTP請求路由到指定的路徑。獲取跟多的信息,能夠查閱routing guide。你能夠提供多個回調函數,他們的內容和中間件同樣,除了這些回調能夠經過調用next('router')來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由。

app.get('/',function(req,res){
    res.send('GET request to homepage')
})

app.listen(port, [hostname], [backlog], [callback])

綁定程序監聽端口到指定的主機端口號。這個方法和Node中的http.Server.listen()是同樣的

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

經過調用express()返回獲得的app其實是一個JavaScript的Function,被設計用來做爲一個回調傳遞給NODE HTTP servers來處理請求。這樣,其就能夠很簡單的基於同一份代碼提供的http和https版本,因此app沒有從這些繼承(它只是一個簡單的回調)。

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

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

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

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

app.METHOD(path,callback [,callback ...])

路由HTTP請求,METHOD是這個請求的HTTP方法,好比GET,POST,PUT等等,小寫。因此,實際方法是app.get,app.post,app.put等等,下面有關於方法完整的表。

獲取更多信息,請看routing guide。 Express支持下面的路由方法,對應與同名的HTTP方法:

具體見app.METHOD

若是使用上述方法時,致使了無效的JavaScript變量名,可使用中括號,好比:app['m-search']('/', function ....

你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒有知足當前路由的處理條件,那麼傳遞控制到隨後的路由。(個人話:"!這一段看了好幾遍啦- -,理解next傳遞很是重要性")

本API文檔把使用比較多的HTTP方法app.get(),app.post,app.put(),app.delete()做爲一個個單獨的項進行說明。然而,其餘上述列出的方法以徹底相同的方式工做。

有一種特殊的路由方法,app.all(),這不是來自任何HTTP方法。他在全部請求方法的路徑上加載中間件,其對於全部的方法都有效

app.param([name],callback)

給路由參數添加回調觸發器,這裏的name是參數名或者參數數組,function是回調方法。回調方法的參數按序是請求對象,響應對象,下箇中間件,參數值和參數名。 若是name是數組,會按照各個參數在數組中被聲明的順序將回調觸發器註冊下來。還有,對於除了最後一個參數的其餘參數,在他們的回調中調用next()來調用下個聲明參數的回調。只有一個參數,那麼就是最後一個參數,和數組中最後一個參數是同樣的。 例如,當:user出如今路由路徑中,你能夠映射用戶加載的邏輯處理來自動提供req.user給這個路由,或者對輸入的參數進行驗證。

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

    // 嘗試從用戶模型獲取用戶詳細信息並將其附加到請求對象
    User.find(id,function(err,user){
        if(err){
            next(err);
        }else if(user){
            req.user = user;
            next();
        }else{
            next(new Error('fail to load user'))
        }
    })
})

對於Param的回調定義的路由來講,他們是局部的。它們不會被掛載的app或者路由繼承。因此,定義在app上的Param回調只有是在app上的路由具備這個路由參數時才起做用。

在定義param的路由上,param回調都是第一個被調用的,它們在一個請求-響應循環中都會被調用一次而且只有一次,即便多個路由都匹配,以下面的栗子:

app.param('id',function(req,res,next,id){
    console.log('CALLED ONLY NOCE');
    next();
})

app.get('/user/:id',function(req,res,next){
    console.log('although this match');
    next();
})

app.get('/user/:id',function(req,res){
    console.log('and this matches too');
    res.end();
})

當GET/user/42,獲得下面結果

CALLED ONLY NOCE
 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(){
    console.log('although this matches');
    next();
})

app.get('/user/:id/:page',function(){
    console.log('and this matchs 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()的行爲
app.param(function(param,option){
    return function(req,res,next,val){
        if(val == option){
            next();
        }else{
            res.sendStatus(403);
        }
    }
})

// 使用定製的app.param()
app.param('id',1337);

// 觸發捕獲的路由
app.get('/user/:id', function (req, res) {
  res.send('OK');
})

app.listen(3000,function(){
    console.log('Ready');
})
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()

返回應用程序的規範路徑(字符串)

var app = express()
  , blog = express()
  , blogAdmin = express();

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

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

若是app掛載很複雜下,那麼這個方法的行爲也會很複雜:一種更好用的方式是使用req.baseUrl來得到這個app的典型路徑。

app.post(path, callback, [callback ...])

使用指定的回調函數將HTTP POST請求路由到指定的路徑。有關更多信息,請參見routing guide

你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由

app.post('/', function (req, res) {
  res.send('POST request to homepage');
});

app.put(path, callback [, callback ...])

使用指定的回調函數將HTTP PUT請求路由到指定的路徑。有關更多信息,請參見routing guide

你能夠提供多個回調函數,它們的行爲和中間件同樣,除了這些回調能夠經過調用next('router')來繞過剩餘的路由回調。你可使用這個機制來爲一個路由設置一些前提條件,若是請求沒能知足當前路由的處理條件,那麼傳遞控制到隨後的路由

app.put('/', function(req, res) {
    res.send('PUT request to homepage');
});

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

經過回調函數返回視圖的呈現HTML,它能夠接受一個可選的參數,可選參數包含了這個view須要用到的本地數據。這個方法相似於res.render(),除了它不能把渲染獲得的HTML文本發送給客戶端。

將app.render()看成是能夠生成渲染視圖字符串的工具方法。在res.render()內部,就是使用的app.render()來渲染視圖。

若是使能了視圖緩存,那麼本地變量緩存就會保留。若是你想在開發的過程當中緩存視圖,設置它爲true。在生產環境中,視圖緩存默認是打開的。

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

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

app.route(path)

返回一個單例模式的路由的實例,以後你能夠在其上施加各類HTTP動做的中間件。使用app.route()來避免重複路由名字

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 是 Application settings 中屬性的一項。

對於一個類型是布爾型的屬性調用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是程序設置之一,它將影響到程序的行爲。下邊列出了程序中的設置。
app.set

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'
  next();
});

在一個路徑上掛載一箇中間件以後,每當請求的路徑的前綴部分匹配了這個路由路徑,那麼這個中間件就會被執行。 因爲默認的路徑爲/,中間件掛載沒有指定路徑,那麼對於每一個請求,這個中間件都會被執行

// 此中間件將不容許請求超出它的範圍。
app.use(function(req, res, next) {
    console.log('Time: %d', Date.now());
    next();
});

路徑(path)能夠是表示路徑的字符串、路徑模式、匹配路徑的正則表達式或其組合數組

下面是中間件的簡單示例:

具體見app.use

下面是一些例子,在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'));

寫在後面

到此Express4.x API 譯文 系列文章已經完成。

本人學識有限,不免有所紕漏或者理解不當之處,翻譯僅僅是方便我的學習交流使用,無其餘用意(若是有不妥之處,請聯繫本人刪除),原文地址:expressjs.com

相關文章
相關標籤/搜索