This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 8d4f6592b34 Align key/id path validation for variables and connections 
(#63897)
8d4f6592b34 is described below

commit 8d4f6592b34e6c7e9057be8983e19ea3e58dcff9
Author: Henry Chen <[email protected]>
AuthorDate: Fri Mar 20 19:46:19 2026 +0800

    Align key/id path validation for variables and connections (#63897)
---
 .../execution_api/routes/connections.py            |  5 +++--
 .../api_fastapi/execution_api/routes/variables.py  | 23 ++++++++++------------
 .../execution_api/versions/head/test_variables.py  | 16 ++++++++-------
 3 files changed, 22 insertions(+), 22 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/execution_api/routes/connections.py 
b/airflow-core/src/airflow/api_fastapi/execution_api/routes/connections.py
index a7bb9959c6d..9182570a01e 100644
--- a/airflow-core/src/airflow/api_fastapi/execution_api/routes/connections.py
+++ b/airflow-core/src/airflow/api_fastapi/execution_api/routes/connections.py
@@ -29,7 +29,7 @@ from airflow.models.connection import Connection
 
 
 async def has_connection_access(
-    connection_id: str = Path(),
+    connection_id: Annotated[str, Path(min_length=1)],
     token=CurrentTIToken,
 ) -> bool:
     """Check if the task has access to the connection."""
@@ -59,7 +59,8 @@ log = logging.getLogger(__name__)
     },
 )
 def get_connection(
-    connection_id: str, team_name: Annotated[str | None, 
Depends(get_team_name_dep)]
+    connection_id: Annotated[str, Path(min_length=1)],
+    team_name: Annotated[str | None, Depends(get_team_name_dep)],
 ) -> ConnectionResponse:
     """Get an Airflow connection."""
     try:
diff --git 
a/airflow-core/src/airflow/api_fastapi/execution_api/routes/variables.py 
b/airflow-core/src/airflow/api_fastapi/execution_api/routes/variables.py
index 1e2e2058932..a139ce0c011 100644
--- a/airflow-core/src/airflow/api_fastapi/execution_api/routes/variables.py
+++ b/airflow-core/src/airflow/api_fastapi/execution_api/routes/variables.py
@@ -32,7 +32,7 @@ from airflow.models.variable import Variable
 
 async def has_variable_access(
     request: Request,
-    variable_key: str = Path(),
+    variable_key: Annotated[str, Path(min_length=1)],
     token=CurrentTIToken,
 ):
     """Check if the task has access to the variable."""
@@ -63,12 +63,10 @@ log = logging.getLogger(__name__)
     },
 )
 def get_variable(
-    variable_key: str, team_name: Annotated[str | None, 
Depends(get_team_name_dep)]
+    variable_key: Annotated[str, Path(min_length=1)],
+    team_name: Annotated[str | None, Depends(get_team_name_dep)],
 ) -> VariableResponse:
     """Get an Airflow Variable."""
-    if not variable_key:
-        raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Not Found")
-
     try:
         variable_value = Variable.get(variable_key, team_name=team_name)
     except KeyError:
@@ -92,12 +90,11 @@ def get_variable(
     },
 )
 def put_variable(
-    variable_key: str, body: VariablePostBody, team_name: Annotated[str | 
None, Depends(get_team_name_dep)]
+    variable_key: Annotated[str, Path(min_length=1)],
+    body: VariablePostBody,
+    team_name: Annotated[str | None, Depends(get_team_name_dep)],
 ):
     """Set an Airflow Variable."""
-    if not variable_key:
-        raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Not Found")
-
     Variable.set(key=variable_key, value=body.value, 
description=body.description, team_name=team_name)
     return {"message": "Variable successfully set"}
 
@@ -110,9 +107,9 @@ def put_variable(
         status.HTTP_403_FORBIDDEN: {"description": "Task does not have access 
to the variable"},
     },
 )
-def delete_variable(variable_key: str, team_name: Annotated[str | None, 
Depends(get_team_name_dep)]):
+def delete_variable(
+    variable_key: Annotated[str, Path(min_length=1)],
+    team_name: Annotated[str | None, Depends(get_team_name_dep)],
+):
     """Delete an Airflow Variable."""
-    if not variable_key:
-        raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Not Found")
-
     Variable.delete(key=variable_key, team_name=team_name)
diff --git 
a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_variables.py
 
b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_variables.py
index 93cd8ca672e..fe761163635 100644
--- 
a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_variables.py
+++ 
b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_variables.py
@@ -159,20 +159,22 @@ class TestPutVariable:
             assert var_from_db.description == payload["description"]
 
     @pytest.mark.parametrize(
-        ("key", "status_code", "payload"),
+        ("key", "payload", "error_type"),
         [
-            pytest.param("", 404, {"value": "{}", "description": 
"description"}, id="missing-key"),
-            pytest.param("var_create", 422, {"description": "description"}, 
id="missing-value"),
+            pytest.param(
+                "", {"value": "{}", "description": "description"}, 
"string_too_short", id="missing-key"
+            ),
+            pytest.param("var_create", {"description": "description"}, 
"missing", id="missing-value"),
         ],
     )
-    def test_variable_missing_mandatory_fields(self, client, key, status_code, 
payload, session):
+    def test_variable_missing_mandatory_fields(self, client, key, payload, 
error_type, session):
         response = client.put(
             f"/execution/variables/{key}",
             json=payload,
         )
-        assert response.status_code == status_code
-        if response.status_code == 422:
-            assert response.json()["detail"][0]["type"] == "missing"
+        assert response.status_code == 422
+        assert response.json()["detail"][0]["type"] == error_type
+        if error_type == "missing":
             assert response.json()["detail"][0]["msg"] == "Field required"
 
     @pytest.mark.parametrize(

Reply via email to