class Mongo::URI

The URI class provides a way for users to parse the MongoDB uri as defined in the connection string format spec.

docs.mongodb.org/manual/reference/connection-string/

@example Use the uri string to make a client connection.

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

Constants

AUTH_DELIM

The character delimiting auth credentials.

@since 2.1.0

AUTH_MECH_MAP

Map of URI authentication mechanisms to ruby driver mechanisms

@since 2.0.0

AUTH_USER_PWD_DELIM

The character separating a username from the password.

@since 2.1.0

DATABASE_DELIM

The character delimiting a database.

@since 2.1.0

FORMAT

MongoDB URI format specification.

@since 2.0.0

HELP

MongoDB URI (connection string) documentation url

@since 2.0.0

HOST_DELIM

The character delimiting hosts.

@since 2.1.0

HOST_PORT_DELIM

The character separating a host and port.

@since 2.1.0

INDIV_URI_OPTS_DELIM

The character delimiting multiple options.

@since 2.1.0

INVALID_HOST

Error details for a missing host.

@since 2.1.0

INVALID_OPTS_DELIM

Error details for providing options without a database delimiter.

@since 2.1.0

INVALID_OPTS_VALUE_DELIM

Error details for an invalid options format.

@since 2.1.0

INVALID_PORT

Error details for an invalid port.

@since 2.1.0

INVALID_SCHEME

Error details for an invalid scheme.

@since 2.1.0

MONGODB_SCHEME

The mongodb connection string scheme root.

@since 2.5.0

MONGODB_SRV_SCHEME

The mongodb srv protocol connection string scheme root.

@since 2.5.0

PERCENT_CHAR

Percent sign that must be encoded in user creds.

@since 2.5.1

READ_MODE_MAP

Map of URI read preference modes to ruby driver read preference modes

@since 2.0.0

REPEATABLE_OPTIONS

Options that are allowed to appear more than once in the uri.

@since 2.1.0

SCHEME

The mongodb connection string scheme.

@deprecated Will be removed in 3.0.

@since 2.0.0

SCHEME_DELIM

Scheme delimiter.

@since 2.5.0

UNESCAPED_DATABASE

Error details for a non-urlencoded auth databsae name.

@since 2.1.0

UNESCAPED_UNIX_SOCKET

Error details for a non-urlencoded unix socket path.

@since 2.1.0

UNESCAPED_USER_PWD

Error details for an non-urlencoded user name or password.

@since 2.1.0

UNIX_SOCKET

Unix socket suffix.

@since 2.1.0

UNSAFE

Unsafe characters that must be urlencoded.

@since 2.1.0

URI_OPTION_MAP

Hash for storing map of URI option parameters to conversion strategies

URI_OPTS_DELIM

The character delimiting options.

@since 2.1.0

URI_OPTS_VALUE_DELIM

The character delimiting an option and its value.

@since 2.1.0

Attributes

options[R]

The uri parser object options.

@since 2.0.0

servers[R]

The servers specified in the uri.

@since 2.0.0

uri_options[R]

The options specified in the uri.

@since 2.1.0

Public Class Methods

get(string, opts = {}) click to toggle source

Get either a URI object or a SRVProtocol URI object.

@example Get the uri object.

URI.get(string)

@return [URI, URI::SRVProtocol] The uri object.

@since 2.5.0

# File lib/mongo/uri.rb, line 213
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
new(string, options = {}) click to toggle source

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

# File lib/mongo/uri.rb, line 251
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

Private Class Methods

uri_option(uri_key, name, extra = {}) click to toggle source

Simple internal dsl to register a MongoDB URI option in the URI_OPTION_MAP.

@param uri_key [String] The MongoDB URI option to register. @param name [Symbol] The name of the option in the driver. @param extra [Hash] Extra options.

* :group [Symbol] Nested hash where option will go.
* :type [Symbol] Name of function to transform value.
# File lib/mongo/uri.rb, line 419
def self.uri_option(uri_key, name, extra = {})
  URI_OPTION_MAP[uri_key] = { :name => name }.merge(extra)
end

Public Instance Methods

client_options() click to toggle source

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.

@example Get the client options.

uri.client_options

@return [ Hash ] The options passed to the Mongo::Client

@since 2.0.0

# File lib/mongo/uri.rb, line 235
def client_options
  opts = uri_options.merge(:database => database)
  @user ? opts.merge(credentials) : opts
end
credentials() click to toggle source

Get the credentials provided in the URI.

@example Get the credentials.

uri.credentials

@return [ Hash ] The credentials.

* :user [ String ] The user.
* :password [ String ] The provided password.

@since 2.0.0

# File lib/mongo/uri.rb, line 269
def credentials
  { :user => @user, :password => @password }
end
database() click to toggle source

Get the database provided in the URI.

@example Get the database.

uri.database

@return [String] The database.

@since 2.0.0

# File lib/mongo/uri.rb, line 281
def database
  @database ? @database : Database::ADMIN
end

Private Instance Methods

add_uri_option(strategy, value, uri_options) click to toggle source

Adds an option to the uri options hash via the supplied strategy.

