Skip to content

Commit d8ddc9b

Browse files
committed
BUG24948344 and BUG24948458: Fix parsing unix socket from the connection URI
This patch fixes parsing of socket from the Connection URI. The following formats are tested and work correctly with this patch: mysqlx://user:pass@(/path/to/sock)/schema mysqlx://user:pass@/path%2Fto%2Fsock/schema mysqlx://user:pass@.%2Fpath%2Fto%2Fsock/schema mysqlx://user:pass@..%2Fpath%2Fto%2Fsock/schema Tests have been added for regression.
1 parent 956916b commit d8ddc9b

File tree

2 files changed

+52
-23
lines changed

2 files changed

+52
-23
lines changed

lib/mysqlx/__init__.py

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -100,36 +100,31 @@ def _parse_connection_uri(uri):
100100
Returns a dict with parsed values of credentials and address of the
101101
MySQL server/farm.
102102
"""
103+
settings = {"schema": ""}
103104
uri = "{0}{1}".format("" if uri.startswith("mysqlx://")
104105
else "mysqlx://", uri)
105-
parsed = urlparse(uri)
106-
if parsed.username is None or parsed.password is None:
106+
scheme, temp = uri.split("://", 1)
107+
userinfo, temp = temp.partition("@")[::2]
108+
host, query_str = temp.partition("?")[::2]
109+
110+
pos = host.rfind("/")
111+
if host[pos:].find(")") is -1 and pos > 0:
112+
host, settings["schema"] = host.rsplit("/", 1)
113+
host = host.strip("()")
114+
115+
if not host or not userinfo or ":" not in userinfo:
107116
raise InterfaceError("Malformed URI '{0}'".format(uri))
117+
settings["user"], settings["password"] = userinfo.split(":", 1)
108118

109-
settings = {
110-
"user": parsed.username,
111-
"password": parsed.password
112-
}
113-
114-
delimiter = ")" if ")" in parsed.path else "/"
115-
socket, schema = parsed.path.rpartition(delimiter)[::2]
116-
settings["schema"] = schema.lstrip("/")
117-
if socket and parsed.hostname:
118-
socket = "{0}{1}".format(parsed.hostname, socket).strip("()")
119-
120-
if socket.startswith(("/", ".", "..")):
121-
settings["socket"] = unquote(socket).encode("utf-8")
122-
return settings
123-
elif socket.startswith("\\."):
119+
if host.startswith(("/", "..", ".")):
120+
settings["socket"] = unquote(host).encode("utf-8")
121+
elif host.startswith("\\."):
124122
raise InterfaceError("Windows Pipe is not supported.")
125-
elif parsed.hostname is None:
126-
raise InterfaceError("Malformed URI '{0}'".format(uri))
123+
else:
124+
settings.update(_parse_address_list(host))
127125

128-
query = dict(parse_qsl(parsed.query, True))
129-
for opt, val in query.items():
126+
for opt, val in dict(parse_qsl(query_str, True)).items():
130127
settings[opt] = unquote(val.strip("()")) or True
131-
132-
settings.update(_parse_address_list(parsed.netloc.split("@")[-1]))
133128
return settings
134129

135130
def _validate_settings(settings):

tests/test_mysqlx_connection.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,40 @@ def test_mysqlx_socket(self):
173173

174174
session = mysqlx.get_session(uri)
175175

176+
conn = mysqlx._get_connection_settings("root:@(/path/to/sock)")
177+
self.assertEqual("/path/to/sock", conn["socket"])
178+
self.assertEqual("", conn["schema"])
179+
180+
conn = mysqlx._get_connection_settings("root:@(/path/to/sock)/schema")
181+
self.assertEqual("/path/to/sock", conn["socket"])
182+
self.assertEqual("schema", conn["schema"])
183+
184+
conn = mysqlx._get_connection_settings("root:@/path%2Fto%2Fsock")
185+
self.assertEqual("/path/to/sock", conn["socket"])
186+
self.assertEqual("", conn["schema"])
187+
188+
conn = mysqlx._get_connection_settings("root:@/path%2Fto%2Fsock/schema")
189+
self.assertEqual("/path/to/sock", conn["socket"])
190+
self.assertEqual("schema", conn["schema"])
191+
192+
conn = mysqlx._get_connection_settings("root:@.%2Fpath%2Fto%2Fsock")
193+
self.assertEqual("./path/to/sock", conn["socket"])
194+
self.assertEqual("", conn["schema"])
195+
196+
conn = mysqlx._get_connection_settings("root:@.%2Fpath%2Fto%2Fsock"
197+
"/schema")
198+
self.assertEqual("./path/to/sock", conn["socket"])
199+
self.assertEqual("schema", conn["schema"])
200+
201+
conn = mysqlx._get_connection_settings("root:@..%2Fpath%2Fto%2Fsock")
202+
self.assertEqual("../path/to/sock", conn["socket"])
203+
self.assertEqual("", conn["schema"])
204+
205+
conn = mysqlx._get_connection_settings("root:@..%2Fpath%2Fto%2Fsock"
206+
"/schema")
207+
self.assertEqual("../path/to/sock", conn["socket"])
208+
self.assertEqual("schema", conn["schema"])
209+
176210

177211
def test_connection_uri(self):
178212
uri = ("mysqlx://{user}:{password}@{host}:{port}/{schema}"

0 commit comments

Comments
 (0)