在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
样式文件,在客户端就可以像下面这样引用:
通过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:'itbilu.com'}; next(); }); // 访问上一个中间件中的数据 app.use(function(req, res, next) { /** * 中间件影响其后的中间件,我们可以在后面的中间件中访问请一个中间件的数据 * 中间件也会影响其后的路由,在路由处理函数中同样也可以访问它前面中间件的数据 */ console.log(req.user) next(); });