Acquires a target for the option based on group.
Transforms the value.
Merges the option into the target.

@param strategy [Symbol] The strategy for this option. @param value [String] The value of the option. @param #uri_options [Hash] The base option target.

# File lib/mongo/uri.rb, line 541
def add_uri_option(strategy, value, uri_options)
  target = select_target(uri_options, strategy[:group])
  value = apply_transform(value, strategy[:type])
  merge_uri_option(target, value, strategy[:name])
end
apply_transform(value, type = nil) click to toggle source

Applies URI value transformation by either using the default cast or a transformation appropriate for the given type.

@param value [String] The value to be transformed. @param type [Symbol] The transform method.

# File lib/mongo/uri.rb, line 487
def apply_transform(value, type = nil)
  if type
    send(type, value)
  else
    cast(value)
  end
end
array(value) click to toggle source

Extract values from the string and put them into an array.

@param [ String ] value The string to build an array from.

@return [ Array ] The array built from the string.

# File lib/mongo/uri.rb, line 646
def array(value)
  value.split(',')
end
auth_mech(value) click to toggle source

Authentication mechanism transformation.

@param value [String] The authentication mechanism.

@return [Symbol] The transformed authentication mechanism.

# File lib/mongo/uri.rb, line 571
def auth_mech(value)
  AUTH_MECH_MAP[value.upcase]
end
auth_mech_props(value) click to toggle source

Auth mechanism properties extractor.

@param value [ String ] The auth mechanism properties string.

@return [ Hash ] The auth mechanism properties hash.

# File lib/mongo/uri.rb, line 607
def auth_mech_props(value)
  properties = hash_extractor(value)
  if properties[:canonicalize_host_name]
    properties.merge!(canonicalize_host_name:
                        properties[:canonicalize_host_name] == 'true')
  end
  properties
end
auth_source(value) click to toggle source

Auth source transformation, either db string or :external.

@param value [String] Authentication source.

@return [String] If auth source is database name. @return [:external] If auth source is external authentication.

# File lib/mongo/uri.rb, line 562
def auth_source(value)
  value == '$external' ? :external : decode(value)
end
cast(value) click to toggle source

Casts option values that do not have a specifically provided transformation to the appropriate type.

@param value [String] The value to be cast.

@return [true, false, Fixnum, Symbol] The cast value.

# File lib/mongo/uri.rb, line 470
def cast(value)
  if value == 'true'
    true
  elsif value == 'false'
    false
  elsif value =~ /[\d]/
    value.to_i
  else
    decode(value).to_sym
  end
end
decode(value) click to toggle source
# File lib/mongo/uri.rb, line 401
def decode(value)
  ::URI.decode(value)
end
encode(value) click to toggle source
# File lib/mongo/uri.rb, line 405
def encode(value)
  ::URI.encode(value)
end
extract_db_opts!(string) click to toggle source
# File lib/mongo/uri.rb, line 304
def extract_db_opts!(string)
  db_opts, _, creds_hosts = string.reverse.partition(DATABASE_DELIM)
  db_opts, creds_hosts = creds_hosts, db_opts if creds_hosts.empty?
  if db_opts.empty? && creds_hosts.include?(URI_OPTS_DELIM)
    raise_invalid_error!(INVALID_OPTS_DELIM)
  end
  [ creds_hosts, db_opts ].map { |s| s.reverse }
end
hash_extractor(value) click to toggle source

Extract values from the string and put them into a nested hash.

@param value [ String ] The string to build a hash from.

@return [ Hash ] The hash built from the string.

# File lib/mongo/uri.rb, line 634
def hash_extractor(value)
  value.split(',').reduce({}) do |set, tag|
    k, v = tag.split(':')
    set.merge(decode(k).downcase.to_sym => decode(v))
  end
end
merge_uri_option(target, value, name) click to toggle source

Merges a new option into the target.

If the option exists at the target destination the merge will be an addition.

Specifically required to append an additional tag set to the array of tag sets without overwriting the original.

@param target [Hash] The destination. @param value [Object] The value to be merged. @param name [Symbol] The name of the option.

# File lib/mongo/uri.rb, line 520
def merge_uri_option(target, value, name)
  if target.key?(name)
    if REPEATABLE_OPTIONS.include?(name)
      target[name] += value
    else
      log_warn("Repeated option key: #{name}.")
    end
  else
    target.merge!(name => value)
  end
end
ms_convert(value) click to toggle source

Ruby's convention is to provide timeouts in seconds, not milliseconds and to use fractions where more precision is necessary. The connection string options are always in MS so we provide an easy conversion type.

@param [ Integer ] value The millisecond value.

@return [ Float ] The seconds value.

@since 2.0.0

# File lib/mongo/uri.rb, line 625
def ms_convert(value)
  value.to_f / 1000
end
parse!(remaining) click to toggle source
# File lib/mongo/uri.rb, line 298
def parse!(remaining)
  creds_hosts, db_opts = extract_db_opts!(remaining)
  parse_creds_hosts!(creds_hosts)
  parse_db_opts!(db_opts)
