简体   繁体   English

如何按路由将参数传递给通用Express中间件功能?

[英]How can I pass parameters to a generic Express middleware function on a per-route basis?

I've written a generic validation function that takes an object as the first parameter with a property required (amongst others) that is an array of strings. 我编写了一个通用的验证函数,该函数将一个对象作为第一个参数,并带有一个required的属性(其中包括字符串数组)。 It is used to test incoming front end data against any keys found in required . 它用于根据required找到的任何键测试传入的前端数据。 Here's a mockup of how it looks - using underscore to check isEmpty : 这是外观的模型-使用下划线检查isEmpty

validator.js 验证器

function validateRequest(options, req, done) {
  const { body } = req;
  const { required } = options;
  const errors = {};

  if (required && required.length) {
    required.forEach(key => {
      const value = `${body[key]}`;

      if (_.isEmpty(value)) {
        errors[key] = 'This field is required';
      }
    });
  }

  if (_.isEmpty(errors)) done({ success: true });
  else done({ success: false, errors });
}

And I currently use it as such: 我目前正这样使用它:

routes/auth.js 路由/auth.js

router.post('/login', (req, res, next) => {
  validator.validateRequest({
    required: ['identifier', 'password']
  }, req, result => {
    if (!result.success) return res.status(400).send(result);
    next();
  });
}, auth.login);

I'd like to be able to use it in a cleaner fashion, something more like: 我希望能够以更清洁的方式使用它,例如:

router.post('/login', validator.validateRequest({
  required: ['identifier', 'password']
}), auth.login);

I'd rather not use app.use because it involves me having to worry about always positioning it in the proper hierarchy of the route files and is not scalable in the sense I need it to be. 我宁愿不使用app.use因为它涉及到我必须担心始终将其放置在路由文件的正确层次结构中,并且在我需要的情况下无法伸缩。 I also have other parameters being passed as options , validating input as numeric, correct zip codes, etc. so the function above is much more in-depth than the example. 我还将其他参数作为options传递,将输入验证为数字,正确的邮政编码等,因此上面的功能比示例更深入。 Is there a way for me to use something like this on a route-by-route basis? 有没有办法让我逐条路线使用类似的方法? There's gotta be a way for my middleware functions to intercept (req, res, next) without having to write it out each time.. right? 我的中间件函数必须有一种方法来拦截(req, res, next)而不必每次都写出来。

The answer was to use a higher order function returning a function that takes (req, res, next) as parameters like this: 答案是使用一个高阶函数返回一个将(req, res, next)作为参数的函数,如下所示:

validator.js 验证器

function validateRequest(options) {
  return (req, res, next) => {
    const { body } = req;
    const { required } = options;
    const errors = {};

    if (required && required.length) {
      required.forEach(key => {
        const value = `${body[key]}`;

        if (_.isEmpty(value)) {
          errors[key] = 'This field is required';
        }
      });
    }

    if (!_.isEmpty(errors)) {
      res.send({ success: false, errors });
    } else {
      next();
    }
  }
}

then it can be used like so: 然后可以这样使用:

routes/auth.js 路由/auth.js

router.post('/login', validateRequest({
  required: ['identifier', 'password']
}), auth.login);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM