apache / couchdb-nano

Nano: The official Apache CouchDB library for Node.js
https://www.npmjs.com/package/nano
Apache License 2.0
651 stars 165 forks source link

db.multipart.insert return invalid UTF-8 JSON #238

Closed rmylb closed 3 years ago

rmylb commented 3 years ago

Expected Behavior

Insert doc and attachment(s) in the db with the db.multipart.insert function as described in docs.

Current Behavior

Error return

Error: invalid UTF-8 JSON
    at responseHandler (/root/progCEN-backend/node_modules/nano/lib/nano.js:171:20)
    at /root/progCEN-backend/node_modules/nano/lib/nano.js:357:13
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {

and

  scope: 'couch',
  statusCode: 400,
  request: {
    method: 'put',
    headers: {
      'content-type': 'multipart/related',
      'user-agent': 'nano/9.0.1 (Node.js v12.19.0)',
      'Accept-Encoding': 'deflate, gzip'
    },
    multipart: [ [Object], [Object] ],
    qsStringifyOptions: { arrayFormat: 'repeat' },
    url: 'http://XXXXXX:XXXXXX@localhost:5984/test/mydoc',
    params: undefined,
    paramsSerializer: [Function],
    data: undefined,
    maxRedirects: 0,
    httpAgent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 80,
      protocol: 'http:',
      options: [Object],
      requests: {},
      sockets: {},
      freeSockets: [Object],
      keepAliveMsecs: 30000,
      keepAlive: true,
      maxSockets: 50,
      maxFreeSockets: 256,
      maxTotalSockets: Infinity,
      totalSocketCount: 0,
      [Symbol(kCapture)]: false
    },
    httpsAgent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 443,
      protocol: 'https:',
      options: [Object],
      requests: {},
      sockets: {},
      freeSockets: {},
      keepAliveMsecs: 30000,
      keepAlive: true,
      maxSockets: 50,
      maxFreeSockets: 256,
      maxTotalSockets: Infinity,
      totalSocketCount: 0,
      maxCachedSessions: 100,
      _sessionCache: [Object],
      [Symbol(kCapture)]: false
    }
  },
  headers: {
    uri: 'http://admin:admin@localhost:5984/test/mydoc',
    statusCode: 400,
    'cache-control': 'must-revalidate',
    'content-type': 'application/json',
    date: 'Wed, 18 Nov 2020 11:00:58 GMT',
    'x-couch-request-id': '9fde561ae3',
    'x-couchdb-body-time': '0',
    url: undefined
  },
  errid: 'non_200',
  description: 'invalid UTF-8 JSON',
  error: 'bad_request',
  reason: 'invalid UTF-8 JSON'
}

Steps to Reproduce (for bugs)

  1. Run the following script with a local file called local-test.pdf
const nano = require('nano')(`http://admin:admin@localhost:5984`);
const db = nano.db.use('test');

const fs = require('fs');

fs.readFile('local-test.pdf', (err, data) => {
    if (!err) {
        db.multipart.insert({ foo: 'bar' }, [{name: 'local-test.pdf', data: data, content_type: 'application/pdf'}], 'mydoc')
            .then((body) => {
            console.log(body);
        })
            .catch((error) => {
                console.log(error)
            });
    }
});

Your Environment

Edit : I've downgrade to version 8.2.3 and is ok, but the version 9.0.0 and 9.0.1 aren't.

olafkrueger commented 3 years ago

Just to give another feedback: Same issue here with nano v9.0.3. Downgrade to v8.2.3 works.

jo commented 3 years ago

I also ran into this regression in multipart attachment support when I tried to update nano in couchdb-push. I'll use 8.2 for the time being. But I really like the switch to axios and the minimal dependency footprint, this is really awesome work!

I tried to debug the issue, but without much luck.

There is a test for this, but it shows a false positive. The request is nocked here but doesn't test the attachment request body sent.

I tried running the testsuite locally with NOCK_OFF=true but that seems not supported anymore? I see there is a hardcoded couchdb url, so it won't work against a Couch v3 (admin party has been removed from couch > 2). So I tried running it against couch v2 and also couch v1.7.2, but the testsuite fails with a lot of tests and I aborted it.

Next thing I tried was running the attachment test alone, with

NOCK_OFF=true npx jest --env node test/multipart.insert.test.js

and it throws Database does not exist. Looks like there's some setup code gone.

Looking at the code, the multipart data is added to the request, which is later passed to axios. But there seems no handling of multipart data in axios.

So from what I understand is needed is to manually construct the multipart body. In the browser, this can be done via FormData and in node possibly with the form-data package.

pejman1 commented 3 years ago

I have same problem with version 9.0.3 - downgrade to version 8.2.3 solve the issue

pejman1 commented 3 years ago

The problem still has not been resolved in version 9.0.4 . I get same error during upload multipart insert downgrading to version 8 will solve this issue @jo Johannes Jörg Schmidt https://github.com/jo/nano-option/pull/22

glynnbird commented 3 years ago

Fixed in nano@9.0.5