This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new 4055919095f [v3-3-test] Fix 500 for non-dict JSON bodies on
variable/connection endpoints (#72683) (#72878)
4055919095f is described below
commit 4055919095fdced8f8fe53ab3406defd5f312838
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 10 14:03:59 2026 +0200
[v3-3-test] Fix 500 for non-dict JSON bodies on variable/connection
endpoints (#72683) (#72878)
* Fix 500 for non-dict JSON bodies on variable/connection endpoints
* Simplify the comment
---------
(cherry picked from commit b13414865e100cb181634505f8330d9b5f3baeb2)
Signed-off-by: PoAn Yang <[email protected]>
Co-authored-by: PoAn Yang <[email protected]>
---
.../src/airflow/api_fastapi/logging/decorators.py | 6 ++++--
.../core_api/routes/public/test_connections.py | 22 ++++++++++++++++++++++
.../core_api/routes/public/test_variables.py | 18 ++++++++++++++++++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/airflow-core/src/airflow/api_fastapi/logging/decorators.py
b/airflow-core/src/airflow/api_fastapi/logging/decorators.py
index 71942cafe41..7d785ca0388 100644
--- a/airflow-core/src/airflow/api_fastapi/logging/decorators.py
+++ b/airflow-core/src/airflow/api_fastapi/logging/decorators.py
@@ -160,8 +160,10 @@ def action_logging(event: str | None = None):
masked_body_json = {}
if has_json_body:
- request_body = await request.json()
- if isinstance(request_body, dict):
+ # Non-dict bodies fall through to the endpoint's own 422.
+ parsed_body = await request.json()
+ if isinstance(parsed_body, dict):
+ request_body = parsed_body
masked_body_json = {k: secrets_masker.redact(v, k) for k, v in
request_body.items()}
if event_name in skip_dry_run_events and
request_body.get("dry_run", True):
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py
index a9822e5afaf..84563368126 100644
---
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py
+++
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_connections.py
@@ -368,6 +368,28 @@ class TestPostConnection(TestConnectionEndpoint):
]
}
+ @pytest.mark.parametrize(
+ "body",
+ [
+ [{"connection_id": TEST_CONN_ID, "conn_type": TEST_CONN_TYPE}],
+ '{"connection_id": "a"}',
+ 42,
+ ],
+ ids=["list", "string", "number"],
+ )
+ def test_post_should_respond_422_for_non_dict_json_body(self, test_client,
session, body):
+ """The audit-log dependency reads the body before validation, so a
non-object body still gets a 422."""
+ response = test_client.post("/connections", json=body)
+ assert response.status_code == 422
+ assert response.json()["detail"][0]["loc"] == ["body"]
+ _check_last_log(
+ session,
+ dag_id=None,
+ event="post_connection",
+ logical_date=None,
+ expected_extra={"method": "POST"},
+ )
+
@conf_vars({("core", "multi_team"): "False"})
def test_post_rejects_team_name_when_multi_team_disabled(self,
test_client):
response = test_client.post(
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_variables.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_variables.py
index ec5f915dc43..9a61130e3c1 100644
---
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_variables.py
+++
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_variables.py
@@ -805,6 +805,24 @@ class TestPostVariable(TestVariableEndpoint):
]
}
+ @pytest.mark.parametrize(
+ "body",
+ [[{"key": "new variable key", "value": "new variable value"}],
'{"key": "a"}', 42],
+ ids=["list", "string", "number"],
+ )
+ def test_post_should_respond_422_for_non_dict_json_body(self, test_client,
session, body):
+ """The audit-log dependency reads the body before validation, so a
non-object body still gets a 422."""
+ response = test_client.post("/variables", json=body)
+ assert response.status_code == 422
+ assert response.json()["detail"][0]["loc"] == ["body"]
+ check_last_log(
+ session,
+ dag_id=None,
+ event="post_variable",
+ logical_date=None,
+ expected_extra={"method": "POST"},
+ )
+
@conf_vars({("core", "multi_team"): "False"})
def test_post_rejects_team_name_when_multi_team_disabled(self,
test_client):
body = {