diff --git a/README.md b/README.md index acac8e8c..fcc68505 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Note the minimum required version of Node.js is 10. - [db.fetch(docnames, [params], [callback])](#dbfetchdocnames-params-callback) - [db.fetchRevs(docnames, [params], [callback])](#dbfetchrevsdocnames-params-callback) - [db.createIndex(indexDef, [callback])](#dbcreateindexindexdef-callback) - - [db.changesReader...](#reading-changes-feed) + - [db.changesReader...](##reading-changes-feed) - [Partitioned database functions](#partition-functions) - [db.partitionInfo(partitionKey, [callback])](#dbpartitioninfopartitionkey-callback)) - [db.partitionedList(partitionKey, [params], [callback])](#dbpartitionedlistpartitionkey-params-callback) @@ -1031,7 +1031,9 @@ alice.attachment.get('rabbit', 'rabbit.png').then((body) => { ```js const fs = require('fs'); -alice.attachment.getAsStream('rabbit', 'rabbit.png').pipe(fs.createWriteStream('rabbit.png')); +alice.attachment.getAsStream('rabbit', 'rabbit.png') + .on('error', (e) => console.error(e)) + .pipe(fs.createWriteStream('rabbit.png')); ``` ### db.attachment.destroy(docname, attname, [params], [callback]) diff --git a/lib/nano.js b/lib/nano.js index cf6773ae..6f914f35 100644 --- a/lib/nano.js +++ b/lib/nano.js @@ -14,6 +14,7 @@ const { URL } = require('url') const assert = require('assert') const querystring = require('qs') const axios = require('axios').default +const INVALID_PARAMETERS_ERROR = new Error('Invalid parameters') const stream = require('stream') const http = require('http') const https = require('https') @@ -46,7 +47,7 @@ function missing (...params) { } // calls the supplied callback or if not supplied, returns a rejected promise -function callbackOrRejectError (callback, error = new Error('Invalid parameters')) { +function callbackOrRejectError (callback, error = INVALID_PARAMETERS_ERROR) { if (callback) { return callback(error, null) } else { @@ -189,6 +190,33 @@ module.exports = exports = function dbScope (cfg) { } } + function streamResponseHandler (response, req, stream) { + const statusCode = response.status || (response.response && response.response.status) || 500 + if (response.isAxiosError && response.response) { + response = response.response + } + const message = response.statusText + + const responseHeaders = Object.assign({ + uri: req.url, + statusCode: statusCode + }, response.headers) + + const error = new Error(message) + error.scope = 'couch' + error.statusCode = statusCode + error.request = req + error.headers = responseHeaders + error.errid = 'non_200' + error.name = 'Error' + error.description = message + error.reason = message + + log({ err: 'couch', body: message, headers: responseHeaders }) + + stream.emit('error', error) + } + function relax (opts, callback) { if (typeof opts === 'function') { callback = opts @@ -339,7 +367,12 @@ module.exports = exports = function dbScope (cfg) { if (opts.stream) { // return the Request object for streaming const outStream = new stream.PassThrough() - axios(req).then((response) => { response.data.pipe(outStream) }) + axios(req) + .then((response) => { + response.data.pipe(outStream) + }).catch(e => { + streamResponseHandler(e, req, outStream) + }) return outStream } else { if (typeof callback === 'function') { diff --git a/test/attachment.getAsStream.test.js b/test/attachment.getAsStream.test.js index 61c54e76..6d80b3b4 100644 --- a/test/attachment.getAsStream.test.js +++ b/test/attachment.getAsStream.test.js @@ -41,3 +41,19 @@ test('should be able to get an attachment as a stream - GET /db/id/attname - db. }) }) }) + +test('should emit an error when stream attachment does not exist - GET /db/id/attname - db.attachment.getAsStream', () => { + // test GET /db/id/attname + nock(COUCH_URL) + .get('/db/id/notexists.gif') + .reply(404, 'Object Not Found', { 'content-type': 'application/json' }) + + return new Promise((resolve, reject) => { + const db = nano.db.use('db') + db.attachment.getAsStream('id', 'notexist.gif') + .on('error', (e) => { + expect(e.statusCode).toStrictEqual(404) + resolve() + }) + }) +})