Skip to content

Commit a377033

Browse files
PyasmaPyasma
andauthored
Fix/RE:Invalid uri created when extras contains non string elements (#59339)
Co-authored-by: Pyasma <[email protected]>
1 parent 0343763 commit a377033

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

airflow-core/src/airflow/models/connection.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ def _parse_from_uri(self, uri: str):
252252
if self.EXTRA_KEY in query:
253253
self.extra = query[self.EXTRA_KEY]
254254
else:
255+
for key, value in query.items():
256+
try:
257+
query[key] = json.loads(value)
258+
except (JSONDecodeError, TypeError):
259+
self.log.info("Failed parsing the json for key %s", key)
255260
self.extra = json.dumps(query)
256261

257262
@staticmethod
@@ -330,15 +335,22 @@ def get_uri(self) -> str:
330335
uri += host_block
331336

332337
if self.extra:
338+
extra_dict = self.extra_dejson
339+
can_flatten = True
340+
for value in extra_dict.values():
341+
if not isinstance(value, str):
342+
can_flatten = False
343+
break
344+
333345
try:
334-
query: str | None = urlencode(self.extra_dejson)
346+
query: str | None = urlencode(extra_dict)
335347
except TypeError:
336348
query = None
337-
if query and self.extra_dejson == dict(parse_qsl(query, keep_blank_values=True)):
349+
350+
if can_flatten and query and extra_dict == dict(parse_qsl(query, keep_blank_values=True)):
338351
uri += ("?" if self.schema else "/?") + query
339352
else:
340353
uri += ("?" if self.schema else "/?") + urlencode({self.EXTRA_KEY: self.extra})
341-
342354
return uri
343355

344356
def get_password(self) -> str | None:

airflow-core/tests/unit/models/test_connection.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,28 @@ def clear_fernet_cache(self):
148148
None,
149149
r"Invalid connection string: type://user:pass@protocol://host:port?param=value.",
150150
),
151+
(
152+
"type://host?int_param=123&bool_param=true&float_param=1.5&str_param=some_str",
153+
"type",
154+
"host",
155+
None,
156+
None,
157+
None,
158+
"",
159+
{"int_param": 123, "bool_param": True, "float_param": 1.5, "str_param": "some_str"},
160+
None,
161+
),
162+
(
163+
"type://host?__extra__=%7B%22foo%22%3A+%22bar%22%7D",
164+
"type",
165+
"host",
166+
None,
167+
None,
168+
None,
169+
"",
170+
{"foo": "bar"},
171+
None,
172+
),
151173
],
152174
)
153175
def test_parse_from_uri(
@@ -212,6 +234,14 @@ def test_parse_from_uri(
212234
),
213235
"type://protocol://user:pass@host:100/schema?param1=val1&param2=val2",
214236
),
237+
(
238+
Connection(
239+
conn_type="type",
240+
host="host",
241+
extra={"bool_param": True, "int_param": 123, "float_param": 1.5, "list_param": [1, 2]},
242+
),
243+
"type://host/?__extra__=%7B%22bool_param%22%3A+true%2C+%22int_param%22%3A+123%2C+%22float_param%22%3A+1.5%2C+%22list_param%22%3A+%5B1%2C+2%5D%7D",
244+
),
215245
],
216246
)
217247
def test_get_uri(self, connection, expected_uri):

0 commit comments

Comments
 (0)