express中间件

参考:http://expressjs.com/en/4x/api.html

express自身是一个功能极简,完全是由路由和中间件构成的一个Web开发框架。 从本质上来说,一个express应用就是在调用各种中间件和路由。

中间件(Middleware)是一个函数,它可以访问请求对象(request)、响应对象(response), 和Web应用中处于请求-响应流程中的中间件,一般被命名为next方法。

中间件函数原型是:function ([Object error, ] Object request, Object response, Function next)

error对象是发生错误后的错误对象。

request对象是请求相关的对象。

response对象是响应相关的对象。

next如果被调用了,表示下一个中间件会接着执行,如果没有调用,后面的中间件就不会被执行了。

这种设计在架构模式中称为分层模式,在设计模式中称为责任链模式。在其他Web开发框架中经常会设计拦截器,拦截器通常使用观察者模式实现。 这种实现方法比拦截器更具有通用性、灵活性大大增强。

1.1、应用级中间件

应用级中间件绑定到app对象,使用app.use()或者app.METHOD()方法,METHODGETPOSTPUTDELETEHEADHTTP轻视方式,全部小写。

1.1.1、全局拦截器

如果不把中间件挂载到指定的URL上,那么就是对所有的请求都有效,如果我们把此中间件的调用放在最前面(防止被终结), 就实现了全局拦截器的效果。

示例:

var express = require('express');
var app = express();

app.use(function (request, response, next) {
    //TODO
    next();
});
1.1.2、404错误中间件

示例:

var express = require('express');
var app = express();

//other middleware invoked!

// catch 404 and forward to error handler
app.use(function (request, response, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

express中,404并不被看作是一个错误。因此,错误处理器中间件并不捕获404。 这是因为404只是意味着某些功能没有实现。也就是说,express执行了所有中间件、路由之后还是没有获取到任何输出。 你所需要做的就是在其他所有中间件的后面添加一个处理404的中间件。

这个中间件看似与全局拦截器一样,不同的地方就在与他放的地方,全局拦截器放在所有调用中间件的最前面,这是为了防止某些中间件没有调用next()方法而终止了后面的中间件。404错误中间件要放在所有中间件的后面,这是因为一旦其他中间件不能正确处理,他才有机会得到执行,其他中间件能正确处理,他就不会被执行。

1.1.3、挂载到指定URL上的中间件

示例:

var express = require('express');
var app = express();

app.use('/index', function(request, response, next) {
    //TODO
    next();
});

指定URL上的拦截器。

1.1.4、执行一组中间件

示例1:

var express = require('express');
var app = express();

app.use(function (request, response, next) {
    //TODO
    next();
}
, function (request, response, next) {
    //TODO
    next();
}
);

这有什么作用呢?为啥不写在一块儿呢?这是因为项目开发过程中为了预防变化,而将功能拆分开,如果不需要,直接注释掉即可, 而不需要改来改去的!

示例2:

var express = require('express');
var app = express();

app.use('/index', function (request, response, next) {
    //TODO
    next();
}
, function (request, response, next) {
    //TODO
    next();
}
);
1.2、路由级中间件

路由级中间件绑定到router对象,使用router.use()或者router.METHOD()方法,METHODGETPOSTPUTDELETEHEADHTTP轻视方式,全部小写。

示例:

var express = require('express');
var router = express.Router();

router.use(function (request, response, next) {
    //TODO
    next();
});

router.use('/index', function (request, response, next) {
    //TODO
    next();
});

router.get('/index', function (request, response, next) {
    //TODO
    next();
});
1.3、错误处理中间件

错误处理中间件有4个参数,定义错误处理中间件时必须使用这4个参数。即使不需要next方法,也必须在签名中声明它,否则中间件会被识别为一个常规中间件,不能处理错误。

示例:

var express = require('express');
var app = express();

app.use(function (error, request, response, next) {
    res.status(error.status || 500);

    if (app.get('env') === "development") {
        res.render('error-development', { error: error });
    } else {
        res.render('error-production', { error: error });
    }
});
1.4、内置中间件

4.x版本开始,express已经不再依赖Connect了。 除了express.static()express以前内置的中间件现在已经全部单独作为模块安装使用了。

示例:

var express = require('express');
var app = repress();

var options = {
    dotfiles  : 'ignore',
    etag      : false,
    extensions: ['htm', 'html'],
    index     : false,
    maxAge    : '1d',
    redirect  : false,
    setHeaders: function (response, path, stat) {
        response.set('x-timestamp', Date.now());
    }
};

app.use(express.static(path.join(__dirname, 'public'), options));
1.5、第三方中间件

通过使用第三方中间件从而为express应用增加更多功能。 安装所需功能的node模块,并在应用中加载,可以在应用级加载,也可以在路由级加载。

第三方中间件列表

下面是一些常用的第三方中间件:

  • basicAuth
    基本的身份认证功能,处理之后可以通过req.user属性访问被认证的用户对象。
  • bodyParser
    完成请求体消息的三种转换功能:json()、urlencoded()、multipart()、这三个中间件可以分别使用, 而bodyParse是对三者的统一封装
  • compress
    对response数据进行压缩处理
  • cookieParser
    Cookie头进行处理,然后通过req.cookies属性来访问所有cookie对象
  • cookieSession
    提供对Session的支持。我们知道大部分的服务器Session其实是通过cookie来实现的。 服务器端通过判断客户端发送的两次请求中某一个cookie项的值是否相同来认定是否是同一个session。 处理之后可以通过req.session属性访问session对象
  • csrf
    对CSRF(跨域请求伪造)保护的支持。CSRF是指伪造他人请求发送给受攻击的站点。其防御方法有验证HTTP Refer字段; 在请求地址中添加token并进行验证;在HTTP头中自定义属性并进行验证等等。该中间件就是通过生成token来解决的, 生成的token可以通过req.csrfToken()来进行访问

示例:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var app = repress();

app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
1.6、自定义中间件

中间件函数原型是:function ([Object error, ] Object request, Object response, Function next)

我们自己编写一个node.js模块,实现此函数即可,当然也可以直接使用匿名函数的方法。

示例(url-decode.js模块):

module.exports = function (request, response, next) {
    request.url = decodeURI(request.url);
    next();
};

然后调用(url-decode.js模块):

var express = require('express');
var app = express();

app.use('require(./url-decode.js)');

功能如此简单,我们可以直接写成如下,省去加载文件:

var express = require('express');
var app = express();

app.use(function (request, response, next) {
    request.url = decodeURI(request.url);
    next();
});

一定要注意调用顺序。