验证和序列化

Fastify 使用基于 schema 的方法, 虽然不是强制的,但是我们建议使用 JSON Schema 验证路由并序列化输出。在内部,Fastify 用高性能的方法编译 JSON。

验证

路由验证器在内部使用了 Ajv 这个包, 它是一个高性能的 JSON schema 验证器。 验证非常简单:只需要添加需要验证的字段即可。

  • body:验证请求体,必须是 POST 或者 PUT 请求。
  • querystring: 验证查询字符串。可以是一个完成的 JSON Schema 对象(符合 {type: "object", properties: {...}} 的格式)或者没有 typeproperties 属性,而只有查询字符串列表。(查看下面的例子)
  • params: 验证路由参数。
  • headers: 验证请求头。

Example:

const schema = {
  body: {
    type: 'object',
    properties: {
      someKey: { type: 'string' },
      someOtherKey: { type: 'number' }
    }
  },

  querystring: {
    name: { type: 'string' },
    excitement: { type: 'integer' }
  },

  params: {
    type: 'object',
    properties: {
      par1: { type: 'string' },
      par2: { type: 'number' }
    }
  },

  headers: {
    type: 'object',
    properties: {
      'x-foo': { type: 'string' }
    },
    required: ['x-foo']
  }
}

注意 Ajv 默认会尝试将值强制转换为 schema 类型关键字中指定的类型。

Schema Compiler

schemaCompiler 是一个指定 schema 编译器的方法。(用来验证 body, params, headers, querystring)。默认的 schemaCompiler 返回一个实现 ajv 接口的编译器。 Fastify 在内部使用它以达到快速验证。

如果你想更改默认的 ajv 实例,可以传入 ajv 配置项, 查看 Ajv documentation 了解更多。

const fastify = require('fastify')({
  ajv: {
    removeAdditional: true,
    useDefaults:      true,
    coerceTypes:      true
  }
})

或许你想直接更换验证的库,比如使用 Joi:

const Joi = require('joi')

fastify.post('/the/url', {
  schema: {
    body: Joi.object().keys({
      hello: Joi.string().required()
    }).required()
  },
  schemaCompiler: schema => data => Joi.validate(data, schema)
})

schemaCompiler 返回的函数的参数是一个含有如下属性的对象:

  • error: filled with an instance of Error or a string that describes the validation error
  • value: the coerced value that passed the validation

序列化

通常,我们通过 JSON 将数据发送给客户端, Fastify 提供了一个强大的工具: fast-json-stringify,如果在路由选项中传入了 output schema,fastify 就会使用它。 使用 output schema会根据你的有效载荷提高100-400%的吞吐量,还会防止敏感信息的意外泄露。

Example:

const schema = {
  response: {
    200: {
      type: 'object',
      properties: {
        value: { type: 'string' },
        otherValue: { type: 'boolean' }
      }
    }
  }
}

可以看到,response schema 是基于状态码的,如果想应用相同的 schema 给多个同级状态码, 可以使用 2xx

for example:

const schema = {
  response: {
    '2xx': {
      type: 'object',
      properties: {
        value: { type: 'string' },
        otherValue: { type: 'boolean' }
      }
    },
    201: {
      type: 'object',
      properties: {
        value: { type: 'string' }
      }
    }
  }
}

如果你想使用自定义的序列化器,比如 msgpack5 或者 protobuf,你可以使用 .serializer()

Resources

results matching ""

    No results matching ""