Skip to content

Commit

Permalink
lib: work around node.js bug
Browse files Browse the repository at this point in the history
  • Loading branch information
LinusU committed Sep 19, 2015
1 parent 166db35 commit d96af4a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 26 deletions.
10 changes: 9 additions & 1 deletion lib/make-middleware.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
var is = require('type-is')
var Busboy = require('busboy')
var extend = require('xtend')
var onFinished = require('on-finished')
var appendField = require('append-field')

var Counter = require('./counter')
var makeError = require('./make-error')
var FileAppender = require('./file-appender')
var removeUploadedFiles = require('./remove-uploaded-files')

function drainStream (stream) {
stream.on('readable', stream.read.bind(stream))
}

function makeMiddleware (setup) {
return function multerMiddleware (req, res, next) {
if (!is(req, ['multipart'])) return next()
Expand Down Expand Up @@ -38,9 +43,12 @@ function makeMiddleware (setup) {
function done (err) {
if (isDone) return
isDone = true

req.unpipe(busboy)
drainStream(req)
busboy.removeAllListeners()
next(err)

onFinished(req, function () { next(err) })
}

function indicateDone () {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"concat-stream": "^1.5.0",
"mkdirp": "^0.5.1",
"object-assign": "^3.0.0",
"on-finished": "^2.3.0",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
},
Expand Down
8 changes: 7 additions & 1 deletion test/_util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var fs = require('fs')
var path = require('path')
var stream = require('stream')
var onFinished = require('on-finished')

exports.file = function file (name) {
return fs.createReadStream(path.join(__dirname, 'files', name))
Expand All @@ -16,14 +17,19 @@ exports.submitForm = function submitForm (multer, form, cb) {

var req = new stream.PassThrough()

req.complete = false
form.once('end', function () {
req.complete = true
})

form.pipe(req)
req.headers = {
'content-type': 'multipart/form-data; boundary=' + form.getBoundary(),
'content-length': length
}

multer(req, null, function (err) {
cb(err, req)
onFinished(req, function () { cb(err, req) })
})
})
}
90 changes: 66 additions & 24 deletions test/express-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,102 @@ var util = require('./_util')
var express = require('express')
var FormData = require('form-data')
var concat = require('concat-stream')
var onFinished = require('on-finished')

var port = 34279

describe('Express Integration', function () {
var app

before(function (done) {
app = express()
app.listen(port, done)
})

function submitForm (form, path, cb) {
var req = form.submit('http://localhost:' + port + path)

req.on('error', cb)
req.on('response', function (res) {
res.on('error', cb)
res.pipe(concat({ encoding: 'buffer' }, function (body) {
onFinished(req, function () { cb(null, res, body) })
}))
})
}

it('should work with express error handling', function (done) {
var app = express()
var limits = { fileSize: 200 }
var upload = multer({ limits: limits })
var router = new express.Router()
var form = new FormData()

var routeCalled = 0
var errorCalled = 0

form.append('avatar', util.file('large.jpg'))

app.post('/profile', upload.single('avatar'), function (req, res, next) {
router.post('/profile', upload.single('avatar'), function (req, res, next) {
routeCalled++
res.status(200).end('SUCCESS')
})

app.use(function (err, req, res, next) {
router.use(function (err, req, res, next) {
assert.equal(err.code, 'LIMIT_FILE_SIZE')

errorCalled++
res.status(500).end('ERROR')
})

app.listen(port, function () {
var res, body
var req = form.submit('http://localhost:' + port + '/profile')
var pending = 2
app.use('/t1', router)
submitForm(form, '/t1/profile', function (err, res, body) {
assert.ifError(err)

assert.equal(routeCalled, 0)
assert.equal(errorCalled, 1)
assert.equal(body.toString(), 'ERROR')
assert.equal(res.statusCode, 500)

done()
})
})

it('should work when receiving error from fileFilter', function (done) {
function fileFilter (req, file, cb) {
cb(new Error('TEST'))
}

var upload = multer({ fileFilter: fileFilter })
var router = new express.Router()
var form = new FormData()

var routeCalled = 0
var errorCalled = 0

form.append('avatar', util.file('large.jpg'))

function validate () {
assert.equal(routeCalled, 0)
assert.equal(errorCalled, 1)
assert.equal(body.toString(), 'ERROR')
assert.equal(res.statusCode, 500)
router.post('/profile', upload.single('avatar'), function (req, res, next) {
routeCalled++
res.status(200).end('SUCCESS')
})

done()
}
router.use(function (err, req, res, next) {
assert.equal(err.message, 'TEST')

req.on('response', function (_res) {
res = _res
errorCalled++
res.status(500).end('ERROR')
})

res.pipe(concat({ encoding: 'buffer' }, function (_body) {
body = _body
app.use('/t2', router)
submitForm(form, '/t2/profile', function (err, res, body) {
assert.ifError(err)

if (--pending === 0) validate()
}))
})
assert.equal(routeCalled, 0)
assert.equal(errorCalled, 1)
assert.equal(body.toString(), 'ERROR')
assert.equal(res.statusCode, 500)

req.on('finish', function () {
if (--pending === 0) validate()
})
done()
})
})
})

0 comments on commit d96af4a

Please sign in to comment.