123456789_123456789_123456789_123456789_123456789_

Class: Mongo::URI::SRVProtocol

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, URI
Instance Chain:
self, URI
Inherits: URI
  • Object
Defined in: lib/mongo/uri/srv_protocol.rb

Overview

Parser for a ::Mongo::URI using the mongodb+srv protocol, which specifies a DNS to query for SRV records. The driver will query the DNS server for SRV records on ., prefixed with _mongodb._tcp The SRV records can then be used as the seedlist for a ::Mongo::Client. The driver also queries for a TXT record providing default connection string options. Only one TXT record is allowed, and only a subset of ::Mongo::Client options is allowed.

Please refer to the Initial DNS Seedlist Discovery spec for details.

https://github.com/mongodb/specifications/blob/master/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md

Examples:

Use the uri string to make a client connection.

client = Mongo::Client.new('mongodb+srv://test6.test.build.10gen.cc/')

Since:

  • 2.5.0

Constant Summary

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#query_hostnameString (readonly)

This method is for internal use only.

The hostname that is specified in the ::Mongo::URI and used to look up SRV records.

This attribute needs to be defined because SRVProtocol changes #servers to be the result of the lookup rather than the hostname specified in the ::Mongo::URI.

Returns:

  • (String)

    The hostname used in SRV lookup.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 68

attr_reader :query_hostname

#srv_records (readonly)

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 35

attr_reader :srv_records

#srv_resultSrv::Result (readonly)

This method is for internal use only.

Returns:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 56

attr_reader :srv_result

Instance Method Details

#client_optionsHash

Gets the options hash that needs to be passed to a ::Mongo::Client on instantiation, so we don't have to merge the txt record options, credentials, and database in at that point - we only have a single point here.

Examples:

Get the client options.

uri.client_options

Returns:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 47

def client_options
  opts = @txt_options.merge(ssl: true)
  opts = opts.merge(uri_options).merge(database: database)
  @user ? opts.merge(credentials) : opts
end

#get_txt_options(hostname) ⇒ Hash (private)

Obtains the TXT options of a host.

Parameters:

  • hostname (String)

    The hostname whose records should be obtained.

Returns:

  • (Hash)

    The TXT record options (an empty hash if no TXT records are found).

Raises:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 193

def get_txt_options(hostname)
  options_string = resolver.get_txt_options_string(hostname)
  if options_string
    parse_txt_options!(options_string)
  else
    {}
  end
end

#parse!(remaining) (private)

Parses the credentials from the ::Mongo::URI and performs DNS queries to obtain the hosts and TXT options.

Parameters:

  • remaining (String)

    The portion of the ::Mongo::URI pertaining to the authentication credentials and the hosts.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 138

def parse!(remaining)
  super

  raise_invalid_error!(INVALID_HOST) if @servers.length != 1
  hostname = @servers.first
  validate_srv_hostname(hostname)
  @query_hostname = hostname

  log_debug "attempting to resolve #{hostname}"

  @srv_result = resolver.get_records(
    hostname,
    uri_options[:srv_service_name] || options[:srv_service_name],
    uri_options[:srv_max_hosts] || options[:srv_max_hosts]
  )
  raise Error::NoSRVRecords.new(NO_SRV_RECORDS % hostname) if srv_result.empty?

  @txt_options = get_txt_options(hostname) || {}
  records = srv_result.address_strs
  records.each do |record|
    validate_address_str!(record)
  end
  @servers = records
rescue Error::InvalidAddress => e
  raise_invalid_error!(e.message)
end

#parse_txt_options!(string) ⇒ Hash (private)

Parses the TXT record options into a hash and adds the options to set of all ::Mongo::URI options parsed.

Parameters:

  • string (String)

    The concatenated TXT options.

Returns:

  • (Hash)

    The parsed TXT options.

Raises:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 211

def parse_txt_options!(string)
  string.split(INDIV_URI_OPTS_DELIM).each_with_object({}) do |opt, txt_options|
    raise Error::InvalidTXTRecord.new(INVALID_OPTS_VALUE_DELIM) unless opt.index(URI_OPTS_VALUE_DELIM)

    key, value = opt.split('=')
    unless VALID_TXT_OPTIONS.include?(key.downcase)
      msg = "TXT records can only specify the options [#{VALID_TXT_OPTIONS.join(', ')}]: #{string}"
      raise Error::InvalidTXTRecord.new(msg)
    end
    options_mapper.add_uri_option(key, value, txt_options)
  end
end

#raise_invalid_error!(details) (private)

Raises an InvalidURI error.

Parameters:

  • details (String)

    A detailed error message.

Raises:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 116

def raise_invalid_error!(details)
  raise Error::InvalidURI.new(@string, details, FORMAT)
end

#resolverMongo::Srv::Resolver (private)

Gets the SRV resolver. If domain verification fails or no SRV records are found, an error must not be raised per the spec; instead, a warning is logged.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 125

def resolver
  @resolver ||= Srv::Resolver.new(
    raise_on_invalid: false,
    resolv_options: options[:resolv_options],
    timeout: options[:connect_timeout]
  )
end

#schemeString (private)

Gets the MongoDB SRV ::Mongo::URI scheme.

Returns:

  • (String)

    The MongoDB SRV URI scheme.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 107

def scheme
  MONGODB_SRV_SCHEME
end

#validate_srv_hostname(hostname) (private)

Validates the hostname used in an SRV URI.

The hostname cannot include a port.

The hostname must not begin with a dot, end with a dot, or have consecutive dots. The hostname must have a minimum of 1 component

Raises Error::InvalidURI if validation fails.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 173

def validate_srv_hostname(hostname)
  raise_invalid_error!(INVALID_PORT) if hostname.include?(HOST_PORT_DELIM)

  raise_invalid_error!("Hostname cannot start with a dot: #{hostname}") if hostname.start_with?('.')
  raise_invalid_error!("Hostname cannot end with a dot: #{hostname}") if hostname.end_with?('.')
  parts = hostname.split('.')
  raise_invalid_error!("Hostname cannot have consecutive dots: #{hostname}") if parts.any?(&:empty?)
  return unless parts.length < 1

  raise_invalid_error!("Hostname cannot be empty: #{hostname}")
end

#validate_uri_options! (private)

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/uri/srv_protocol.rb', line 224

def validate_uri_options!
  if uri_options[:direct_connection]
    raise_invalid_error_no_fmt!('directConnection=true is incompatible with SRV URIs')
  end

  super
end