Skip to content

Commit 432988b

Browse files
authored
fix(service-provider-core): allow specifying a host with _ characters MONGOSH-933 (#1048)
1 parent 813200d commit 432988b

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

packages/cli-repl/test/e2e.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { promises as fs, createReadStream } from 'fs';
88
import { promisify } from 'util';
99
import rimraf from 'rimraf';
1010
import path from 'path';
11+
import os from 'os';
1112
import { readReplLogfile } from './repl-helpers';
1213
import { bson } from '@mongosh/service-provider-core';
1314
const { EJSON } = bson;
@@ -447,6 +448,30 @@ describe('e2e', function() {
447448
});
448449
});
449450

451+
describe('with --host', () => {
452+
let shell: TestShell;
453+
it('allows invalid hostnames with _', async() => {
454+
shell = TestShell.start({
455+
args: [ '--host', 'xx_invalid_domain_xx' ],
456+
env: { ...process.env, FORCE_COLOR: 'true', TERM: 'xterm-256color' },
457+
forceTerminal: true
458+
});
459+
460+
const result = await Promise.race([
461+
shell.waitForPromptOrExit(),
462+
promisify(setTimeout)(5000)
463+
]);
464+
465+
shell.assertNotContainsOutput('host');
466+
if (typeof result === 'object') {
467+
expect(result.state).to.equal('exit');
468+
shell.assertContainsOutput('MongoNetworkError');
469+
} else {
470+
shell.kill(os.constants.signals.SIGKILL);
471+
}
472+
});
473+
});
474+
450475
describe('Ctrl+C aka SIGINT', () => {
451476
before(function() {
452477
if (process.platform === 'win32') {

packages/service-provider-core/src/uri-generator.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ describe('uri-generator.generate-uri', () => {
2525
it('handles host with port included', () => {
2626
expect(generateUri({ connectionSpecifier: undefined, host: 'localhost:27018' })).to.equal('mongodb://localhost:27018/?directConnection=true&serverSelectionTimeoutMS=2000');
2727
});
28+
it('handles host with an underscore', () => {
29+
expect(generateUri({ connectionSpecifier: undefined, host: 'some_host' })).to.equal('mongodb://some_host:27017/?directConnection=true');
30+
});
2831
it('throws if host has port AND port set to other value', () => {
2932
try {
3033
generateUri({ connectionSpecifier: undefined, host: 'localhost:27018', port: '27019' });
@@ -422,10 +425,10 @@ describe('uri-generator.generate-uri', () => {
422425
});
423426
it('returns a URI for the hosts and ports specified in --host and database name', () => {
424427
const options = {
425-
host: 'host1:123,host2,host3:456,',
428+
host: 'host1:123,host_2,host3:456,',
426429
connectionSpecifier: 'admin'
427430
};
428-
expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/admin');
431+
expect(generateUri(options)).to.equal('mongodb://host1:123,host_2,host3:456/admin');
429432
});
430433
});
431434
context('with a replica set', () => {

packages/service-provider-core/src/uri-generator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function validateConflicts(options: CliOptions, connectionString?: ConnectionStr
7171
* @param {string} host - The value of the --host option.
7272
*/
7373
function validateHost(host: string): void {
74-
const invalidCharacter = host.match(/[^a-zA-Z0-9.:\[\]-]/);
74+
const invalidCharacter = host.match(/[^a-zA-Z0-9.:\[\]_-]/);
7575
if (invalidCharacter) {
7676
throw new MongoshInvalidInputError(
7777
i18n.__(INVALID_HOST) + ': ' + invalidCharacter[0],
@@ -149,7 +149,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString {
149149
// If the --host argument contains /, it has the format
150150
// <replSetName>/<hostname1><:port>,<hostname2><:port>,<...>
151151
const replSetHostMatch = (options.host ?? '').match(
152-
/^(?<replSetName>[^/]+)\/(?<hosts>([A-Za-z0-9.-]+(:\d+)?,?)+)$/
152+
/^(?<replSetName>[^/]+)\/(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/
153153
);
154154
if (replSetHostMatch) {
155155
const { replSetName, hosts } = replSetHostMatch.groups as { replSetName: string, hosts: string };
@@ -162,7 +162,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString {
162162
// If the --host argument contains multiple hosts as a seed list
163163
// we directly do not do additional host/port parsing
164164
const seedList = (options.host ?? '').match(
165-
/^(?<hosts>([A-Za-z0-9.-]+(:\d+)?,?)+)$/
165+
/^(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/
166166
);
167167
if (seedList && options.host?.includes(',')) {
168168
const { hosts } = seedList.groups as { hosts: string };
@@ -190,7 +190,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString {
190190

191191
// Capture host, port and db from the string and generate a URI from
192192
// the parts. If there is a db part, it *must* start with /.
193-
const uriMatch = /^([A-Za-z0-9][A-Za-z0-9.-]+):?(\d+)?(?:\/(\S*))?$/gi;
193+
const uriMatch = /^([A-Za-z0-9][A-Za-z0-9._-]+):?(\d+)?(?:\/(\S*))?$/gi;
194194
let parts: string[] | null = uriMatch.exec(uri);
195195

196196
if (parts === null) {

0 commit comments

Comments
 (0)