【问题标题】:Use ajv-formats with fastify通过 fastify 使用 ajv 格式
【发布时间】:2021-04-19 21:34:59
【问题描述】:

在路由上使用 fastify 和 schema 对象,我正在尝试添加更多验证。 fastify 使用(用于身体验证)ajv。按照 fastify 文档和代码,添加一个 ajv 插件我需要这样做:

const fastify = require('fastify')({
  ajv: {
    plugins: [
      require('ajv-merge-patch')
    ]
  }
})

文档是here

问题是当我们尝试添加这个插件时,我收到这个错误:Cannot read property 'code' of undefined" 这是堆栈错误:

TypeError: Cannot read property 'code' of undefined
  at addFormats (/test-api/node_modules/ajv-formats/dist/index.js:30:26)
  at Array.formatsPlugin (/test-api/node_modules/ajv-formats/dist/index.js:15:5)
  at ValidatorCompiler (/test-api/node_modules/fastify/lib/schema-compilers.js:42:16)
  at buildCompilerFromPool (/test-api/node_modules/fastify/lib/schema-compilers.js:20:22)
  at Boot.<anonymous> (/test-api/node_modules/fastify/lib/route.js:269:39)
  at Object.onceWrapper (events.js:421:28)
  at Boot.emit (events.js:327:22)
  at /test-api/node_modules/avvio/boot.js:153:12
  at /test-api/node_modules/avvio/plugin.js:269:7
  at done (/test-api/node_modules/avvio/plugin.js:201:5)"

这段代码出现了这个错误:

const server: FastifyInstance<Server, IncomingMessage, ServerResponse > = fastify({
  ignoreTrailingSlash: true,
  logger: true,
  ajv: {
    plugins: [
      require('ajv-formats')
    ]
  }
})

async function run (): Promise<string> {
  server.addHook('onRoute', (options) => console.log(options))

  await server.register(helmet)
  await server.register(cors)

  return server.listen(3000, 'localhost')
}

有人可以在 fastify 中使用 ajv-formats 吗?或者你能帮帮我吗?

提前致谢!

【问题讨论】:

  • 你运行的是什么版本?
  • 我现在正在运行 fastify@3.9.2
  • 您能添加一些架构吗?因为我有一个使用此插件的工作示例,但无法复制您的错误
  • 错误没有路由也没有,例如,使用这段代码,我得到错误:`` async function run (): Promise { server.addHook('onRoute', (options) => console.log(options)) await server.register(helmet) await server.register(cors) return server.listen(3000, 'localhost') } ``` 使用这段代码,我得到了错误

标签: javascript node.js ajv fastify


【解决方案1】:

这是一个您可以自定义的工作示例:

    "ajv-merge-patch": "^4.1.0",
    "fastify": "^3.9.2",
    "fastify-cors": "^5.1.0",
    "fastify-helmet": "^5.1.0",
const fastify = require('fastify')({
  ignoreTrailingSlash: true,
  logger: true,
  ajv: {
    plugins: [
      require('ajv-merge-patch')
    ]
  }
})

fastify.register(require('fastify-cors'))
fastify.register(require('fastify-helmet'))

fastify.addSchema({
  $id: 'mySchema.json#',
  type: 'object',
  properties: {
    foo: { type: 'string' },
    bar: { $ref: '#' }
  },
  additionalProperties: false
})

fastify.post('/', {
  schema: {
    body: {
      $id: 'mySchemaExtended.json#',
      $merge: {
        source: { $ref: 'mySchema.json#' },
        with: {
          properties: {
            baz: { type: 'number' }
          }
        }
      }
    }
  }
}, (req, reply) => { reply.send({ echo: req.body }) })

fastify.inject({
  method: 'POST',
  url: '/',
  payload: {
    foo: 'foo',
    bar: {
      foo: 'foo2',
      evit: 'this'
    },
    baz: 42,
    evict: 'this too'
  }
}, (err, res) => {
  console.log(res.json());
  // shows
  // { echo: { foo: 'foo', bar: { foo: 'foo2' }, baz: 42 } }
})

【讨论】:

  • 如何使用fastify-cli将ajv选项添加为插件。
【解决方案2】:

解决了!似乎我的问题来自我的代码的另一部分。创建一个新的项目form 0并使用格式似乎效果很好,我不需要安装ajv-format,因为fastify有选项格式可以在你的模式中使用!

谢谢大家!

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,并决定调查原因。问题是ajv-formats 依赖于ajv 8.x.x 而fastify 依赖于ajv 6.x.x。这两者是不兼容的。

    有多种解决方案

    • 等待fastify支持ajv 8.x.x。这是work in progress
    • 复制所需的验证器,将它们捆绑在自定义的ajv-Plugin 中,并将其添加到fastify。插件是将ajv 实例作为第一个参数1 的函数。您可以在那里添加格式,查看ajv-formats 以了解它是如何完成的。
    • 使用旧版本的ajv-formats。遗憾的是,支持ajv 6.x.x 的最后一个ajv-formats 版本是0.2.0(查看package.json)。 IMO 不是一个好的选择

    1插件也可以采用选项,但没有 Typescript 类型可以将此类插件添加到 fastify。

    【讨论】:

      【解决方案4】:

      遇到同样的问题,所以我决定使用 Ajv 版本 8.x.x 并在其中使用其他插件。

      import Ajv from "ajv";
      import ajvFormats from "ajv-formats";
      import ajvErrors from "ajv-errors";
      
      const ajv = new Ajv({
        removeAdditional: true,
        useDefaults: true,
        coerceTypes: true,
        allErrors: true
      });
      
      ajvFormats(ajv);
      ajvErrors(ajv, { singleError: true });
      
      export { ajv };
      

      之后,我刚刚按照the docs 中的建议,在 Fastify 服务器中使用了这个 Ajv 实例进行架构编译。

      fastify.setValidatorCompiler((opt) => ajv.compile(opt.schema));
      

      它没有任何问题。使用常规 JavaScript 也可以获得相同的结果。

      【讨论】:

        猜你喜欢
        • 2018-06-05
        • 2018-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-02
        • 2021-05-27
        • 2023-02-01
        • 2017-04-29
        相关资源
        最近更新 更多