本文介绍了定制中间件Express.js框架排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写定制中间件,以便在每次请求时将请求数据(如请求路径、响应代码、请求时间戳等)发送到远程服务器。我搞不清楚中间件的顺序。

我已经创建了2个中间件
A)PROCESS_REQUEST(M1)-->;当接收到请求时,该中间件只是将时间戳添加到请求对象以进行注册。
B)Process_Response(M2)-->;此中间件将所需数据发布到远程服务器

M1

function process_request(req, res, next) {
  req.requestTime = Date.now()/1000;
  next();
}

m2

function process_response(req, res, next) {
  const request_obj = {};
  request_obj.request_timestamp = req.requestTime;
  request_obj.response_timestamp = Date.now()/1000;
  request_obj.path = req.protocol + "://" + 
    req.get('host') + req.originalUrl;
  request_obj.response_code = res.statusCode;
  send_perf_request(request_obj); // sends remote https request not shown here
}

我可以在我的app.js中想到两个排序选项:订单1:

m1     
route 1   
route 2    
...
route n      
m2         
404 request handler middleware

订单2:

m1     
route 1   
route 2    
...
route n              
404 request handler middleware
m2

404请求处理中间件

app.use((req, res, next) => {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

order 1的问题是我无法捕获404个我想要捕获的请求。
作为404请求处理程序中间件的order 2的问题在于请求responseCode=404
我是node.js的新手,如果我的思考方式正确,我会感到困惑。

我的app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

const custom_middleware = require("custom_middleware");


var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(custom_middleware.process_request);  //*calling middleware


app.use('/', indexRouter);
app.use('/users', usersRouter);

//catch 404 and forward to error handler
// app.use(function(req, res, next) {
//   console.log("in 404 handler");
//   //next(createError(404, "this page doesn't exist;"));
//   next();
// });


// error handler
app.use(function(err, req, res, next) {
  // this is called only in case of errors  
  // set locals, only providing error in development
  console.log("in error handler");
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  console.log(res.statusCode);
  //res.render('error');
  next(err);
});

app.use(custom_middleware.process_exception); //*calling middleware

module.exports = app;

自定义中间件文件

function process_request(req, res, next) {
  // this middleware adds request timestamp
  console.log("in process request middleware");
  req.requestTime = Date.now()/1000;
  res.on("finish", function (){
        // this middleware collects performance data
        console.log("in process response middleware");
        const request_obj = {};
        request_obj.request_timestamp = req.requestTime;
        request_obj.response_timestamp = Date.now()/1000;
        request_obj.ip_address = ip.address();
        request_obj.path = req.protocol + "://" + 
        req.get('host') + req.originalUrl;
        request_obj.requester = null;
        request_obj.response_code = res.statusCode;
        console.log(request_obj.response_code);
        send_perf_request(request_obj);
    })
  next();
}

function process_exception(err, req, res, next) {
  // this middleware collects exception data
  console.log("in process exception middleware");
  const error_obj = {};
  error_obj.path = req.protocol + "://" + 
    req.hostname + req.originalUrl;
  error_obj.exception = "error occured";
  error_obj.traceback = err.stack;
  error_obj.user = null;
  error_obj.ip_address = ip.address();
  send_exception_request(error_obj);
  next();
}

我的路线/index.js

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

router.get('/', function(req, res, next) {
  throw new Error('this does not exist'); // error manually triggered
  res.status(500);
});

module.exports = router;

推荐答案

如评论中所述,抽象中间件以避免在每条路由上定义一组中间件。

要替换m1,请创建一个全局中间件,它是您在所有其他中间件之前定义的,它设置res.on("finish", function () {})事件处理程序在路由完成时执行某些操作。我非常肯定,如果您在任何地方执行res.status(),这是您将获得实际正确的res.statusCode的唯一事件。

然后将404错误处理程序逻辑移到主错误处理程序中,然后可以在记录和响应之前检查状态代码和所有有用的东西。您还可以使用req.xhr来确定如何响应。

此外,您还可以使用Catch-All获取路径404的app.get('*', function (req, res, next) {,然后发出错误处理程序处理的错误。

这里有一个将所有这些放在一起的示例:

const express = require('express')
const app = express()

// logger middleware
app.use((req, res, next) => {

  // set something
  req.requestTime = Date.now() / 1000;

  // gets fired after all routes have been handled
  res.on("finish", function () {

    //
    req.finishTime = Date.now() / 1000;

    // do something with req, res objects
    console.log('[in logger] originalUrl:', req.originalUrl)
    console.log('[in logger] status code:', res.statusCode)
  })

  next()
})

// apply routes
// ...

app.get('/', (req, res, next) => {
  try {
    // example: look for something, which is not found
    const mock = false
    if (!mock) {
      let err = new Error('Mock was not found!')
      err.status = 404
      throw err
    }

    res.send('Hello World!')
  } catch (err) {
    next(err)
  }
})

// app.get('/foo', ...

// not found route (catch all)
app.get('*', (req, res, next) => {
  let err = new Error('Page not found!')
  err.status = 404
  next(err)
})

// error handler (will catch everything even uncaught exceptions)
app.use((error, req, res, next) => {

  //
  res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate')
  res.header('Expires', '-1')
  res.header('Pragma', 'no-cache')

  // set status from error
  res.status(error.status || 500)

  if (req.xhr) {
    // is ajax call, send error as json
    res.json({
      error: error.name || 'Server error',
      status: error.status || 500,
      message: error.message || 'Internal server error'
    })
  } else {
    // render a view instead (would need to add a view engine)
    res.render('error/' + (error.status || 500), error)
  }
})

app.listen(3000, function () {
  console.log('App listening on port 3000!')
})

这篇关于定制中间件Express.js框架排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 07:12