相關閱讀:
Express 4.X API 翻譯[一] -- Application篇
Express 4.X Api 翻譯[二] -- Request篇
本文是Express 4.x Api翻譯系列的第一篇。由於筆者最近在學習NodeJs,剛剛接觸了Node式的開發模式,被異步IO的編程方式深深吸引,於是准備系統學習一下這項新技術。因為沒有任何NodeJs的基礎,也不知道從何學起,之前也研究過ByVoid的《NodeJs開發指南》也不知道算不算入門。想試着寫一下里面的微博例子,但是發現自己安裝的Express是最新的4.X,網上對於Express的內容本來就很少,更別說是最新的開發文檔了,索性就開始先翻譯一下Express的Api,本篇是Express 4.x中文手冊的第一篇,以下內容來自原文網站 >>>Express官方網站
寫在前面
本文適用的Express版本為V4.0.0,一下內容不能保證同樣適用於之前的版本。由於筆者屬於剛剛接觸Express所以沒有研究過之前的版本與4.0.0版本的區別,之后在接下來的時間里,筆者會翻譯更多關於Express的文章供大家學習。
express()
創建一個express應用
var express = require('express'); var app = express(); app.get('/',function(req,res){ res.send('hello world'); }); app.listen(3000);
setting
以下的設置選項將為您展示如何改變Express的行為:
- env 運行時環境,默認為process.env.NODE_ENV(NODE_ENV環境變量)或者”development”;
- trust proxy 激活反向代理模式,默認為未激活;
- jsonp callback name JSON回調函數替換體,默認為空;
- case sensitive routing 用於激活路由大小寫敏感,默認為未激活,”/Foo”和”/foo”是相同對待的;
- strict routing 激活嚴格路由模式,默認”/foo”和”/foo/”是相同對待的;
- view cache 激活模板引擎編譯緩存,在生產模式默認是開啟的;
- view engine 缺省狀態下默認的模板引擎
- views 模板目錄地址,默認為”process.cwd() + ‘/views’”
app.set(name,value)
將設置項name的值設置為value
app.set('title',My Site); app.get('title');//=>"My Site"
app.get(name)
獲取設置項name的值
app.get('title'); //=> undefined app.set('title','My Site'); app.get('title'); //=>"My Site"
app.enable(name)
將設置項name的值設為true
app.enable('trust proxy'); app.get('trust proxy'); //=>true
app.disable(name)
將設置項name的值設置為false
app.disable('trust proxy'); app.get('trust proxy'); //=>false
app.enabled(name)
檢查設置項name的狀態是否為激活狀態
app.enabled('trust proxy'); //=>false app.enable('trust proxy'); app.enabled('trust proxy'); //=>true
app.disabled(name)
檢查設置項name的狀態是否為未激活狀態
app.disabled('trust proxy'); //=>true app.disable('trust proxy'); app.disabled('trust proxy'); //=>false
app.use([path],function)
使用給定的中間件function,可選參數path,默認為”/”.
var express = require('express'); var app = express(); //simple logger app.use(function(req,res,next){ console.log("%s %s",req.method,req.url); next(); }); app.use(function(req,res,next){ res.send('Hello World'); }); app.listen(3000);
//GET /javascript/jquery.js //GET /style.css //GET /favicon.ico app.use(express.static(__dirname + '/public'));
例如你想為所有的靜態文件增加前綴”/static”,你可以使用“掛載”功能來支持者也操作。被掛載的中間件函數是不會被調用的除非req.url中包含這個前綴,當函數被調用時,這個前綴是被剝去的。當然,這只會影響這個函數,后面的中間件還是會看見req.url中的”/static”被包含的,除非這些中間件也被掛載在”/static”下。
//GET /static/javascripts/jquery.js //GET /static/style.css //GET /static/favicon.ico app.use('/static',express.static(__dirname + '/public'));
使用“被定義的”app.use()的順序非常重要,它們將被順序調用,因此app.use()調用的先后順序決定了中間件的優先級。例如通常任何的日志記錄中間件將被定義在任何被使用的中間件之前:
var logger = require('morgan'); app.use(logger()); app.use(express.static(__dirname + '/public')); app.use(function(req,res){ res.send('Hello'); });
現在假如你想忽略請求靜態文件的記錄,但是又想繼續記錄logger()被定義之后的路由和中間件,那么你只需要將static()移動到logger()之前就可以了。
app.use(express.static(__dirname + '/public')); app.use(logger()); app.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'));
app.engine(ext,callback)
注冊模板引擎的callback來處理擴展名為ext的文件,默認情況下會根據文件的擴展名開引入相應的模板引擎。例如,如果你試圖渲染一個”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專門把所有的node流行的模板引擎進行了包裝,這樣他們在Express內部看起來就一樣了。
var engines = require('consolidate'); app.engine('haml',engines.haml); app.engine('html',engines.hogan);
app.param([name],callback)
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('failed to load user')); } }); });
這個例子有點高級,當檢測到如果第二個參數為正則表達式的話,返回一個很像上面”user”例子的行為的回調函數
app.param(function(name,fn){ if(fn instanceof RegExp) { return function(req,res,next,val){ var captures; if (captures = fn.exec(String(val))){ req.params[name] = captures; next(); } else{ next('route'); } } } });
這個函數現在可以非常有效的用來校驗參數,或者提供正則捕獲后的分組。
app.param('id',/^\d+$/); app.get('/user/:id',function(req,res){ res.send('user' + req.params.id); }); app.apram('range',/^(\w+)\.\.(\W+)?$/); app.get('/range/:range',function(req,res){ var range = req.param.range; res.send('from ' + range[1] + 'to ' + range[2] ); });
app.VERB(path,[callback...],callback)
app.VERB()方法為Express提供了路由方法,這里的VERB指的是一種HTTP動作,比如說app.post()。可以提供多個callback,這多個callback都將會被同等對待,他們的行為就像是中間件一樣,但也有一個例外的情況,如果某一個callback調用了next(‘route’),那么他后面的callback就會被忽略。這種情況會被應用在當滿足一個路由前綴,但是不需要用這個回調函數處理這個路由,於是就把它向后傳遞。
下面的這個代碼片段演示了一個最簡單的路由定義。Express會吧字符串表達式轉換為正則表達式,然后在內部匹配傳入的表達式。請求參數將不會被考慮進來。例如 “GET /”將會匹配下面的路由規則,同樣 “GET /?name=tobi”也會被下面的規則匹配。
app.get('/',function(req,res){ res.send('Hello World'); });
正則表達式也是可以被使用的,尤其是在你有特別的限制時這將會是非常有用的,例如下面的例子將會匹配 “GET /commits/71dbb9c” 同樣也會匹配 “GET /commits/71dbb9c..4c084f9″。
app.get(/^\/commits\/(\w+)(?:\..\..(\w+))?$/,function(req,res){ var from = req.params[0]; var to = req.params[1] || 'HEAD'; res.send('commit range ' + from + '...' + to); });
可以傳遞一些回調,這對於復用一些加載資源、校驗中間件很有作用
app.get('/user/:id',user.load,function(){ //...... });
如果你有眾多的中間件為一個路由規則,你也可以使用路由ap的all()。
var middleware = [loadForum,loadThread]; app.route('/forum/:fid/thread/:tid') .all(loadForum) .all(loadThread) .get(function(){ //.....}) .post(function(){//......})
所有的中間件規則將會被應用與GET 和 POST 請求。
app.all(path,[callback...],callback)
app.all('*',requireAuthentication,loadUser);
它相當於:
app.all('*',requireAuthentication);
app.all('*',loadUser);
另一個更好的例子就是全局白名單函數,這個例子很像之前的,然而它限制了前綴必須為”/api”:
app.all('/api/*',requireAuthentication);
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.locals
應用程序的本地變量會被附加給所有在這個應用程序內渲染的模板。這是一個非常有用的模板函數,就像是應用程序級的數據一樣。
app.locals.title = "My App"; app.locals.strftime = require('strftime'); app.locals.emall = 'me@myapp.com';
app.locals對象是一個Javascript對象。添加到它的屬性,將會被當做局部變量在應用程序中被公開。
app.locals.title //=>'My App' app.locals.email // =>'me@myapp.com'
默認情況下Express之有一個應用程序級的局部變量,那就是setting。
app.set('title','My App'); //use settings.title in a view
app.render(view,[options],callback)
渲染 view,callback用來處理返回渲染后的字符串。這個是res.render()的應用程序級的版本,它們的行為是一樣的。
app.render('email',function(err,html){ //....... }); app.render('email',{name:'Tobi'},function(err,html){ //....... })
app.listen()
在給定的主機和端口上監聽請求,這個和node的文檔http.Server#listen()是一致的
var express = require('express'); var app = express(); app.listen(3000);
通過express()返回的 app 事實上是一個Javascript函數,它被設計為傳遞給node的http Server作為處理請求的回調函數。由於app並不是通過HTTP或HTTPS繼承來的,它只是一個簡單的callback,所以這允許你很輕松的使用同樣的代來處理HTTP和HTTPS請求。
var express = require('express'); var https = require('https'); var http = require('http'); var app = express(); http.createServer(app).listen(80); https.createServer(options,app).listen(443);
app.listen()方法只是被定義為一個簡單的方法,如果你希望是用HTTPS協議或者同時使用HTTP和HTTPS,可以使用上面的技術。
app.listen = function(){ var server = http.createServer(this); return server.listen.apply(server,arguments); }
轉自:http://www.90it.net/expressjs-4-api-zh-cn-application.html