Fastify同类型钩子执行顺序及全局与路由钩子优先级保障
Fastify钩子执行顺序与动态文件上传限制实现
一、同类型钩子的执行顺序
Fastify中同类型钩子的执行规则清晰明确:
- 全局注册的钩子(通过
fastify.addHook())优先于路由级别声明的同类型钩子执行 - 同级别(全局/路由)的多个同类型钩子,严格按照注册/声明的先后顺序依次执行
但你的代码存在两个核心问题,直接按当前写法无法实现需求:
- 路由中
preHandler: upload.array(files, request.body.room.maxFiles)会直接报错——路由声明阶段request对象尚未创建,无法访问request.body.room - fastify-multer的文件解析逻辑运行在
preParsing阶段,而你定义的全局preHandler钩子在preParsing之后才执行,意味着文件上传完成后才会获取room配置,根本无法提前限制文件数量
二、正确实现方案
要实现“根据room配置动态限制上传文件数”的需求,需要调整钩子执行时机,在文件解析前拿到room配置,再动态设置multer规则:
1. 提前获取room配置
在onRequest钩子中获取roomID(建议从URL参数、请求头这类无需解析就能拿到的位置获取,避免依赖未解析的表单数据),并将配置挂载到request对象上:
import fastify from 'fastify' import multer from 'fastify-multer' const server = fastify() // 全局钩子:提前获取room配置并挂载 server.addHook('onRequest', async (request, reply) => { // 示例:从URL参数获取roomID const roomID = request.query.roomID if (!roomID) { await reply.code(400).send('RoomID is required') return } const roomOptions = await getRoomOptions(roomID) if (!roomOptions) { await reply.code(404).send('Room not found') return } request.roomOptions = roomOptions })
2. 动态配置multer上传规则
在路由的preParsing钩子中,根据已挂载的request.roomOptions动态生成multer实例,确保文件解析前就应用上传限制:
server.register(multer.contentParser) server.post('/post', { preParsing: async (request, reply) => { // 根据room配置创建multer实例 const upload = multer({ limits: { files: request.roomOptions.maxFiles } }) // 执行multer的解析逻辑 await new Promise((resolve, reject) => { upload.array('files')(request.raw, reply.raw, (err) => { if (err) reject(err) else resolve() }) }) } }, async (request, reply) => { // 处理上传完成后的逻辑 return { message: 'Files uploaded successfully', uploadedFiles: request.files.length, maxAllowedFiles: request.roomOptions.maxFiles } })
核心逻辑说明
- 利用
onRequest钩子的执行优先级,确保在所有解析逻辑前拿到room配置 - 在
preParsing阶段动态生成multer规则,保证文件上传时直接应用room的限制 - 全局钩子先于路由钩子执行的特性,确保
request.roomOptions在multer配置时已存在
内容的提问来源于stack exchange,提问作者Juribiyan
相关产品推荐
相关产品推荐

