8

我正在构建一个快速应用程序,我想知道我能用中间件获得多少。粗略地说,我想用中间件完成以下工作。

完毕:

  • 将 requestId 添加到所有路由
  • 验证请求
  • 检查用户是否有权访问给定资源(身份验证除外)

尚未完成:

  • A)验证给定路由的参数
  • B)如果中间件因路由而异,则以合理的方式组织中间件,并且每个路由例行调用 3 个中间件

我在一个单独的文件中定义了我的中间件,并将其导入 app.js,如下所示:

var middleware = require('./middleware');
var requestId = middleware.requestId;
var authenticate = middleware.authenticate;

要将其应用于所有路由,我将其添加到 express 配置中:

var app = express.createServer();
app.configure(function () {
  app.use(express.logger());
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(requestId); // add requestId to all incoming requests
});

对于路线细节,我将其添加为 app.get 参数:

var routes = require('./v1/routes');
app.get("/v1/foo", routes.foo);
app.get("/v1/bar", authenticate, routes.bar);

问题A

我很想拥有可以用来检查参数的中间件

validate('x','y','z')

并像这样对给定的路线使用它:

app.get("/v1/bar", authenticate, validate('x','y','z'), routes.bar);

有没有好的方法来做到这一点?或者我应该只是在路由定义文件中基于每个路由进行验证?

问题 B

有没有更好的方法来组织和使用我应该考虑的中间件?

更新

我正在寻找一种方法来验证路由之间变化很大的参数。下面显然不起作用-我不能将参数传递给中间件-但是有没有办法可以定义中间件来执行此操作并按照我上面所说的那样调用它?

var validateParams = function (req, res, params, callback) {
  // Make sure the required parameters are in the request
  console.log('checking for params '+params);
  for (var i = 0; i < params.length; i++) {
    var param = params[i];
    if(!(param in req.query)){
      logger.info('cannot find param ['+param+'] in req: '+JSON.stringify(req.query));
      res.writeHead(400, {
        "Content-Type": "application/json"
      });
      var out = {
        "err": "request missing required parameters"
      };
      res.end(JSON.stringify(out));
      return;      
    }
  }
  callback();
}
4

3 回答 3

2

Problem A

app.get("/v1/bar", authenticate, validate, routes.bar);

function validate(req,res,next){

//Get all parameters here by req.params and req.body.parameter
//validate them and return.
if(validation_true)
next()
}

Problem B

You can use middleware in a way that you don't always need to call authenticate and validate they are called automatically. But that can lead to a mess, for ex. Your middleware then would run on every call, so for SIGNUP/REGISTER there is no point running authenticate.

With validate, sometimes you would need to validate email, sometimes phone no. so both cannot go along.

So using them separate on every call seems the BEST way to me.

于 2012-09-23T03:00:53.447 回答
2

您还可以使用高阶函数(返回函数的函数)。从而传递一组端点特定参数来检查。

module.export = Class RequestValidator {
  static validate(params) {
    return function(req, res, next){
      for(const param of params) {
       validateYourParams here...
       if (validation fails) {
         return next(new Error());
       }
      }
      next();
    }
  }
}

在您的 routeDefinition 中,您现在可以调用验证中间件并将特定于路由的参数传递给它。

const RequestValidator = require('your-validation-middleware');
const controller = require('your-controller');

app.post('/path')
   .RequestValidator.validate(
   [{
    name: 'paramName',
    type: 'boolean'
   },
   {
    name: 'paramName2',
    type: 'string'
   }
   ])
   .Controller.handleRequest;
于 2017-01-14T15:49:37.700 回答
2

您可以使用express-validation来验证请求的正文、查询、参数、标头和 cookie。如果任何配置的验证规则失败,它会以错误响应。

var validate = require('express-validation'),
    Joi = require('joi');

app.post('/login', validate({
  body: {
    email: Joi.string().email().required(),
    password: Joi.string().regex(/[a-zA-Z0-9]{3,30}/).required()
  }
}), function(req, res){
    res.json(200);
});

这将检查电子邮件和密码正文参数是否与验证规则匹配。

如果验证失败,它将响应以下错误。

{
  "status": 400,
  "statusText": "Bad Request",
  "errors": [
    {
      "field": "password",
      "location": "body",
      "messages": [
        "the value of password is not allowed to be empty",
        "the value of password must match the regular expression /[a-zA-Z0-9]{3,30}/"
      ],
      "types": [ "any.empty", "string.regex.base" ]
    }
  ]
}

您还可以查看我的 repo express-mongoose-es6-rest-api以获得完整的集成。

于 2015-09-24T12:13:05.990 回答