Support the current MongoDB URI scheme with multiple hosts/ports separated by commas all using the same authentication and database.
This commit is contained in:
parent
69598857ef
commit
9eaf6b7b83
|
@ -20,7 +20,7 @@ module Mongo
|
||||||
class URIParser
|
class URIParser
|
||||||
|
|
||||||
DEFAULT_PORT = 27017
|
DEFAULT_PORT = 27017
|
||||||
MONGODB_URI_MATCHER = /(([-.\w]+):([^@]+)@)?([-.\w]+)(:([\w]+))?(\/([-\w]+))?/
|
MONGODB_URI_MATCHER = /(([-.\w]+):([^@,]+)@)?((?:(?:[-.\w]+)(?::(?:[\w]+))?,?)+)(\/([-\w]+))?/
|
||||||
MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
|
MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
|
||||||
SPEC_ATTRS = [:nodes, :auths]
|
SPEC_ATTRS = [:nodes, :auths]
|
||||||
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync]
|
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync]
|
||||||
|
@ -108,35 +108,43 @@ module Mongo
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def parse_hosts(hosts)
|
def parse_hosts(uri_without_proto)
|
||||||
@nodes = []
|
@nodes = []
|
||||||
@auths = []
|
@auths = []
|
||||||
specs = hosts.split(',')
|
|
||||||
specs.each do |spec|
|
matches = MONGODB_URI_MATCHER.match(uri_without_proto)
|
||||||
matches = MONGODB_URI_MATCHER.match(spec)
|
|
||||||
if !matches
|
if !matches
|
||||||
raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
|
raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
|
||||||
end
|
end
|
||||||
|
|
||||||
uname = matches[2]
|
uname = matches[2]
|
||||||
pwd = matches[3]
|
pwd = matches[3]
|
||||||
host = matches[4]
|
hosturis = matches[4].split(',')
|
||||||
port = matches[6] || DEFAULT_PORT
|
db = matches[6]
|
||||||
|
|
||||||
|
hosturis.each do |hosturi|
|
||||||
|
# If port is present, use it, otherwise use default port
|
||||||
|
host, port = hosturi.split(':') + [DEFAULT_PORT]
|
||||||
|
|
||||||
if !(port.to_s =~ /^\d+$/)
|
if !(port.to_s =~ /^\d+$/)
|
||||||
raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
|
raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
|
||||||
end
|
end
|
||||||
|
|
||||||
port = port.to_i
|
port = port.to_i
|
||||||
db = matches[8]
|
|
||||||
|
@nodes << [host, port]
|
||||||
|
end
|
||||||
|
|
||||||
if uname && pwd && db
|
if uname && pwd && db
|
||||||
auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
|
auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
|
||||||
elsif uname || pwd
|
elsif uname || pwd
|
||||||
raise MongoArgumentError, "MongoDB URI must include username, password, " +
|
raise MongoArgumentError, "MongoDB URI must include username, password, "
|
||||||
"and db if username or password are specified."
|
"and db if username and password are specified."
|
||||||
end
|
end
|
||||||
|
|
||||||
@nodes << [host, port]
|
# The auths are repeated for each host in a replica set
|
||||||
end
|
@auths *= hosturis.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
|
# This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
|
||||||
|
|
|
@ -43,7 +43,7 @@ class TestThreading < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_multiple_uris_with_auths
|
def test_multiple_uris_with_auths
|
||||||
parser = Mongo::URIParser.new('mongodb://bob:secret@a.example.com:27018/test,joe:secret2@b.example.com/test2')
|
parser = Mongo::URIParser.new('mongodb://bob:secret@a.example.com:27018,b.example.com/test')
|
||||||
assert_equal 2, parser.nodes.length
|
assert_equal 2, parser.nodes.length
|
||||||
assert_equal 'a.example.com', parser.nodes[0][0]
|
assert_equal 'a.example.com', parser.nodes[0][0]
|
||||||
assert_equal 27018, parser.nodes[0][1]
|
assert_equal 27018, parser.nodes[0][1]
|
||||||
|
@ -53,9 +53,9 @@ class TestThreading < Test::Unit::TestCase
|
||||||
assert_equal "bob", parser.auths[0]["username"]
|
assert_equal "bob", parser.auths[0]["username"]
|
||||||
assert_equal "secret", parser.auths[0]["password"]
|
assert_equal "secret", parser.auths[0]["password"]
|
||||||
assert_equal "test", parser.auths[0]["db_name"]
|
assert_equal "test", parser.auths[0]["db_name"]
|
||||||
assert_equal "joe", parser.auths[1]["username"]
|
assert_equal "bob", parser.auths[1]["username"]
|
||||||
assert_equal "secret2", parser.auths[1]["password"]
|
assert_equal "secret", parser.auths[1]["password"]
|
||||||
assert_equal "test2", parser.auths[1]["db_name"]
|
assert_equal "test", parser.auths[1]["db_name"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_opts_basic
|
def test_opts_basic
|
||||||
|
|
Loading…
Reference in New Issue