Skip to content

Commit 2b8ddd9

Browse files
fix parsing of read preference tags
1 parent 44bbd6e commit 2b8ddd9

File tree

2 files changed

+27
-16
lines changed

2 files changed

+27
-16
lines changed

src/connection_string.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ function toRecord(value: string): Record<string, any> {
228228
return record;
229229
}
230230

231-
class CaseInsensitiveMap extends Map<string, any> {
231+
class CaseInsensitiveMap<Value = any> extends Map<string, Value> {
232232
constructor(entries: Array<[string, any]> = []) {
233233
super(entries.map(([k, v]) => [k.toLowerCase(), v]));
234234
}
@@ -262,7 +262,7 @@ export function parseOptions(
262262
const mongoOptions = Object.create(null);
263263
mongoOptions.hosts = isSRV ? [] : hosts.map(HostAddress.fromString);
264264

265-
const urlOptions = new CaseInsensitiveMap();
265+
const urlOptions = new CaseInsensitiveMap<any[]>();
266266

267267
if (url.pathname !== '/' && url.pathname !== '') {
268268
const dbName = decodeURIComponent(
@@ -326,13 +326,16 @@ export function parseOptions(
326326
for (const key of allKeys) {
327327
const values = [];
328328
if (objectOptions.has(key)) {
329-
values.push(objectOptions.get(key));
329+
const options = [objectOptions.get(key)].flat();
330+
values.push(...options);
330331
}
331332
if (urlOptions.has(key)) {
332-
values.push(...urlOptions.get(key));
333+
const options = urlOptions.get(key) ?? [];
334+
values.push(...options);
333335
}
334336
if (DEFAULT_OPTIONS.has(key)) {
335-
values.push(DEFAULT_OPTIONS.get(key));
337+
const options = [DEFAULT_OPTIONS.get(key)].flat();
338+
values.push(...options);
336339
}
337340
allOptions.set(key, values);
338341
}
@@ -478,12 +481,11 @@ export function parseOptions(
478481
throw new MongoParseError('Can only specify both of proxy username/password or neither');
479482
}
480483

481-
if (
482-
urlOptions.get('proxyHost')?.length > 1 ||
483-
urlOptions.get('proxyPort')?.length > 1 ||
484-
urlOptions.get('proxyUsername')?.length > 1 ||
485-
urlOptions.get('proxyPassword')?.length > 1
486-
) {
484+
const proxyOptions = ['proxyHost', 'proxyPort', 'proxyUsername', 'proxyPassword'].map(
485+
key => urlOptions.get(key) ?? []
486+
);
487+
488+
if (proxyOptions.some(options => options.length > 1)) {
487489
throw new MongoParseError(
488490
'Proxy options cannot be specified multiple times in the connection string'
489491
);

test/unit/connection_string.test.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,20 @@ describe('Connection String', function () {
4646
expect(options.hosts[0].port).to.equal(27017);
4747
});
4848

49-
it('should parse multiple readPreferenceTags', function () {
50-
const options = parseOptions(
51-
'mongodb://hostname?readPreferenceTags=bar:foo&readPreferenceTags=baz:bar'
52-
);
53-
expect(options.readPreference.tags).to.deep.equal([{ bar: 'foo' }, { baz: 'bar' }]);
49+
context('readPreferenceTags', function () {
50+
it('should parse multiple readPreferenceTags when passed in the uri', () => {
51+
const options = parseOptions(
52+
'mongodb://hostname?readPreferenceTags=bar:foo&readPreferenceTags=baz:bar'
53+
);
54+
expect(options.readPreference.tags).to.deep.equal([{ bar: 'foo' }, { baz: 'bar' }]);
55+
});
56+
57+
it('should parse multiple readPreferenceTags when passed in options object', () => {
58+
const options = parseOptions('mongodb://hostname?', {
59+
readPreferenceTags: [{ bar: 'foo' }, { baz: 'bar' }]
60+
});
61+
expect(options.readPreference.tags).to.deep.equal([{ bar: 'foo' }, { baz: 'bar' }]);
62+
});
5463
});
5564

5665
it('should parse boolean values', function () {

0 commit comments

Comments
 (0)