Nodejs Express 4.X 中文API 1--- Application篇
相关阅读:
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