PYTHON-2795 Improve host parsing and error messages

This commit is contained in:
Bernie Hackett 2021-07-07 17:04:46 -07:00
parent 00ed2321ba
commit c8d920a46b
4 changed files with 41 additions and 5 deletions

View File

@ -650,7 +650,10 @@ class MongoClient(common.BaseObject):
opts = common._CaseInsensitiveDictionary()
fqdn = None
for entity in host:
if "://" in entity:
# A hostname can only include a-z, 0-9, '-' and '.'. If we find a '/'
# it must be a URI,
# https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
if "/" in entity:
# Determine connection timeout from kwargs.
timeout = keyword_opts.get("connecttimeoutms")
if timeout is not None:

View File

@ -14,6 +14,8 @@
"""Support for resolving hosts and options from mongodb+srv:// URIs."""
import ipaddress
try:
from dns import resolver
_HAVE_DNSPYTHON = True
@ -40,6 +42,9 @@ def _resolve(*args, **kwargs):
# dnspython 1.X
return resolver.query(*args, **kwargs)
_INVALID_HOST_MSG = (
"Invalid URI host: %s is not a valid hostname for 'mongodb+srv://'. "
"Did you mean to use 'mongodb://'?")
class _SrvResolver(object):
def __init__(self, fqdn, connect_timeout=None):
@ -47,13 +52,19 @@ class _SrvResolver(object):
self.__connect_timeout = connect_timeout or CONNECT_TIMEOUT
# Validate the fully qualified domain name.
try:
ipaddress.ip_address(fqdn)
raise ConfigurationError(_INVALID_HOST_MSG % ("an IP address",))
except ValueError:
pass
try:
self.__plist = self.__fqdn.split(".")[1:]
except Exception:
raise ConfigurationError("Invalid URI host: %s" % (fqdn,))
raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,))
self.__slen = len(self.__plist)
if self.__slen < 2:
raise ConfigurationError("Invalid URI host: %s" % (fqdn,))
raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,))
def get_options(self):
try:

View File

@ -166,6 +166,20 @@ class ClientUnitTest(unittest.TestCase):
with self.assertRaises(ValueError):
MongoClient(maxPoolSize=0)
def test_uri_detection(self):
self.assertRaises(
ConfigurationError,
MongoClient,
"/foo")
self.assertRaises(
ConfigurationError,
MongoClient,
"://")
self.assertRaises(
ConfigurationError,
MongoClient,
"foo/")
def test_get_db(self):
def make_db(base, name):
return base[name]

View File

@ -142,12 +142,20 @@ class TestParsingErrors(unittest.TestCase):
def test_invalid_host(self):
self.assertRaisesRegex(
ConfigurationError,
"Invalid URI host: mongodb",
"Invalid URI host: mongodb is not",
MongoClient, "mongodb+srv://mongodb")
self.assertRaisesRegex(
ConfigurationError,
"Invalid URI host: mongodb.com",
"Invalid URI host: mongodb.com is not",
MongoClient, "mongodb+srv://mongodb.com")
self.assertRaisesRegex(
ConfigurationError,
"Invalid URI host: an IP address is not",
MongoClient, "mongodb+srv://127.0.0.1")
self.assertRaisesRegex(
ConfigurationError,
"Invalid URI host: an IP address is not",
MongoClient, "mongodb+srv://[::1]")
if __name__ == '__main__':