向 Fastify 发出 POST 请求时,未解析 JSON 进行验证

Mik*_*ike 3 validation routes node.js ajv fastify

在我的路线中,我有以下内容:

const reservationSchema = {
  body: {
    type: 'object',
    required: ['in', 'out', 'guests', 'language', 'roomsSelected'],
    properties: {
      language: {
        type: 'string',
      },
      // ... several other property validations here
    }
  }
};

fastify.post(
  '/api/reservations/:slug',
  { schema: reservationSchema },
  reservationsController.addReservation
);

Run Code Online (Sandbox Code Playgroud)

我从 React 发送 POST 请求,如下所示:

const response = await fetch(process.env.REACT_APP_API_HOSTNAME + '/api/reservations/' + property.slug, {
  method: 'POST',
  body: JSON.stringify(requestBody)
});
Run Code Online (Sandbox Code Playgroud)

当我查看请求时,我可以看到它正在正确发送 JSON:

截屏

但是我收到以下回复:

const reservationSchema = {
  body: {
    type: 'object',
    required: ['in', 'out', 'guests', 'language', 'roomsSelected'],
    properties: {
      language: {
        type: 'string',
      },
      // ... several other property validations here
    }
  }
};

fastify.post(
  '/api/reservations/:slug',
  { schema: reservationSchema },
  reservationsController.addReservation
);

Run Code Online (Sandbox Code Playgroud)

我是否缺少一些东西来自动将 POST 正文解析为 Fastify 中的对象,以便我可以使用验证模式对其进行验证?即使在我的reservationsController.addReservation()函数中,我也需要手动执行JSON.parse()on req.body。

Mik*_*ike 8

来自fetch()文档:

请求和响应(以及扩展的 fetch() 函数)都将尝试智能地确定内容类型。如果字典中没有设置,请求还将自动设置 Content-Type 标头。

但是,(至少在 Chrome 中),当您发送 JSON 字符串时,它不会智能地确定该字符串是 JSON,而是将Content-Type标头作为text/plain;charset=UTF-8. 由于服务器收到此Content-Type标头,因此它假定您正在发送计划文本字符串,因此不会将其解析为 JSON。

为了使服务器自动将正文解析为 JSON,您需要确保将Content-Type标头设置为application/json. 像这样:

const response = await fetch(process.env.REACT_APP_API_HOSTNAME + '/api/reservations/' + property.slug, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(requestBody)
});
Run Code Online (Sandbox Code Playgroud)