class Mongo::URIParser
Constants
- AUTH_REGEX
- HOST_REGEX
- MONGODB_URI_MATCHER
- MONGODB_URI_SPEC
- NODE_REGEX
- OPT_ATTRS
- OPT_CASE_SENSITIVE
- OPT_CONV
- OPT_ERR
- OPT_VALID
- PATH_REGEX
- PORT_REGEX
- READ_PREFERENCES
- SPEC_ATTRS
Attributes
Public Class Methods
Parse a MongoDB URI. This method is used by Mongo::MongoClient.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.
# File lib/mongo/functional/uri_parser.rb, line 162 def initialize(uri) 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_options(opts) parse_hosts(hosts) validate_connect end
Public Instance Methods
Whether to immediately connect to the MongoDB node. Defaults to true. @return [true, false]
# File lib/mongo/functional/uri_parser.rb, line 207 def connect? connect != false end
Create a Mongo::MongoClient or a Mongo::MongoReplicaSetClient based on the URI.
@note Don't confuse this with attribute getter method connect.
@return [MongoClient,MongoReplicaSetClient]
# File lib/mongo/functional/uri_parser.rb, line 180 def connection(extra_opts={}, legacy = false, sharded = false) opts = connection_options.merge!(extra_opts) if(legacy) if replicaset? ReplSetConnection.new(node_strings, opts) else Connection.new(host, port, opts) end else if sharded MongoShardedClient.new(node_strings, opts) elsif replicaset? MongoReplicaSetClient.new(node_strings, opts) else MongoClient.new(host, port, opts) end end end
Options that can be passed to Mongo::MongoClient.new or Mongo::MongoReplicaSetClient.new @return [Hash]
# File lib/mongo/functional/uri_parser.rb, line 234 def connection_options opts = {} if @wtimeout warn "Using wtimeout in a URI is deprecated, please use wtimeoutMS. It will be removed in v2.0." opts[:wtimeout] = @wtimeout end opts[:wtimeout] = @wtimeoutms if @wtimeoutms opts[:w] = 1 if @safe opts[:w] = @w if @w opts[:j] = @journal if @journal opts[:fsync] = @fsync if @fsync opts[:connect_timeout] = @connecttimeoutms if @connecttimeoutms opts[:op_timeout] = @sockettimeoutms if @sockettimeoutms opts[:pool_size] = @pool_size if @pool_size opts[:read] = @readpreference if @readpreference if @slaveok && !@readpreference unless replicaset? opts[:slave_ok] = true else opts[:read] = :secondary_preferred end end if replicaset.is_a?(String) opts[:name] = replicaset end opts[:db_name] = @db_name if @db_name opts[:auths] = @auths if @auths opts[:ssl] = @ssl if @ssl opts[:connect] = connect? opts end
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/functional/uri_parser.rb, line 216 def direct? !replicaset? end
For direct connections, the host of the (only) node. @return [String]
# File lib/mongo/functional/uri_parser.rb, line 222 def host nodes[0][0] end
# File lib/mongo/functional/uri_parser.rb, line 273 def node_strings nodes.map { |node| node.join(':') } end
For direct connections, the port of the (only) node. @return [Integer]
# File lib/mongo/functional/uri_parser.rb, line 228 def port nodes[0][1].to_i end
Whether this represents a replica set. @return [true,false]
# File lib/mongo/functional/uri_parser.rb, line 201 def replicaset? replicaset.is_a?(String) || nodes.length > 1 end
Private Instance Methods
# File lib/mongo/functional/uri_parser.rb, line 279 def parse_hosts(uri_without_protocol) @nodes = [] @auths = Set.new unless matches = MONGODB_URI_MATCHER.match(uri_without_protocol) raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}" end user_info = matches[2].split(':') if matches[2] host_info = matches[3].split(',') @db_name = matches[8] host_info.each do |host| if host[0,1] == '[' host, port = host.split(']:') << MongoClient::DEFAULT_PORT host = host.end_with?(']') ? host[1...-1] : host[1..-1] else host, port = host.split(':') << MongoClient::DEFAULT_PORT end unless port.to_s =~ /^\d+$/ raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits." end @nodes << [host, port.to_i] end if @nodes.empty? raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at " + "least one node." end # no user info to parse, exit here return unless user_info # check for url encoding for username and password username, password = user_info if user_info.size > 2 || (username && username.include?('@')) || (password && password.include?('@')) raise MongoArgumentError, "The characters ':' and '@' in a username or password " + "must be escaped (RFC 2396)." end # if username exists, proceed adding to auth set unless username.nil? || username.empty? auth = Authentication.validate_credentials({ :db_name => @db_name, :username => URI.unescape(username), :password => password ? URI.unescape(password) : nil, :source => @authsource, :mechanism => @authmechanism }) auth[:extra] = @canonicalizehostname ? { :canonicalize_host_name => @canonicalizehostname } : {} auth[:extra].merge!(:gssapi_service_name => @gssapiservicename) if @gssapiservicename @auths << auth end end
This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate and convert the given options.
# File lib/mongo/functional/uri_parser.rb, line 343 def parse_options(string_opts) # initialize instance variables for available options OPT_VALID.keys.each { |k| instance_variable_set("@#{k}", nil) } string_opts ||= '' return if string_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 key_sym = key.downcase.to_sym memo[key_sym] = OPT_CASE_SENSITIVE.include?(key_sym) ? value.strip : value.strip.downcase memo end 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
# File lib/mongo/functional/uri_parser.rb, line 374 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