This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun 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 4b2ea14b13e Fix support for a path in `[api] base_url` (#47840)
4b2ea14b13e is described below
commit 4b2ea14b13e7ea4bd36c778485f63cdeecf69711
Author: Jed Cunningham <[email protected]>
AuthorDate: Mon Mar 17 06:14:49 2025 -0600
Fix support for a path in `[api] base_url` (#47840)
* Fix missing trailing slash when base_url is set via env var
When `[api] base_url` does not have a trailing slash configured, we
update it to have one. However, this was done with `conf.set`, which
does _not_ actually take precedence over the original value if it was
configured with an env var. So, instead, we will set the fixed value in
an env var.
* Fix auth manager support for paths in base_url
* Fix tests
---------
Co-authored-by: pierrejeambrun <[email protected]>
---
airflow/api_fastapi/app.py | 22 +++++++++++-----------
airflow/ui/src/main.tsx | 5 ++++-
tests/operators/test_trigger_dagrun.py | 2 +-
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/airflow/api_fastapi/app.py b/airflow/api_fastapi/app.py
index a96055a4d08..07061ae70b3 100644
--- a/airflow/api_fastapi/app.py
+++ b/airflow/api_fastapi/app.py
@@ -17,6 +17,7 @@
from __future__ import annotations
import logging
+import os
from contextlib import AsyncExitStack, asynccontextmanager
from typing import TYPE_CHECKING
from urllib.parse import urlsplit
@@ -40,8 +41,14 @@ from airflow.exceptions import AirflowConfigException
if TYPE_CHECKING:
from airflow.api_fastapi.auth.managers.base_auth_manager import
BaseAuthManager
-# Define the path in which the potential auth manager fastapi is mounted
-AUTH_MANAGER_FASTAPI_APP_PREFIX = "/auth"
+API_BASE_URL = conf.get("api", "base_url")
+if API_BASE_URL and not API_BASE_URL.endswith("/"):
+ API_BASE_URL += "/"
+ os.environ["AIRFLOW__API__BASE_URL"] = API_BASE_URL
+API_ROOT_PATH = urlsplit(API_BASE_URL).path
+
+# Define the full path on which the potential auth manager fastapi is mounted
+AUTH_MANAGER_FASTAPI_APP_PREFIX = f"{API_ROOT_PATH}auth"
log = logging.getLogger(__name__)
@@ -64,20 +71,13 @@ async def lifespan(app: FastAPI):
def create_app(apps: str = "all") -> FastAPI:
apps_list = apps.split(",") if apps else ["all"]
- fastapi_base_url = conf.get("api", "base_url", fallback="")
- if fastapi_base_url and not fastapi_base_url.endswith("/"):
- fastapi_base_url += "/"
- conf.set("api", "base_url", fastapi_base_url)
-
- root_path = urlsplit(fastapi_base_url).path.removesuffix("/")
-
app = FastAPI(
title="Airflow API",
description="Airflow API. All endpoints located under ``/public`` can
be used safely, are stable and backward compatible. "
"Endpoints located under ``/ui`` are dedicated to the UI and are
subject to breaking change "
"depending on the need of the frontend. Users should not rely on those
but use the public ones instead.",
lifespan=lifespan,
- root_path=root_path,
+ root_path=API_ROOT_PATH.removesuffix("/"),
)
if "execution" in apps_list or "all" in apps_list:
@@ -144,7 +144,7 @@ def init_auth_manager(app: FastAPI | None = None) ->
BaseAuthManager:
am.init()
if app and (auth_manager_fastapi_app := am.get_fastapi_app()):
- app.mount(AUTH_MANAGER_FASTAPI_APP_PREFIX, auth_manager_fastapi_app)
+ app.mount("/auth", auth_manager_fastapi_app)
app.state.auth_manager = am
return am
diff --git a/airflow/ui/src/main.tsx b/airflow/ui/src/main.tsx
index 73aef5517f2..5c6215ab178 100644
--- a/airflow/ui/src/main.tsx
+++ b/airflow/ui/src/main.tsx
@@ -44,7 +44,10 @@ axios.interceptors.response.use(
const params = new URLSearchParams();
params.set("next", globalThis.location.href);
- globalThis.location.replace(`/public/auth/login?${params.toString()}`);
+ const baseUrl =
document.querySelector("head>base")?.getAttribute("href") ?? "";
+ const loginPath = new URL("public/auth/login", baseUrl).pathname;
+
+ globalThis.location.replace(`${loginPath}?${params.toString()}`);
}
return Promise.reject(error);
diff --git a/tests/operators/test_trigger_dagrun.py
b/tests/operators/test_trigger_dagrun.py
index e8464dde2b3..bb6aa842a80 100644
--- a/tests/operators/test_trigger_dagrun.py
+++ b/tests/operators/test_trigger_dagrun.py
@@ -99,7 +99,7 @@ class TestDagRunOperator:
if AIRFLOW_V_3_0_PLUS:
base_url = conf.get_mandatory_value("api", "base_url").lower()
- expected_url =
f"{base_url}/dags/{triggered_dag_run.dag_id}/runs/{triggered_dag_run.run_id}"
+ expected_url =
f"{base_url}dags/{triggered_dag_run.dag_id}/runs/{triggered_dag_run.run_id}"
link = triggering_task.operator_extra_links[0].get_link(
operator=triggering_task, ti_key=triggering_ti.key