class Mongo::URIParser

Constants

AUTH_REGEX
HOST_REGEX
MONGODB_URI_MATCHER
MONGODB_URI_SPEC
NODE_REGEX
OPT_ATTRS
OPT_CONV
OPT_ERR
OPT_VALID
PASS_REGEX
PATH_REGEX
PORT_REGEX
SPEC_ATTRS
USER_REGEX

Attributes

auths[R]
connect[R]
connecttimeoutms[R]
fsync[R]
journal[R]
nodes[R]
replicaset[R]
safe[R]
slaveok[R]
sockettimeoutms[R]
w[R]
wtimeout[R]
wtimeoutms[R]

Public Class Methods

new(uri, extra_opts={}) click to toggle source

Parse a MongoDB URI. This method is used by Mongo::Connection.from_uri. Returns an array of nodes and an array of db authorizations, if applicable.

@note Passwords can contain any character except for ','

@param [String] uri The MongoDB URI string. @param [Hash,nil] extra_opts Extra options. Will override anything already specified in the URI.

@core connections

# File lib/mongo/util/uri_parser.rb, line 89
def initialize(uri, extra_opts={})
  if uri.start_with?('mongodb://')
    uri = uri[10..-1]
  else
    raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
  end

  hosts, opts = uri.split('?')
  parse_hosts(hosts)
  parse_options(opts, extra_opts)
  validate_connect
end

Public Instance Methods

connect?() click to toggle source

Whether to immediately connect to the MongoDB node. Defaults to true. @return [true, false]

# File lib/mongo/util/uri_parser.rb, line 123
def connect?
  connect != false
end
connection() click to toggle source

Create a Mongo::Connection or a Mongo::ReplSetConnection based on the URI.

@note Don't confuse this with attribute getter method connect.

@return [Connection,ReplSetConnection]

# File lib/mongo/util/uri_parser.rb, line 107
def connection
  if replicaset?
    ReplSetConnection.new(*(nodes+[connection_options]))
  else
    Connection.new(host, port, connection_options)
  end
end
connection_options() click to toggle source

Options that can be passed to Mongo::Connection.new or Mongo::ReplSetConnection.new @return [Hash]

# File lib/mongo/util/uri_parser.rb, line 150
def connection_options
  opts = {}

  if (@w || @journal || @wtimeout || @fsync || @wtimeoutms) && !@safe
    raise MongoArgumentError, "Safe must be true if w, journal, wtimeoutMS, or fsync is specified"
  end

  if @safe
    if @w || @journal || @wtimeout || @fsync || @wtimeoutms
      safe_opts = {}
      safe_opts[:w] = @w if @w
      safe_opts[:j] = @journal if @journal
      
      if @wtimeout
        warn "Using wtimeout in a URI is deprecated, please use wtimeoutMS. It will be removed in v2.0."
        safe_opts[:wtimeout] = @wtimeout
      end
      
      if @wtimeoutms
        safe_opts[:wtimeout] = @wtimeoutms
      end
      
      safe_opts[:fsync] = @fsync if @fsync
    else
      safe_opts = true
    end

    opts[:safe] = safe_opts
  end
  
  if @connecttimeoutms
    opts[:connect_timeout] = @connecttimeoutms
  end
  
  if @sockettimeoutms
    opts[:op_timeout] = @sockettimeoutms
  end

  if @slaveok
    if direct?
      opts[:slave_ok] = true
    else
      opts[:read] = :secondary
    end
  end

  if direct?
    opts[:auths] = auths
  end

  if replicaset.is_a?(String)
    opts[:name] = replicaset
  end

  opts[:connect] = connect?

  opts
end
direct?() click to toggle source

Whether this represents a direct connection.

@note Specifying :connect => 'direct' has no effect… other than to raise an exception if other variables suggest a replicaset.

@return [true,false]

# File lib/mongo/util/uri_parser.rb, line 132
def direct?
  !replicaset?
end
host() click to toggle source

For direct connections, the host of the (only) node. @return [String]

# File lib/mongo/util/uri_parser.rb, line 138
def host
  nodes[0][0]
end
port() click to toggle source

For direct connections, the port of the (only) node. @return [Integer]

# File lib/mongo/util/uri_parser.rb, line 144
def port
  nodes[0][1].to_i
end
replicaset?() click to toggle source

Whether this represents a replica set. @return [true,false]

# File lib/mongo/util/uri_parser.rb, line 117
def replicaset?
  replicaset.is_a?(String) || nodes.length > 1
end

Private Instance Methods

parse_hosts(uri_without_proto) click to toggle source
# File lib/mongo/util/uri_parser.rb, line 211
def parse_hosts(uri_without_proto)
  @nodes = []
  @auths = []

  matches = MONGODB_URI_MATCHER.match(uri_without_proto)

  if !matches
    raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
  end

  uname    = matches[2]
  pwd      = matches[3]
  hosturis = matches[4].split(',')
  db       = matches[8]

  hosturis.each do |hosturi|
    # If port is present, use it, otherwise use default port
    host, port = hosturi.split(':') + [Connection::DEFAULT_PORT]

    if !(port.to_s =~ /^\d+$/)
      raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
    end

    port = port.to_i

    @nodes << [host, port]
  end

  if @nodes.empty?
    raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at least one node."
  end

  if uname && pwd && db
    auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
  elsif uname || pwd
    raise MongoArgumentError, "MongoDB URI must include username, password, "
      "and db if username and password are specified."
  end

  # The auths are repeated for each host in a replica set
  @auths *= hosturis.length
end
parse_options(string_opts, extra_opts={}) click to toggle source

This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate and convert the given options.

# File lib/mongo/util/uri_parser.rb, line 256
def parse_options(string_opts, extra_opts={})
  # initialize instance variables for available options
  OPT_VALID.keys.each { |k| instance_variable_set("@#{k}", nil) }

  string_opts ||= ''

  return if string_opts.empty? && extra_opts.empty?

  if string_opts.include?(';') and string_opts.include?('&')
    raise MongoArgumentError, "must not mix URL separators ; and &"
  end

  opts = CGI.parse(string_opts).inject({}) do |memo, (key, value)|
    value = value.first
    memo[key.downcase.to_sym] = value.strip.downcase
    memo
  end

  opts.merge! extra_opts

  opts.each do |key, value|
    if !OPT_ATTRS.include?(key)
      raise MongoArgumentError, "Invalid Mongo URI option #{key}"
    end
    if OPT_VALID[key].call(value)
      instance_variable_set("@#{key}", OPT_CONV[key].call(value))
    else
      raise MongoArgumentError, "Invalid value #{value.inspect} for #{key}: #{OPT_ERR[key]}"
    end
  end
end
validate_connect() click to toggle source
# File lib/mongo/util/uri_parser.rb, line 288
def validate_connect
  if replicaset? and @connect == 'direct'
    # Make sure the user doesn't specify something contradictory
    raise MongoArgumentError, "connect=direct conflicts with setting a replicaset name"
  end
end