Skip to content

Commit 93a9eff

Browse files
glynnbirdGlynn Bird
and
Glynn Bird
authored
to avoid circular references (#275)
* use selective attribute copy instead of clone to avoid circular references - fixes issue #274 * add a couple of tests to prevent circular references silently regressing Co-authored-by: Glynn Bird <glynnbird@apache.org>
1 parent 4e1ca07 commit 93a9eff

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

lib/nano.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,11 @@ module.exports = exports = function dbScope (cfg) {
381381
}
382382

383383
// scrub and log
384-
delete req.agent // Agent contains circular refs that does not works well with JSON.stringify
385-
const scrubbedReq = JSON.parse(JSON.stringify(req))
384+
const scrubbedReq = {
385+
method: req.method,
386+
headers: JSON.parse(JSON.stringify(req.headers)),
387+
url: req.url
388+
}
386389
scrubRequest(scrubbedReq, true)
387390
log(scrubbedReq)
388391

test/attachment.insert.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,20 @@ test('should be able to insert document attachment as stream - PUT /db/docname/a
9393
expect(reply).toStrictEqual(response)
9494
expect(scope.isDone()).toBe(true)
9595
})
96+
97+
test('should be able to insert document attachment as stream with circular reference - PUT /db/docname/attachment - db.attachment.insert', async () => {
98+
// mocks
99+
const response = { ok: true, id: 'docname', rev: '2-456' }
100+
const scope = nock(COUCH_URL, { reqheaders: { 'content-type': 'image/jpg' } })
101+
.put('/db/docname/logo2.jpg?rev=1-150', image2)
102+
.reply(200, response)
103+
104+
// test PUT /db/docname/attachment
105+
const rs = fs.createReadStream('./test/logo.jpg')
106+
// create artificial circular reference to make sure nano doesn't trip over on it
107+
rs.test = rs
108+
const db = nano.db.use('db')
109+
const reply = await db.attachment.insert('docname', 'logo2.jpg', rs, 'image/jpg', { rev: '1-150' })
110+
expect(reply).toStrictEqual(response)
111+
expect(scope.isDone()).toBe(true)
112+
})

test/nano.agent.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed under the Apache License, Version 2.0 (the 'License'); you may not
2+
// use this file except in compliance with the License. You may obtain a copy of
3+
// the License at
4+
//
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
//
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
9+
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
// License for the specific language governing permissions and limitations under
11+
// the License.
12+
13+
const nock = require('nock')
14+
const Nano = require('..')
15+
const COUCH_URL = 'http://localhost:5984'
16+
const http = require('http')
17+
const httpAgent = new http.Agent()
18+
19+
afterEach(() => {
20+
nock.cleanAll()
21+
})
22+
23+
test('should be able to log output with a user-supplied http agent', async () => {
24+
// setup Nano with custom logger
25+
const logs = []
26+
const nano = Nano({
27+
url: COUCH_URL,
28+
log: (data) => {
29+
logs.push(data)
30+
},
31+
requestDefaults: {
32+
agent: httpAgent
33+
}
34+
})
35+
36+
// mocks
37+
const response = { _id: 'id', rev: '1-123', a: 1, b: 'two', c: true }
38+
const scope = nock(COUCH_URL)
39+
.get('/db/id')
40+
.reply(200, response)
41+
42+
// test GET /db/id
43+
const db = nano.db.use('db')
44+
const p = await db.get('id')
45+
expect(p).toStrictEqual(response)
46+
expect(logs.length).toBe(2)
47+
expect(scope.isDone()).toBe(true)
48+
})

0 commit comments

Comments
 (0)