Skip to content

Commit

Permalink
Wait for all files to be completed before calling the handler. (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
mcollina committed Jul 5, 2018
1 parent 62194f2 commit 547527d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 3 deletions.
37 changes: 35 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const fp = require('fastify-plugin')
const Busboy = require('busboy')
const kMultipart = Symbol('multipart')
const eos = require('end-of-stream')

function setMultipart (req, done) {
// nothing to do, it will be done by the Request.multipart object
Expand Down Expand Up @@ -46,15 +47,27 @@ function fastifyMultipart (fastify, options, done) {
busboyOptions[keys[i]] = options[keys[i]]
}
const stream = new Busboy(busboyOptions)
var completed = false
var files = 0
var count = 0
var callDoneOnNextEos = false

req.on('error', function (err) {
stream.destroy()
done(err)
if (!completed) {
completed = true
done(err)
}
})

stream.on('finish', function () {
log.debug('finished multipart parsing')
done()
if (!completed && count === files) {
completed = true
setImmediate(done)
} else {
callDoneOnNextEos = true
}
})

stream.on('file', wrap)
Expand All @@ -63,9 +76,29 @@ function fastifyMultipart (fastify, options, done) {

function wrap (field, file, filename, encoding, mimetype) {
log.debug({ field, filename, encoding, mimetype }, 'parsing part')
files++
eos(file, waitForFiles)
handler(field, file, filename, encoding, mimetype)
}

function waitForFiles (err) {
if (err) {
completed = true
done(err)
return
}

if (completed) {
return
}

++count
if (callDoneOnNextEos && count === files) {
completed = true
done()
}
}

return stream
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "index.js",
"dependencies": {
"busboy": "^0.2.14",
"end-of-stream": "^1.4.1",
"fastify-plugin": "^1.0.0"
},
"devDependencies": {
Expand Down
58 changes: 57 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict'

const os = require('os')
const test = require('tap').test
const FormData = require('form-data')
const Fastify = require('fastify')
Expand Down Expand Up @@ -80,6 +80,62 @@ test('should parse forms', function (t) {
})
})

test('should call finished when both files are pumped', function (t) {
t.plan(8)

const fastify = Fastify()
t.tearDown(fastify.close.bind(fastify))

fastify.register(multipart)

fastify.post('/', function (req, reply) {
var fileCount = 0
t.ok(req.isMultipart())

req.multipart(handler, function (err) {
t.error(err)
t.equal(fileCount, 2)
reply.code(200).send()
})

function handler (field, file, filename, encoding, mimetype) {
const saveTo = path.join(os.tmpdir(), path.basename(filename))
pump(file, fs.createWriteStream(saveTo), function (err) {
t.error(err)
fileCount++
})
}
})

fastify.listen(0, function () {
// request
var form = new FormData()
var opts = {
protocol: 'http:',
hostname: 'localhost',
port: fastify.server.address().port,
path: '/',
headers: form.getHeaders(),
method: 'POST'
}

var req = http.request(opts, (res) => {
t.equal(res.statusCode, 200)
res.resume()
res.on('end', () => {
t.pass('res ended successfully')
})
})
form.append('upload', fs.createReadStream(filePath))
form.append('upload2', fs.createReadStream(filePath))
form.append('hello', 'world')
form.append('willbe', 'dropped')
pump(form, req, function (err) {
t.error(err, 'client pump: no err')
})
})
})

test('should error if it is not multipart', function (t) {
t.plan(4)

Expand Down

0 comments on commit 547527d

Please sign in to comment.