From 90f69f24745dc7b4bd4034e6dd7565312aef30f3 Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Fri, 25 Jul 2025 12:30:29 +0100 Subject: [PATCH 1/4] test: added test for multiple json content-types --- tests/test_json_validation.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_json_validation.py b/tests/test_json_validation.py index aa9b0cf30..a51685450 100644 --- a/tests/test_json_validation.py +++ b/tests/test_json_validation.py @@ -175,3 +175,26 @@ class MyDefaultsJSONBodyValidator(DefaultsJSONRequestBodyValidator): ) assert res.status_code == 200 assert res.json().get("human") + + +def test_multiple_json_content_type(json_validation_spec_dir, spec): + """ensure that defaults applied that modify the body""" + + class MyDefaultsJSONBodyValidator(DefaultsJSONRequestBodyValidator): + pass + + validator_map = {"body": {"application/json": MyDefaultsJSONBodyValidator}} + + app = App(__name__, specification_dir=json_validation_spec_dir) + app.add_api(spec, validate_responses=True, validator_map=validator_map) + app_client = app.test_client() + + res = app_client.post( + "/v1.0/user", + data=json.dumps({"name": "foo"}), + headers={ + "content-type": "application/json", + "Content-Type": "application/json", + }, + ) + assert res.status_code == 415 From 684a8196d4bb7fb1cc22b94c4635f578c1de359a Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Fri, 25 Jul 2025 12:31:14 +0100 Subject: [PATCH 2/4] fix: 415 error if multiple content-type request headers --- connexion/utils.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/connexion/utils.py b/connexion/utils.py index 5458ca85b..d95ca0ec6 100644 --- a/connexion/utils.py +++ b/connexion/utils.py @@ -310,10 +310,8 @@ def extract_content_type( if decoded_key.lower() == "content-type": if isinstance(value, bytes): - content_type = value.decode("latin-1") - else: - content_type = value - break + value = value.decode("latin-1") + content_type = ",".join([content_type, value] if content_type else [value]) return content_type From a06b2d4fe29630e5f02d54f08a88c5c80ad620e8 Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Mon, 28 Jul 2025 19:48:53 +0100 Subject: [PATCH 3/4] test: split json --- tests/test_utils.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index adfa1b115..26a8763bd 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -62,16 +62,29 @@ def test_deep_get_list(): assert utils.deep_get(obj, ["0", "properties", "id"]) == {"type": "string"} -def test_is_json_mimetype(): - assert utils.is_json_mimetype("application/json") - assert utils.is_json_mimetype("application/vnd.com.myEntreprise.v6+json") - assert utils.is_json_mimetype( - "application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0" - ) - assert utils.is_json_mimetype( - "application/vnd.com.myEntreprise.v6+json; charset=UTF-8" - ) - assert not utils.is_json_mimetype("text/html") +@pytest.mark.parametrize( + "mime_type", + [ + "application/json", + "application/vnd.com.myEntreprise.v6+json", + "application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0", + "application/vnd.com.myEntreprise.v6+json; charset=UTF-8", + ], +) +def test_is_json_mimetype_true(mime_type: str): + assert utils.is_json_mimetype(mime_type) + + +@pytest.mark.parametrize( + "mime_type", + [ + "application/json,application/json", + "text/html", + "text/json", + ], +) +def test_is_json_mimetype_false(mime_type: str): + assert not utils.is_json_mimetype(mime_type) def test_sort_routes(): From e46f8443d77bcc99c0fb0e52992217f451b0525b Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Mon, 28 Jul 2025 19:49:15 +0100 Subject: [PATCH 4/4] refactor: limit split of json --- connexion/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connexion/utils.py b/connexion/utils.py index d95ca0ec6..f97567b4d 100644 --- a/connexion/utils.py +++ b/connexion/utils.py @@ -158,7 +158,7 @@ def is_json_mimetype(mimetype): if mimetype is None: return False - maintype, subtype = mimetype.split("/") # type: str, str + maintype, subtype = mimetype.split("/", maxsplit=1) # type: str, str if ";" in subtype: subtype, parameter = subtype.split(";", maxsplit=1) return maintype == "application" and (