end
parse_creds_hosts!(string) click to toggle source
# File lib/mongo/uri.rb, line 291
def parse_creds_hosts!(string)
  hosts, creds = split_creds_hosts(string)
  @servers = parse_servers!(hosts)
  @user = parse_user!(creds)
  @password = parse_password!(creds)
end
parse_database!(string) click to toggle source
# File lib/mongo/uri.rb, line 366
def parse_database!(string)
  raise_invalid_error!(UNESCAPED_DATABASE) if string =~ UNSAFE
  decode(string) if string.length > 0
end
parse_db_opts!(string) click to toggle source
# File lib/mongo/uri.rb, line 319
def parse_db_opts!(string)
  auth_db, _, uri_opts = string.partition(URI_OPTS_DELIM)
  @uri_options = Options::Redacted.new(parse_uri_options!(uri_opts))
  @database = parse_database!(auth_db)
end
parse_password!(string) click to toggle source
# File lib/mongo/uri.rb, line 353
def parse_password!(string)
  if (string && pwd = string.partition(AUTH_USER_PWD_DELIM)[2])
    if pwd.length > 0
      raise_invalid_error!(UNESCAPED_USER_PWD) if pwd =~ UNSAFE
      pwd_decoded = decode(pwd)
      if pwd_decoded =~ PERCENT_CHAR && encode(pwd_decoded) != pwd
        raise_invalid_error!(UNESCAPED_USER_PWD)
      end
      pwd_decoded
    end
  end
end
parse_servers!(string) click to toggle source
# File lib/mongo/uri.rb, line 377
def parse_servers!(string)
  raise_invalid_error!(INVALID_HOST) unless string.size > 0
  string.split(HOST_DELIM).reduce([]) do |servers, host|
    if host[0] == '['
      if host.index(']:')
        h, p = host.split(']:')
        validate_port_string!(p)
      end
    elsif host.index(HOST_PORT_DELIM)
      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
parse_uri_options!(string) click to toggle source
# File lib/mongo/uri.rb, line 325
def parse_uri_options!(string)
  return {} unless string
  string.split(INDIV_URI_OPTS_DELIM).reduce({}) do |uri_options, opt|
    raise_invalid_error!(INVALID_OPTS_VALUE_DELIM) unless opt.index(URI_OPTS_VALUE_DELIM)
    key, value = opt.split(URI_OPTS_VALUE_DELIM)
    strategy = URI_OPTION_MAP[key.downcase]
    if strategy.nil?
      log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
    else
      add_uri_option(strategy, value, uri_options)
    end
    uri_options
  end
end
parse_user!(string) click to toggle source
# File lib/mongo/uri.rb, line 340
def parse_user!(string)
  if (string && user = string.partition(AUTH_USER_PWD_DELIM)[0])
    if user.length > 0
      raise_invalid_error!(UNESCAPED_USER_PWD) if user =~ UNSAFE
      user_decoded = decode(user)
      if user_decoded =~ PERCENT_CHAR && encode(user_decoded) != user
        raise_invalid_error!(UNESCAPED_USER_PWD)
      end
      user_decoded
    end
  end
end
raise_invalid_error!(details) click to toggle source
# File lib/mongo/uri.rb, line 397
def raise_invalid_error!(details)
  raise Error::InvalidURI.new(@string, details, FORMAT)
end
read_mode(value) click to toggle source

Read preference mode transformation.

@param value [String] The read mode string value.

@return [Symbol] The read mode symbol.

# File lib/mongo/uri.rb, line 580
def read_mode(value)
  READ_MODE_MAP[value.downcase]
end
read_set(value) click to toggle source

Read preference tag set extractor.

@param value [String] The tag set string.

@return [Hash] The tag set hash.

# File lib/mongo/uri.rb, line 598
def read_set(value)
  hash_extractor(value)
end
read_tags(value) click to toggle source

Read preference tags transformation.

@param value [String] The string representing tag set.

@return [Array<Hash>] Array with tag set.

# File lib/mongo/uri.rb, line 589
def read_tags(value)
  [read_set(value)]
end
replica_set(value) click to toggle source

Replica set transformation, avoid converting to Symbol.

@param value [String] Replica set name.

@return [String] Same value to avoid cast to Symbol.

# File lib/mongo/uri.rb, line 552
def replica_set(value)
  decode(value)
end
scheme() click to toggle source
# File lib/mongo/uri.rb, line 287
def scheme
  MONGODB_SCHEME
end
select_target(uri_options, group = nil) click to toggle source

Selects the output destination for an option.

@param [Hash] #uri_options The base target. @param [Symbol] group Group subtarget.

@return [Hash] The target for the option.

# File lib/mongo/uri.rb, line 501
def select_target(uri_options, group = nil)
  if group
    uri_options[group] ||= {}
  else
    uri_options
  end
end
split_creds_hosts(string) click to toggle source
# File lib/mongo/uri.rb, line 313
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
validate_port_string!(port) click to toggle source
# File lib/mongo/uri.rb, line 371
def validate_port_string!(port)
  unless port.nil? || (port.length > 0 && port.to_i > 0 && port.to_i <= 65535)
    raise_invalid_error!(INVALID_PORT)
  end
end