在Express 的app.js文件中,可以向应用添加一些中间件。Express 的通过方法重载将中间件添加到应用中,这些中间件可以被其后路由中的GET、POST等HTTP方法使用,也可以通过中间件做一些通用的处理。
1. Expres中的中间件
Express 应用创建后,会默认添加几个中间件。在app.js中:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use(function(req, res, next) {
// 设置所有HTTP请求的超时时间
req.setTimeout(5000)
// 设置所有HTTP请求的服务器响应超时时间
res.setTimeout(5000)
next();
});
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
app.js文件中,通过app.use()方法重载引入的都是中间件。所有中间件都是针对HTTP的处理,你可以在中间件中进行数据解析、设置静态目录、或是做一些通用的处理。
2. 数据解析中间件
在Express引入的中间中,有几个用于数据解的,如:
app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser());
通过这些中间的处理,Express会将HTTP的请求中的参数和Cookie进行格式化,会将这些数据转换为对象形式。这样在其后的路由中,可以很容易的处理这些数据。
3. 设置静态目录
静态目录是在客户端可以不通过路由映射而直接访问的目录。如,在app.js中设置了public目录:
app.use(express.static(path.join(__dirname, 'public')));
public目录会被做为静态资源的根目录,这样在客户端我们就可以访问到public下的静态资源。
如,访问public/stylesheets/style.css样式文件,在客户端就可以像下面这样引用:
<link rel='stylesheet' href='/stylesheets/style.css' />
通过app.use()重载和express.static()方法,我们也可以设置其它的静态资源目录。
如,我们在Express的根目录下有一个存放上传文件的目录upload,我们要在客户端以静态资源的方式访问这个目录,可以像下面这样设置:
app.use(express.static(path.join(__dirname, 'upload')));
4. 通用处理
中间件还可以做一些通用的处理,在app.js中:
//捕获 404 状态并传递到错误处理中
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// 错误处理
// 开发环境下的错误处理
// 会输出堆栈信息
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// 生产环境下的错误处理
// 不会向用户泄漏堆栈错误
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
在这些中间件中,对HTTP错误404、50*等错误进行了处理,这样我们就可以统一处理所有应用异常。
中间件是针对HTTP请求的中间处理,在中间件中可以访问HTTP请求中的请求对象和响应对象,也可以通过next回调函数将所做处理传递到其后的HTTP路由处理或其它中间件中:
// 通过中间件向req或res中添加一些处理
app.use(function(req, res, next) {
// 向req中添加一个user对象
req.user = {name:'myName'};
// req.locals中添加一个site对象,在其后的路由处理中通过render渲染后的视图中都可以访问到这个对象
req.locals.site = {name:'IT笔录', domain:'niefengjun.cn'};
next();
});
// 访问上一个中间件中的数据
app.use(function(req, res, next) {
/**
* 中间件影响其后的中间件,我们可以在后面的中间件中访问请一个中间件的数据
* 中间件也会影响其后的路由,在路由处理函数中同样也可以访问它前面中间件的数据
*/
console.log(req.user)
next();
});
