Express Validator 运行服务器端验证后出现 Ajax 400 错误

Ajax 400 error after Express Validator runs server-side validation

提问人:Andrew Buccellato 提问时间:8/24/2023 最后编辑:jonrsharpeAndrew Buccellato 更新时间:9/1/2023 访问量:38

问:

我正在尝试修复一个表单处理程序,该处理程序在中间件验证后总是抛出 400 错误。

中间件验证如下所示:

const contactValidate = [
  check('name')
    .exists()
    .trim()
    .escape()
    .not()
    .isEmpty()
    .withMessage('Name can not be empty!')
    .bail()
    .isLength({min: 2})
    .withMessage('Minimum 2 characters required!')
    .bail()
    .isAlpha('en-US', {ignore: ' '})
    .withMessage('Name can only have letters and spaces')
    .bail(),
  check('phone')
    .trim()
    .escape()
    .not()
    .isEmpty()
    .withMessage('Phone can not be empty!')
    .bail()
    .isMobilePhone()
    .withMessage('Must be a phone number.')
    .bail(),
  check('email')
    .trim()
    .normalizeEmail()
    .not()
    .isEmpty()
    .withMessage('Invalid email address!')
    .bail(),
  check('note')
    .exists()
    .trim()
    .escape()
    .not()
    .isEmpty()
    .withMessage('Message can not be empty!')
    .bail(),
  check('botCheck')
    .isIn(["on"])
    .withMessage("Bot Check Failed")
    .bail(),
  function (req, res, next) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    next();
  },
];

它应该将错误传递给这个 ajax 调用:

const form = document.getElementById('contact-form');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const formData = new FormData(form);

  fetch('/contact/', {
      method: 'POST',
      body: formData,
      mode: 'cors',
      contentType: "application/json; charset=utf-8"
    })
    .then((response) => {
      response.json();
    })
    .then((response) => {
      // handle errors
      if (response.errors) {
        response.errors.forEach(({ msg }) => {
          document.getElementById('status').innerHTML += `<p class="note note-danger">${msg}</p>`
        });
        return;
      }
      // If mail was sent successfully, reset all elements with attribute 'name'
      const values = document.querySelectorAll('[name]');
      values.forEach( value => {
        value.textContent = '';
      });

      document.getElementById('status').innerHTML = `<p class="note note-success">${response.msg}</p>`;
    })
    .catch((err) => {
      document.getElementById('status').innerHTML += `<p class="note note-danger">${err}</p>`
    })
    .finally(()=> {
      setTimeout(()=> {
        document.getElementById('status').innerHTML = '';
      }, 2000)
    })
});

表单的开头具有正确的 HTMl 元素:<form id="contact-form" class="needs-validation" novalidate enctype="multipart/form-data">

我无法让它通过 400 错误,上面写着“TypeError:无法读取未定义的属性(读取'错误')”。我不确定是我在express-validator中的服务器端验证还是AJAX调用不正确。

node.js ajax express-validator

评论

0赞 jonrsharpe 8/24/2023
为什么要使用显式JSON内容类型发送表单数据?
0赞 Andrew Buccellato 8/24/2023
我发现这通常是更快地处理错误的最佳方法,而且过去对我来说效果很好。它的发送方式有问题吗?
0赞 jonrsharpe 8/24/2023
表单数据和 JSON 根本不是相同的格式,但这与您的问题无关 - 这与服务器是否或如何验证请求无关,甚至与它如何响应无关,想想为什么会是你试图访问它的地方。responseundefinederrors
0赞 Andrew Buccellato 8/24/2023
好的,所以我可以看到有效负载有正确的字段。所以这意味着错误在我的验证器中
0赞 jonrsharpe 8/24/2023
这在理论上是没有意义的。我们不能排除验证器中的错误,但这不会导致您询问的特定错误。在代码中穿线 - promise/always-return

答:

0赞 Andrew Buccellato 9/1/2023 #1

好的,回头看后我意识到是中间件,问题的第 1 步,然后我使用的 Ajax 句柄格式不正确,无法处理响应。

正确的中间件应该是:


module.exports = [
body("name")
  .trim()
  .notEmpty().withMessage('Name is required.')
  .isAlpha('en-US', {ignore: '\s'}).withMessage('Name can only have letters.')
  .bail(),

body("email")
  .trim()
  .notEmpty().withMessage('Email is required.')
  .isEmail().withMessage('Invalid email address.')
  .bail(),

body("phone")
  .trim()
  .notEmpty().withMessage('Phone number is required.')
  .isMobilePhone('en-US').withMessage("Please make sure it is a valid phone number")
  .bail(),

body("note")
  .trim()
  .notEmpty().withMessage('Message is required.')
  .bail(),

body("botCheck").isIn(["on"]).withMessage("Bot Check Failed"),


  function (req, res, next) {
    const errors = validationResult(req);
    console.log("Validation Result:", errors); 
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
       
    }
    next();
  },
];

然后,处理该响应的 AJAX 应为:

const form = document.getElementById('contact-form');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const formData = new FormData(form);
  for (var pair of formData.entries()) {
      console.log(pair[0]+ ', ' + pair[1]); 
  }
  console.log(formData);  // Log form data

  fetch('/contact', {
    method: 'POST',
    body: formData,
    mode: 'cors'
  })
  .then((response) => {
    return response.json();  // Otherwise, proceed as usual
  })
  .then((response) => {
    // handle errors
    if (response.errors) {
      response.errors.forEach(({ msg }) => {
        document.getElementById('status').innerHTML += `<p class="note note-danger">${msg}</p>`;
      });
      return;
    }
    // If mail was sent successfully, reset all elements with attribute 'name'
    const values = document.querySelectorAll('[name]');
    values.forEach(value => {
      value.textContent = '';
    });
    document.getElementById('status').innerHTML = `<p class="note note-success">${response.msg}</p>`;
    // Clear the form
    form.reset();
  })
  .catch((err) => {
    document.getElementById('status').innerHTML += `<p class="note note-danger">${err}</p>`;
  })
  .finally(() => {
    setTimeout(() => {
      document.getElementById('status').innerHTML = '';
    }, 2000);
  });
});

我现在意识到 400 错误是由于格式错误的 express-validator 代码造成的,我只需要在 Ajax 中处理 formData,它运行良好。

感谢您的帮助。