Skip to content

Commit

Permalink
refactor: group parser (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
climba03003 authored Jul 11, 2021
1 parent 679a665 commit 42f951c
Showing 1 changed file with 50 additions and 49 deletions.
99 changes: 50 additions & 49 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Ajv } from 'ajv'
import { FastifyPluginAsync, FastifyRequest } from 'fastify'
import FastifyPlugin from 'fastify-plugin'
import { Fields, File, Files, IncomingForm, Options } from 'formidable'
import Formidable from 'formidable/Formidable'
import { IncomingMessage } from 'http'
const kIsMultipart = Symbol.for('[isMultipart]')

declare module 'fastify' {
Expand All @@ -19,6 +21,37 @@ export interface FastifyFormidableOptions {
formidable?: Options
}

function promisify (func: Function): (request: IncomingMessage) => Promise<{ fields: Fields, files: Files }> {
return async function (request: IncomingMessage): Promise<{ fields: Fields, files: Files }> {
return await new Promise(function (resolve, reject) {
func(request, function (err: any, fields: Fields, files: Files) {
if (err as true) reject(err)
resolve({ fields, files })
})
})
}
}

function buildRequestParser (formidable: Formidable): (request: FastifyRequest, options?: Pick<FastifyFormidableOptions, 'removeFilesFromBody'>) => Promise<{ body: Fields, files: Files }> {
const parse = promisify(formidable.parse.bind(formidable))
return async function (request: FastifyRequest, options?: Pick<FastifyFormidableOptions, 'removeFilesFromBody'>): Promise<{ body: Fields, files: Files }> {
const { fields, files } = await parse(request.raw)

const body = Object.assign({}, fields)
if (options?.removeFilesFromBody !== true) {
Object.keys(files).forEach(function (key) {
(body as any)[key] = Array.isArray(files[key])
? (files[key] as File[]).map(function (file) {
return file.path
})
: (files[key] as File).path
})
}

return { body, files }
}
}

const plugin: FastifyPluginAsync<FastifyFormidableOptions> = async function (fastify, options) {
const formidable = new IncomingForm(options.formidable)

Expand All @@ -35,47 +68,25 @@ const plugin: FastifyPluginAsync<FastifyFormidableOptions> = async function (fas
requestFormidable = new IncomingForm(decoratorOptions)
}

return await new Promise(function (resolve, reject) {
// skip if it is not multipart
if (!request[kIsMultipart]) return reject(new Error('Cannot handle non-multipart request'))
requestFormidable.parse(request.raw, function (err, fields, files) {
if (err as true) reject(err)
request.body = Object.assign({}, fields)
if (options.removeFilesFromBody !== true) {
Object.keys(files).forEach(function (key) {
(request.body as any)[key] = Array.isArray(files[key])
? (files[key] as File[]).map(function (file) {
return file.path
})
: (files[key] as File).path
})
}
request.files = files
resolve(request.body)
})
})
const parser = buildRequestParser(requestFormidable)
const { body, files } = await parser(request, { removeFilesFromBody: options.removeFilesFromBody })
request.body = body
request.files = files

return body
})

if (options.addContentTypeParser === true && options.addHooks === true) {
throw new Error('Cannot enable `addContentTypeParser` togather with `addHooks`')
}

if (options.addContentTypeParser === true) {
fastify.addContentTypeParser('multipart', function (request, _, done) {
fastify.addContentTypeParser('multipart', async function (request: FastifyRequest) {
request[kIsMultipart] = true
formidable.parse(request.raw, function (err, fields, files) {
if (err as true) done(err)
const body = Object.assign({}, fields)
Object.keys(files).forEach(function (key) {
(body as any)[key] = Array.isArray(files[key])
? (files[key] as File[]).map(function (file) {
return file.path
})
: (files[key] as File).path
})
request.files = files
done(null, body)
})
const parse = buildRequestParser(formidable)
const { body, files } = await parse(request)
request.files = files
return body
})
} else {
fastify.addContentTypeParser('multipart', function (request, _, done) {
Expand All @@ -85,23 +96,13 @@ const plugin: FastifyPluginAsync<FastifyFormidableOptions> = async function (fas
}

if (options.addHooks === true) {
fastify.addHook('preValidation', function (request, reply, done) {
fastify.addHook('preValidation', async function (request: FastifyRequest) {
// skip if it is not multipart
if (!request[kIsMultipart]) return done()

formidable.parse(request.raw, function (err, fields, files) {
if (err as true) done(err)
request.body = Object.assign({}, fields)
Object.keys(files).forEach(function (key) {
(request.body as any)[key] = Array.isArray(files[key])
? (files[key] as File[]).map(function (file) {
return file.path
})
: (files[key] as File).path
})
request.files = files
done()
})
if (!request[kIsMultipart]) return
const parse = buildRequestParser(formidable)
const { body, files } = await parse(request)
request.body = body
request.files = files
})
}

Expand Down

0 comments on commit 42f951c

Please sign in to comment.