It's an easy image (picture) download server, Express.js receives the request, gets an image from MongoDB GridFS, and responds with the file.
It's OK when request is valid (when the requested file exists).
The problem is that I cannot catch the MongoError
when the query failed (i.e. requested image does not exist).
import Grid from 'gridfs-stream'
const root = 'fs_images'
// This func returns the file stream
export function getReadStream (id) {
const gfs = Grid(mongoose.connection.db, mongoose.mongo)
const options = {
_id: id,
mode: 'r',
root: root
}
const readStream = gfs.createReadStream(options)
readStream.on('error', function (err) {
// throw here
// it performs the same without this on-error hook;
// if comment the `throw err`, nothing will happens
// but I want the caller knows the error
throw err
})
return readStream
}
And this is the router
router.get('/:fileId', function (req, res, next) {
const fileId = req.params.fileId
try {
const imgReadStream = image.getReadStream(fileId)
imgReadStream.pipe(res)
} catch (err) {
// nothing catched here
// instead, the process just crashed
console.log(err)
}
}
And I just cannot catch the err. When I try to request something that doesn't exist the MongoError
shows in the console, and the app crashes with errno
is 1
.
Head of console output:
/.../node_modules/mongodb/lib/utils.js:123
process.nextTick(function() { throw err; });
^
MongoError: file with id 123456123456123456123456 not opened for writing
at Function.MongoError.create (/.../node_modules/mongodb-core/lib/error.js:31:11)
This may be a bit different. If somewhere else throws an Error
it will be caught by my error-handler (app.use(function(err, req, res, next){ /* ... */})
), or at least by the default handler from Express.js
, and returns a 500
, without the process crashing.
In short, I want the app to know and catch this MongoError
so I can handle it manually (i.e. return a 404
response).
try
/catch
won't work because the error is happening in a different tick (asynchronously). Perhaps you could listen for the error in the router instead?
const imgReadStream = image.getReadStream(fileId)
imgReadStream.on('error', function(err) {
// Handle error
});
imgReadStream.pipe(res)