This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch v2-10-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v2-10-test by this push:
new 453ade4f8b5 [v2-10-test] Allow fetching XCom with forward slash from
the API and escape it in the UI (#45134) (#45137)
453ade4f8b5 is described below
commit 453ade4f8b5f0074d070f8a0a6a5bdc0ba9dcedb
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Dec 21 19:10:06 2024 +0100
[v2-10-test] Allow fetching XCom with forward slash from the API and escape
it in the UI (#45134) (#45137)
(cherry picked from commit 9316ed6df85234ba7f36437152329d9b1a27424d)
Co-authored-by: Shahar Epstein <[email protected]>
---
airflow/api_connexion/openapi/v1.yaml | 1 +
airflow/www/static/js/api/useTaskXcom.ts | 18 +++++++++--------
newsfragments/45134.bugfix.rst | 1 +
.../api_connexion/endpoints/test_xcom_endpoint.py | 23 ++++++++++++++++++----
4 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/airflow/api_connexion/openapi/v1.yaml
b/airflow/api_connexion/openapi/v1.yaml
index 55a0b60c74d..180f854c02f 100644
--- a/airflow/api_connexion/openapi/v1.yaml
+++ b/airflow/api_connexion/openapi/v1.yaml
@@ -5733,6 +5733,7 @@ components:
name: xcom_key
schema:
type: string
+ format: path
required: true
description: The XCom key.
diff --git a/airflow/www/static/js/api/useTaskXcom.ts
b/airflow/www/static/js/api/useTaskXcom.ts
index 403233285eb..d8758e60b90 100644
--- a/airflow/www/static/js/api/useTaskXcom.ts
+++ b/airflow/www/static/js/api/useTaskXcom.ts
@@ -57,14 +57,16 @@ export const useTaskXcomEntry = ({
}: TaskXcomProps) =>
useQuery(
["taskXcom", dagId, dagRunId, taskId, mapIndex, xcomKey, tryNumber],
- () =>
- axios.get<AxiosResponse, API.XCom>(
- getMetaValue("task_xcom_entry_api")
- .replace("_DAG_RUN_ID_", dagRunId)
- .replace("_TASK_ID_", taskId)
- .replace("_XCOM_KEY_", xcomKey),
- { params: { map_index: mapIndex, stringify: false } }
- ),
+ () => {
+ const taskXcomEntryApiUrl = getMetaValue("task_xcom_entry_api")
+ .replace("_DAG_RUN_ID_", dagRunId)
+ .replace("_TASK_ID_", taskId)
+ .replace("_XCOM_KEY_", encodeURIComponent(xcomKey));
+
+ return axios.get<AxiosResponse, API.XCom>(taskXcomEntryApiUrl, {
+ params: { map_index: mapIndex, stringify: false },
+ });
+ },
{
enabled: !!xcomKey,
}
diff --git a/newsfragments/45134.bugfix.rst b/newsfragments/45134.bugfix.rst
new file mode 100644
index 00000000000..09aaae23a34
--- /dev/null
+++ b/newsfragments/45134.bugfix.rst
@@ -0,0 +1 @@
+(v2 API & UI) Allow fetching XCom with forward slash from the API and escape
it in the UI
diff --git a/tests/api_connexion/endpoints/test_xcom_endpoint.py
b/tests/api_connexion/endpoints/test_xcom_endpoint.py
index 7a51714c5b2..101c2a65f8e 100644
--- a/tests/api_connexion/endpoints/test_xcom_endpoint.py
+++ b/tests/api_connexion/endpoints/test_xcom_endpoint.py
@@ -272,52 +272,67 @@ class TestGetXComEntry(TestXComEndpoint):
)
@pytest.mark.parametrize(
- "allowed, query, expected_status_or_value",
+ "allowed, query, expected_status_or_value, key",
[
pytest.param(
True,
"?deserialize=true",
"real deserialized TEST_VALUE",
+ "key",
id="true",
),
pytest.param(
False,
"?deserialize=true",
400,
+ "key",
id="disallowed",
),
pytest.param(
True,
"?deserialize=false",
"orm deserialized TEST_VALUE",
+ "key",
id="false-irrelevant",
),
pytest.param(
False,
"?deserialize=false",
"orm deserialized TEST_VALUE",
+ "key",
id="false",
),
pytest.param(
True,
"",
"orm deserialized TEST_VALUE",
+ "key",
id="default-irrelevant",
),
pytest.param(
False,
"",
"orm deserialized TEST_VALUE",
+ "key",
id="default",
),
+ pytest.param(
+ False,
+ "",
+ "orm deserialized TEST_VALUE",
+ "key/with/slashes",
+ id="key-with-slashes",
+ ),
],
)
@conf_vars({("core", "xcom_backend"):
"tests.api_connexion.endpoints.test_xcom_endpoint.CustomXCom"})
- def test_custom_xcom_deserialize(self, allowed: bool, query: str,
expected_status_or_value: int | str):
+ def test_custom_xcom_deserialize(
+ self, allowed: bool, query: str, expected_status_or_value: int | str,
key: str
+ ):
XCom = resolve_xcom_backend()
- self._create_xcom_entry("dag", "run", utcnow(), "task", "key",
backend=XCom)
+ self._create_xcom_entry("dag", "run", utcnow(), "task", key,
backend=XCom)
- url =
f"/api/v1/dags/dag/dagRuns/run/taskInstances/task/xcomEntries/key{query}"
+ url =
f"/api/v1/dags/dag/dagRuns/run/taskInstances/task/xcomEntries/{key}{query}"
with mock.patch("airflow.api_connexion.endpoints.xcom_endpoint.XCom",
XCom):
with conf_vars({("api", "enable_xcom_deserialize_support"):
str(allowed)}):
response = self.client.get(url,
environ_overrides={"REMOTE_USER": "test"})