PYTHON-1282 Username/password must be URI-escaped
Not just "%", "@", and ":" must be escaped, all delimiters from RFC 3986 must be percent-encoded. Therefore, since "/" must be escaped in username and password, we can split the URI at the first "/" instead of the last.
This commit is contained in:
parent
803c83d342
commit
c72ee15b52
@ -5,19 +5,22 @@ MongoDB supports several different authentication mechanisms. These examples
|
||||
cover all authentication methods currently supported by PyMongo, documenting
|
||||
Python module and MongoDB version dependencies.
|
||||
|
||||
Support For Special Characters In Usernames And Passwords
|
||||
---------------------------------------------------------
|
||||
Percent-Escaping Username and Password
|
||||
--------------------------------------
|
||||
|
||||
If your username or password contains special characters (e.g. '/', ' ',
|
||||
or '@') you must ``%xx`` escape them for use in the MongoDB URI. PyMongo
|
||||
uses :meth:`~urllib.unquote_plus` to decode them. For example::
|
||||
Username and password must be percent-escaped with :meth:`~urllib.quote_plus`
|
||||
to be used in a MongoDB URI. PyMongo uses :meth:`~urllib.unquote_plus`
|
||||
internally to decode them. For example::
|
||||
|
||||
>>> from pymongo import MongoClient
|
||||
>>> import urllib
|
||||
>>> username = urllib.quote_plus('user')
|
||||
>>> username
|
||||
'user'
|
||||
>>> password = urllib.quote_plus('pass/word')
|
||||
>>> password
|
||||
'pass%2Fword'
|
||||
>>> MongoClient('mongodb://user:' + password + '@127.0.0.1')
|
||||
>>> MongoClient('mongodb://%s:%s@127.0.0.1' % (username, password)
|
||||
MongoClient('127.0.0.1', 27017)
|
||||
|
||||
SCRAM-SHA-1 (RFC 5802)
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
"""Tools to parse and validate a MongoDB URI."""
|
||||
import re
|
||||
import warnings
|
||||
|
||||
from bson.py3compat import PY3, iteritems, string_type
|
||||
@ -68,7 +69,7 @@ def _rpartition(entity, sep):
|
||||
def parse_userinfo(userinfo):
|
||||
"""Validates the format of user information in a MongoDB URI.
|
||||
Reserved characters like ':', '/', '+' and '@' must be escaped
|
||||
following RFC 2396.
|
||||
following RFC 3986.
|
||||
|
||||
Returns a 2-tuple containing the unescaped username followed
|
||||
by the unescaped password.
|
||||
@ -80,16 +81,13 @@ def parse_userinfo(userinfo):
|
||||
Now uses `urllib.unquote_plus` so `+` characters must be escaped.
|
||||
"""
|
||||
if '@' in userinfo or userinfo.count(':') > 1:
|
||||
raise InvalidURI("':' or '@' characters in a username or password "
|
||||
"must be escaped according to RFC 2396.")
|
||||
raise InvalidURI("Username and password must be escaped according to "
|
||||
"RFC 3986, use urllib.quote_plus().")
|
||||
user, _, passwd = _partition(userinfo, ":")
|
||||
# No password is expected with GSSAPI authentication.
|
||||
if not user:
|
||||
raise InvalidURI("The empty string is not valid username.")
|
||||
user = unquote_plus(user)
|
||||
passwd = unquote_plus(passwd)
|
||||
|
||||
return user, passwd
|
||||
return unquote_plus(user), unquote_plus(passwd)
|
||||
|
||||
|
||||
def parse_ipv6_literal_host(entity, default_port):
|
||||
@ -251,6 +249,11 @@ def split_hosts(hosts, default_port=DEFAULT_PORT):
|
||||
return nodes
|
||||
|
||||
|
||||
# Prohibited characters in database name. DB names also can't have ".", but for
|
||||
# backward-compat we allow "db.collection" in URI.
|
||||
_BAD_DB_CHARS = re.compile('[' + re.escape(r'/ "$') + ']')
|
||||
|
||||
|
||||
def parse_uri(uri, default_port=DEFAULT_PORT, validate=True, warn=False):
|
||||
"""Parse and validate a MongoDB URI.
|
||||
|
||||
@ -294,19 +297,10 @@ def parse_uri(uri, default_port=DEFAULT_PORT, validate=True, warn=False):
|
||||
collection = None
|
||||
options = {}
|
||||
|
||||
# Check for unix domain sockets in the uri
|
||||
if '.sock' in scheme_free:
|
||||
host_part, _, path_part = _rpartition(scheme_free, '/')
|
||||
if not host_part:
|
||||
host_part = path_part
|
||||
path_part = ""
|
||||
if '/' in host_part:
|
||||
raise InvalidURI("Any '/' in a unix domain socket must be"
|
||||
" URL encoded: %s" % host_part)
|
||||
host_part = unquote_plus(host_part)
|
||||
path_part = unquote_plus(path_part)
|
||||
else:
|
||||
host_part, _, path_part = _partition(scheme_free, '/')
|
||||
host_part, _, path_part = _partition(scheme_free, '/')
|
||||
if not host_part:
|
||||
host_part = path_part
|
||||
path_part = ""
|
||||
|
||||
if not path_part and '?' in host_part:
|
||||
raise InvalidURI("A '/' is required between "
|
||||
@ -318,17 +312,24 @@ def parse_uri(uri, default_port=DEFAULT_PORT, validate=True, warn=False):
|
||||
else:
|
||||
hosts = host_part
|
||||
|
||||
if '/' in hosts:
|
||||
raise InvalidURI("Any '/' in a unix domain socket must be"
|
||||
" URL encoded: %s" % host_part)
|
||||
|
||||
hosts = unquote_plus(hosts)
|
||||
nodes = split_hosts(hosts, default_port=default_port)
|
||||
|
||||
if path_part:
|
||||
|
||||
if path_part[0] == '?':
|
||||
opts = path_part[1:]
|
||||
opts = unquote_plus(path_part[1:])
|
||||
else:
|
||||
dbase, _, opts = _partition(path_part, '?')
|
||||
dbase, _, opts = map(unquote_plus, _partition(path_part, '?'))
|
||||
if '.' in dbase:
|
||||
dbase, collection = dbase.split('.', 1)
|
||||
|
||||
if _BAD_DB_CHARS.search(dbase):
|
||||
raise InvalidURI('Bad database name "%s"' % dbase)
|
||||
|
||||
if opts:
|
||||
options = split_options(opts, validate, warn)
|
||||
|
||||
|
||||
@ -189,6 +189,15 @@
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Username with password containing an unescaped colon",
|
||||
"hosts": null,
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo:bar@127.0.0.1",
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Username containing an unescaped at-sign",
|
||||
@ -207,6 +216,33 @@
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Username containing an unescaped slash",
|
||||
"hosts": null,
|
||||
"options": null,
|
||||
"uri": "mongodb://alice/@localhost/db",
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Username containing unescaped slash with password",
|
||||
"hosts": null,
|
||||
"options": null,
|
||||
"uri": "mongodb://alice/bob:foo@localhost/db",
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Username with password containing an unescaped slash",
|
||||
"hosts": null,
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo/bar@localhost/db",
|
||||
"valid": false,
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Host with unescaped slash",
|
||||
|
||||
@ -2,328 +2,309 @@
|
||||
"tests": [
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "foo",
|
||||
"db": null,
|
||||
"password": "foo",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "User info for single IPv4 host without database",
|
||||
},
|
||||
"description": "User info for single IPv4 host without database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo@127.0.0.1",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo@127.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "test",
|
||||
"password": "foo",
|
||||
"db": "test",
|
||||
"password": "foo",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "User info for single IPv4 host with database",
|
||||
},
|
||||
"description": "User info for single IPv4 host with database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo@127.0.0.1/test",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:foo@127.0.0.1/test",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "t\u0000est",
|
||||
"password": "f\u0000oo",
|
||||
"username": "a\u0000lice"
|
||||
},
|
||||
"description": "User info for single IPv4 host with database (escaped null bytes)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://a%00lice:f%00oo@127.0.0.1/t%00est",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "bar",
|
||||
"db": null,
|
||||
"password": "bar",
|
||||
"username": "bob"
|
||||
},
|
||||
"description": "User info for single IP literal host without database",
|
||||
},
|
||||
"description": "User info for single IP literal host without database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "::1",
|
||||
"port": 27018,
|
||||
"host": "::1",
|
||||
"port": 27018,
|
||||
"type": "ip_literal"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://bob:bar@[::1]:27018",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://bob:bar@[::1]:27018",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin",
|
||||
"password": "bar",
|
||||
"db": "admin",
|
||||
"password": "bar",
|
||||
"username": "bob"
|
||||
},
|
||||
"description": "User info for single IP literal host with database",
|
||||
},
|
||||
"description": "User info for single IP literal host with database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "::1",
|
||||
"port": 27018,
|
||||
"host": "::1",
|
||||
"port": 27018,
|
||||
"type": "ip_literal"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://bob:bar@[::1]:27018/admin",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://bob:bar@[::1]:27018/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "baz",
|
||||
"db": null,
|
||||
"password": "baz",
|
||||
"username": "eve"
|
||||
},
|
||||
"description": "User info for single hostname without database",
|
||||
},
|
||||
"description": "User info for single hostname without database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://eve:baz@example.com",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://eve:baz@example.com",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "db2",
|
||||
"password": "baz",
|
||||
"db": "db2",
|
||||
"password": "baz",
|
||||
"username": "eve"
|
||||
},
|
||||
"description": "User info for single hostname with database",
|
||||
},
|
||||
"description": "User info for single hostname with database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://eve:baz@example.com/db2",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://eve:baz@example.com/db2",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "secret",
|
||||
"db": null,
|
||||
"password": "secret",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "User info for multiple hosts without database",
|
||||
},
|
||||
"description": "User info for multiple hosts without database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
},
|
||||
},
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": 27018,
|
||||
"host": "example.com",
|
||||
"port": 27018,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:secret@127.0.0.1,example.com:27018",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:secret@127.0.0.1,example.com:27018",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin",
|
||||
"password": "secret",
|
||||
"db": "admin",
|
||||
"password": "secret",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "User info for multiple hosts with database",
|
||||
},
|
||||
"description": "User info for multiple hosts with database",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
},
|
||||
},
|
||||
{
|
||||
"host": "::1",
|
||||
"port": 27019,
|
||||
"host": "::1",
|
||||
"port": 27019,
|
||||
"type": "ip_literal"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:secret@example.com,[::1]:27019/admin",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:secret@example.com,[::1]:27019/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": null,
|
||||
"db": null,
|
||||
"password": null,
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "Username without password",
|
||||
},
|
||||
"description": "Username without password",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice@127.0.0.1",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice@127.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "",
|
||||
"db": null,
|
||||
"password": "",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "Username with empty password",
|
||||
},
|
||||
"description": "Username with empty password",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:@127.0.0.1",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://alice:@127.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "my=db",
|
||||
"password": null,
|
||||
"username": "@l:ce"
|
||||
},
|
||||
"description": "Escaped username and database without password",
|
||||
"db": "my=db",
|
||||
"password": null,
|
||||
"username": "@l:ce/="
|
||||
},
|
||||
"description": "Escaped username and database without password",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%40l%3Ace@example.com/my%3Ddb",
|
||||
"valid": true,
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%40l%3Ace%2F%3D@example.com/my%3Ddb",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin?",
|
||||
"password": "f:zzb@zz",
|
||||
"db": "admin?",
|
||||
"password": "f:zzb@z/z=",
|
||||
"username": "$am"
|
||||
},
|
||||
"description": "Escaped user info and database (MONGODB-CR)",
|
||||
},
|
||||
"description": "Escaped user info and database (MONGODB-CR)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
],
|
||||
"options": {
|
||||
"authmechanism": "MONGODB-CR"
|
||||
},
|
||||
"uri": "mongodb://%24am:f%3Azzb%40zz@127.0.0.1/admin%3F?authMechanism=MONGODB-CR",
|
||||
"valid": true,
|
||||
},
|
||||
"uri": "mongodb://%24am:f%3Azzb%40z%2Fz%3D@127.0.0.1/admin%3F?authMechanism=MONGODB-CR",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": null,
|
||||
"db": null,
|
||||
"password": null,
|
||||
"username": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry"
|
||||
},
|
||||
"description": "Escaped username (MONGODB-X509)",
|
||||
},
|
||||
"description": "Escaped username (MONGODB-X509)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": null,
|
||||
"host": "localhost",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
],
|
||||
"options": {
|
||||
"authmechanism": "MONGODB-X509"
|
||||
},
|
||||
"uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509",
|
||||
"valid": true,
|
||||
},
|
||||
"uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": null,
|
||||
"password": "secret",
|
||||
"db": null,
|
||||
"password": "secret",
|
||||
"username": "user@EXAMPLE.COM"
|
||||
},
|
||||
"description": "Escaped username (GSSAPI)",
|
||||
},
|
||||
"description": "Escaped username (GSSAPI)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": null,
|
||||
"host": "localhost",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
],
|
||||
"options": {
|
||||
"authmechanism": "GSSAPI",
|
||||
"authmechanism": "GSSAPI",
|
||||
"authmechanismproperties": {
|
||||
"CANONICALIZE_HOST_NAME": true,
|
||||
"CANONICALIZE_HOST_NAME": true,
|
||||
"SERVICE_NAME": "other"
|
||||
}
|
||||
},
|
||||
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI",
|
||||
"valid": true,
|
||||
},
|
||||
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin",
|
||||
"password": "secret",
|
||||
"db": "admin",
|
||||
"password": "secret",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "At-signs in options aren't part of the userinfo",
|
||||
},
|
||||
"description": "At-signs in options aren't part of the userinfo",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
],
|
||||
"options": {
|
||||
"replicaset": "my@replicaset"
|
||||
},
|
||||
"uri": "mongodb://alice:secret@example.com/admin?replicaset=my@replicaset",
|
||||
"valid": true,
|
||||
},
|
||||
"uri": "mongodb://alice:secret@example.com/admin?replicaset=my@replicaset",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
}
|
||||
]
|
||||
|
||||
100
test/connection_string/test/valid-db-with-dotted-name.json
Normal file
100
test/connection_string/test/valid-db-with-dotted-name.json
Normal file
@ -0,0 +1,100 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.sock",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets and auth DB resembling a socket (relative path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "rel/mongodb-27017.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
},
|
||||
{
|
||||
"host": "rel/mongodb-27018.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.sock",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.shoe",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets with auth DB resembling a path (relative path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "rel/mongodb-27017.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
},
|
||||
{
|
||||
"host": "rel/mongodb-27018.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.shoe",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.sock",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets and auth DB resembling a socket (absolute path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "/tmp/mongodb-27017.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
},
|
||||
{
|
||||
"host": "/tmp/mongodb-27018.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.sock",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.shoe",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets with auth DB resembling a path (absolute path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "/tmp/mongodb-27017.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
},
|
||||
{
|
||||
"host": "/tmp/mongodb-27018.sock",
|
||||
"port": null,
|
||||
"type": "unix"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.shoe",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,154 +1,154 @@
|
||||
{
|
||||
"tests": [
|
||||
"tests": [
|
||||
{
|
||||
"description": "Single IPv4 host without port",
|
||||
"uri": "mongodb://127.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single IPv4 host without port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://127.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single IPv4 host with port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 27018,
|
||||
"type": "ipv4"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://127.0.0.1:27018",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single IP literal host without port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "::1",
|
||||
"port": null,
|
||||
"type": "ip_literal"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://[::1]",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single IP literal host with port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "::1",
|
||||
"port": 27019,
|
||||
"type": "ip_literal"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://[::1]:27019",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single hostname without port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://example.com",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single hostname with port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": 27020,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://example.com:27020",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Single hostname (resembling IPv4) without port",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "256.0.0.1",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://256.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Multiple hosts (mixed formats)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": null,
|
||||
"type": "ipv4"
|
||||
},
|
||||
{
|
||||
"host": "::1",
|
||||
"port": 27018,
|
||||
"type": "ip_literal"
|
||||
},
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": 27019,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://127.0.0.1,[::1]:27018,example.com:27019",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "UTF-8 hosts",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "b\u00fccher.example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
},
|
||||
{
|
||||
"host": "uml\u00e4ut.example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://b\u00fccher.example.com,uml\u00e4ut.example.com/",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
"type": "ipv4",
|
||||
"host": "127.0.0.1",
|
||||
"port": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single IPv4 host with port",
|
||||
"uri": "mongodb://127.0.0.1:27018",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "ipv4",
|
||||
"host": "127.0.0.1",
|
||||
"port": 27018
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single IP literal host without port",
|
||||
"uri": "mongodb://[::1]",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "ip_literal",
|
||||
"host": "::1",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single IP literal host with port",
|
||||
"uri": "mongodb://[::1]:27019",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "ip_literal",
|
||||
"host": "::1",
|
||||
"port": 27019
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single hostname without port",
|
||||
"uri": "mongodb://example.com",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single hostname with port",
|
||||
"uri": "mongodb://example.com:27020",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": 27020
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Single hostname (resembling IPv4) without port",
|
||||
"uri": "mongodb://256.0.0.1",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "256.0.0.1",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Multiple hosts (mixed formats)",
|
||||
"uri": "mongodb://127.0.0.1,[::1]:27018,example.com:27019",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "ipv4",
|
||||
"host": "127.0.0.1",
|
||||
"port": null
|
||||
},
|
||||
{
|
||||
"type": "ip_literal",
|
||||
"host": "::1",
|
||||
"port": 27018
|
||||
},
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": 27019
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "UTF-8 hosts",
|
||||
"uri": "mongodb://b\u00fccher.example.com,uml\u00e4ut.example.com/",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "b\u00fccher.example.com",
|
||||
"port": null
|
||||
},
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "uml\u00e4ut.example.com",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,42 +1,25 @@
|
||||
{
|
||||
"tests": [
|
||||
"tests": [
|
||||
{
|
||||
"description": "Option names are normalized to lowercase",
|
||||
"uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=MONGODB-CR",
|
||||
"valid": true,
|
||||
"warning": false,
|
||||
"hosts": [
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin",
|
||||
"password": "secret",
|
||||
"username": "alice"
|
||||
},
|
||||
"description": "Option names are normalized to lowercase",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"authmechanism": "MONGODB-CR"
|
||||
},
|
||||
"uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=MONGODB-CR",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Option key and value (escaped null bytes)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"replicaset": "my\u0000rs"
|
||||
},
|
||||
"uri": "mongodb://example.com/?replicaSet=my%00rs",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"auth": {
|
||||
"username": "alice",
|
||||
"password": "secret",
|
||||
"db": "admin"
|
||||
},
|
||||
"options": {
|
||||
"authmechanism": "MONGODB-CR"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -175,11 +175,11 @@
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.sock",
|
||||
"db": "admin",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets and auth DB resembling a socket (absolute path)",
|
||||
"description": "Multiple Unix domain sockets and auth DB (absolute path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "/tmp/mongodb-27017.sock",
|
||||
@ -193,17 +193,17 @@
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.sock",
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.shoe",
|
||||
"db": "admin",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
"description": "Multiple Unix domain sockets with auth DB resembling a path (absolute path)",
|
||||
"description": "Multiple Unix domain sockets with auth DB (absolute path)",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "/tmp/mongodb-27017.sock",
|
||||
@ -217,7 +217,7 @@
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.shoe",
|
||||
"uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
|
||||
@ -195,7 +195,7 @@
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.sock",
|
||||
"db": "admin",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
@ -213,13 +213,13 @@
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.sock",
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
{
|
||||
"auth": {
|
||||
"db": "admin.shoe",
|
||||
"db": "admin",
|
||||
"password": null,
|
||||
"username": null
|
||||
},
|
||||
@ -237,7 +237,7 @@
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.shoe",
|
||||
"uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin",
|
||||
"valid": true,
|
||||
"warning": false
|
||||
},
|
||||
|
||||
@ -1,68 +1,68 @@
|
||||
{
|
||||
"tests": [
|
||||
"tests": [
|
||||
{
|
||||
"description": "Unrecognized option keys are ignored",
|
||||
"uri": "mongodb://example.com/?foo=bar",
|
||||
"valid": true,
|
||||
"warning": true,
|
||||
"hosts": [
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Unrecognized option keys are ignored",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://example.com/?foo=bar",
|
||||
"valid": true,
|
||||
"warning": true
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Unsupported option values are ignored",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": null,
|
||||
"uri": "mongodb://example.com/?fsync=ifPossible",
|
||||
"valid": true,
|
||||
"warning": true
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Repeated option keys",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"replicaset": "test"
|
||||
},
|
||||
"uri": "mongodb://example.com/?replicaSet=test&replicaSet=test",
|
||||
"valid": true,
|
||||
"warning": true
|
||||
},
|
||||
{
|
||||
"auth": null,
|
||||
"description": "Deprecated (or unknown) options are ignored if replacement exists",
|
||||
"hosts": [
|
||||
{
|
||||
"host": "example.com",
|
||||
"port": null,
|
||||
"type": "hostname"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"wtimeoutms": 10
|
||||
},
|
||||
"uri": "mongodb://example.com/?wtimeout=5&wtimeoutMS=10",
|
||||
"valid": true,
|
||||
"warning": true
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Unsupported option values are ignored",
|
||||
"uri": "mongodb://example.com/?fsync=ifPossible",
|
||||
"valid": true,
|
||||
"warning": true,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"description": "Repeated option keys",
|
||||
"uri": "mongodb://example.com/?replicaSet=test&replicaSet=test",
|
||||
"valid": true,
|
||||
"warning": true,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": {
|
||||
"replicaset": "test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Deprecated (or unknown) options are ignored if replacement exists",
|
||||
"uri": "mongodb://example.com/?wtimeout=5&wtimeoutMS=10",
|
||||
"valid": true,
|
||||
"warning": true,
|
||||
"hosts": [
|
||||
{
|
||||
"type": "hostname",
|
||||
"host": "example.com",
|
||||
"port": null
|
||||
}
|
||||
],
|
||||
"auth": null,
|
||||
"options": {
|
||||
"wtimeoutms": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -331,6 +331,12 @@ class TestURI(unittest.TestCase):
|
||||
parse_uri("mongodb://fred:foobar@localhost/"
|
||||
"test.yield_historical.in"))
|
||||
|
||||
res = copy.deepcopy(orig)
|
||||
res['database'] = 'test'
|
||||
res['collection'] = 'name/with "delimiters'
|
||||
self.assertEqual(
|
||||
res, parse_uri("mongodb://localhost/test.name/with \"delimiters"))
|
||||
|
||||
res = copy.deepcopy(orig)
|
||||
res['options'] = {'readpreference': ReadPreference.SECONDARY.mode}
|
||||
self.assertEqual(res, parse_uri(
|
||||
@ -446,6 +452,30 @@ class TestURI(unittest.TestCase):
|
||||
for key in res['options']:
|
||||
self.assertTrue(isinstance(key, str))
|
||||
|
||||
def test_parse_ssl_paths(self):
|
||||
# Turn off "validate" since these paths don't exist on filesystem.
|
||||
self.assertEqual(
|
||||
{'collection': None,
|
||||
'database': None,
|
||||
'nodelist': [('/MongoDB.sock', None)],
|
||||
'options': {'ssl_certfile': '/a/b'},
|
||||
'password': 'foo/bar',
|
||||
'username': 'jesse'},
|
||||
parse_uri(
|
||||
'mongodb://jesse:foo%2Fbar@%2FMongoDB.sock/?ssl_certfile=/a/b',
|
||||
validate=False))
|
||||
|
||||
self.assertEqual(
|
||||
{'collection': None,
|
||||
'database': None,
|
||||
'nodelist': [('/MongoDB.sock', None)],
|
||||
'options': {'ssl_certfile': 'a/b'},
|
||||
'password': 'foo/bar',
|
||||
'username': 'jesse'},
|
||||
parse_uri(
|
||||
'mongodb://jesse:foo%2Fbar@%2FMongoDB.sock/?ssl_certfile=a/b',
|
||||
validate=False))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user