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

相关文章
相关标签/搜索