lib/mongo/uri.rb in mongo-2.5.0.beta vs lib/mongo/uri.rb in mongo-2.5.0

- old
+ new

@@ -20,12 +20,12 @@ # defined in the connection string format spec. # # http://docs.mongodb.org/manual/reference/connection-string/ # # @example Use the uri string to make a client connection. - # uri = URI.new('mongodb://localhost:27017') - # client = Client.new(uri.server, uri.options) + # uri = Mongo::URI.new('mongodb://localhost:27017') + # client = Mongo::Client.new(uri.servers, uri.options) # client.login(uri.credentials) # client[uri.database] # # @since 2.0.0 class URI @@ -44,25 +44,53 @@ # The servers specified in the uri. # # @since 2.0.0 attr_reader :servers + # The mongodb connection string scheme. + # + # @deprecated Will be removed in 3.0. + # + # @since 2.0.0 + SCHEME = 'mongodb://'.freeze + + # The mongodb connection string scheme root. + # + # @since 2.5.0 + MONGODB_SCHEME = 'mongodb'.freeze + + # The mongodb srv protocol connection string scheme root. + # + # @since 2.5.0 + MONGODB_SRV_SCHEME = 'mongodb+srv'.freeze + + # Error details for an invalid scheme. + # + # @since 2.1.0 + INVALID_SCHEME = "Invalid scheme. Scheme must be '#{MONGODB_SCHEME}' or '#{MONGODB_SRV_SCHEME}'".freeze + + # MongoDB URI format specification. + # + # @since 2.0.0 + FORMAT = 'mongodb://[username:password@]host1[:port1][,host2[:port2]' + + ',...[,hostN[:portN]]][/[database][?options]]'.freeze + + # MongoDB URI (connection string) documentation url + # + # @since 2.0.0 + HELP = 'http://docs.mongodb.org/manual/reference/connection-string/'.freeze + # Unsafe characters that must be urlencoded. # # @since 2.1.0 UNSAFE = /[\:\/\+\@]/ # Unix socket suffix. # # @since 2.1.0 UNIX_SOCKET = /.sock/ - # The mongodb connection string scheme. - # - # @since 2.0.0 - SCHEME = 'mongodb://'.freeze - # The character delimiting hosts. # # @since 2.1.0 HOST_DELIM = ','.freeze @@ -99,14 +127,14 @@ # The character delimiting auth credentials. # # @since 2.1.0 AUTH_DELIM = '@'.freeze - # Error details for an invalid scheme. + # Scheme delimiter. # - # @since 2.1.0 - INVALID_SCHEME = "Invalid scheme. Scheme must be '#{SCHEME}'".freeze + # @since 2.5.0 + SCHEME_DELIM = '://'.freeze # Error details for an invalid options format. # # @since 2.1.0 INVALID_OPTS_VALUE_DELIM = "Options and their values must be delimited" + @@ -140,21 +168,10 @@ # Error details for an invalid port. # # @since 2.1.0 INVALID_PORT = "Invalid port. Port must be an integer greater than 0 and less than 65536".freeze - # MongoDB URI format specification. - # - # @since 2.0.0 - FORMAT = 'mongodb://[username:password@]host1[:port1][,host2[:port2]' + - ',...[,hostN[:portN]]][/[database][?options]]'.freeze - - # MongoDB URI (connection string) documentation url - # - # @since 2.0.0 - HELP = 'http://docs.mongodb.org/manual/reference/connection-string/'.freeze - # Map of URI read preference modes to ruby driver read preference modes # # @since 2.0.0 READ_MODE_MAP = { 'primary' => :primary, @@ -178,27 +195,28 @@ # Options that are allowed to appear more than once in the uri. # # @since 2.1.0 REPEATABLE_OPTIONS = [ :tag_sets ] - # Create the new uri from the provided string. + # Get either a URI object or a SRVProtocol URI object. # - # @example Create the new URI. - # URI.new('mongodb://localhost:27017') + # @example Get the uri object. + # URI.get(string) # - # @param [ String ] string The uri string. - # @param [ Hash ] options The options. + # @return [URI, URI::SRVProtocol] The uri object. # - # @raise [ Error::InvalidURI ] If the uri does not match the spec. - # - # @since 2.0.0 - def initialize(string, options = {}) - @string = string - @options = options - _, scheme, remaining = @string.partition(SCHEME) - raise_invalid_error!(INVALID_SCHEME) unless scheme == SCHEME - setup!(remaining) + # @since 2.5.0 + def self.get(string, opts = {}) + scheme, _, remaining = string.partition(SCHEME_DELIM) + case scheme + when MONGODB_SCHEME + URI.new(string, opts) + when MONGODB_SRV_SCHEME + SRVProtocol.new(string, opts) + else + raise Error::InvalidURI.new(string, INVALID_SCHEME) + end end # Gets the options hash that needs to be passed to a Mongo::Client on # instantiation, so we don't have to merge the credentials and database in # at that point - we only have a single point here. @@ -212,10 +230,29 @@ def client_options opts = uri_options.merge(:database => database) @user ? opts.merge(credentials) : opts end + # Create the new uri from the provided string. + # + # @example Create the new URI. + # URI.new('mongodb://localhost:27017') + # + # @param [ String ] string The uri string. + # @param [ Hash ] options The options. + # + # @raise [ Error::InvalidURI ] If the uri does not match the spec. + # + # @since 2.0.0 + def initialize(string, options = {}) + @string = string + @options = options + parsed_scheme, _, remaining = string.partition(SCHEME_DELIM) + raise_invalid_error!(INVALID_SCHEME) unless parsed_scheme == scheme + parse!(remaining) + end + # Get the credentials provided in the URI. # # @example Get the credentials. # uri.credentials # @@ -240,11 +277,22 @@ @database ? @database : Database::ADMIN end private - def setup!(remaining) + def scheme + MONGODB_SCHEME + end + + def parse_creds_hosts!(string) + hosts, creds = split_creds_hosts(string) + @servers = parse_servers!(hosts) + @user = parse_user!(creds) + @password = parse_password!(creds) + end + + def parse!(remaining) creds_hosts, db_opts = extract_db_opts!(remaining) parse_creds_hosts!(creds_hosts) parse_db_opts!(db_opts) end @@ -255,17 +303,10 @@ raise_invalid_error!(INVALID_OPTS_DELIM) end [ creds_hosts, db_opts ].map { |s| s.reverse } end - def parse_creds_hosts!(string) - hosts, creds = split_creds_hosts(string) - @servers = parse_servers!(hosts) - @user = parse_user!(creds) - @password = parse_password!(creds) - end - def split_creds_hosts(string) hosts, _, creds = string.reverse.partition(AUTH_DELIM) hosts, creds = creds, hosts if hosts.empty? [ hosts, creds ].map { |s| s.reverse } end @@ -328,17 +369,18 @@ h, _, p = host.partition(HOST_PORT_DELIM) raise_invalid_error!(INVALID_HOST) unless h.size > 0 validate_port_string!(p) elsif host =~ UNIX_SOCKET raise_invalid_error!(UNESCAPED_UNIX_SOCKET) if host =~ UNSAFE + host = decode(host) end servers << host end end def raise_invalid_error!(details) - raise Error::InvalidURI.new(@string, details) + raise Error::InvalidURI.new(@string, details, FORMAT) end def decode(value) ::URI::DEFAULT_PARSER.unescape(value) end @@ -583,5 +625,7 @@ def array(value) value.split(',') end end end + +require 'mongo/uri/srv_protocol'