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 bd46aa1058e fix(http): Fix HttpHook.url_from_endpoint() lazy 
initialization (#54202)
bd46aa1058e is described below

commit bd46aa1058e19bb22c238954539f6fe4c0953bce
Author: Gary Hsu <[email protected]>
AuthorDate: Tue Aug 19 08:15:34 2025 +0800

    fix(http): Fix HttpHook.url_from_endpoint() lazy initialization (#54202)
    
    * fix(http): fix HttpHook.url_from_endpoint() without get_conn() call
    
    - Add _base_url_initialized flag to track initialization state
    - Implement lazy initialization in url_from_endpoint() method
    - Fix issue where url_from_endpoint() returns incorrect URL when called 
independently
    
    * Add modification on url_from_endpoint to make sure base_url is set
---
 .../http/src/airflow/providers/http/hooks/http.py  |  6 ++++++
 providers/http/tests/unit/http/hooks/test_http.py  | 23 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/providers/http/src/airflow/providers/http/hooks/http.py 
b/providers/http/src/airflow/providers/http/hooks/http.py
index b789688a5d8..b8baa580c41 100644
--- a/providers/http/src/airflow/providers/http/hooks/http.py
+++ b/providers/http/src/airflow/providers/http/hooks/http.py
@@ -135,6 +135,7 @@ class HttpHook(BaseHook):
         self.http_conn_id = http_conn_id
         self.method = method.upper()
         self.base_url: str = ""
+        self._base_url_initialized: bool = False
         self._retry_obj: Callable[..., Any]
         self._auth_type: Any = auth_type
 
@@ -203,6 +204,7 @@ class HttpHook(BaseHook):
         parsed = urlparse(self.base_url)
         if not parsed.scheme:
             raise ValueError(f"Invalid base URL: Missing scheme in 
{self.base_url}")
+        self._base_url_initialized = True
 
     def _configure_session_from_auth(self, session: Session, connection: 
Connection) -> Session:
         session.auth = self._extract_auth(connection)
@@ -383,6 +385,10 @@ class HttpHook(BaseHook):
 
     def url_from_endpoint(self, endpoint: str | None) -> str:
         """Combine base url with endpoint."""
+        # Ensure base_url is set by initializing it if it hasn't been 
initialized yet
+        if not self._base_url_initialized and not self.base_url:
+            connection = self.get_connection(self.http_conn_id)
+            self._set_base_url(connection)
         return _url_from_endpoint(base_url=self.base_url, endpoint=endpoint)
 
     def test_connection(self):
diff --git a/providers/http/tests/unit/http/hooks/test_http.py 
b/providers/http/tests/unit/http/hooks/test_http.py
index 9f60fee30ed..7ebc9754cc8 100644
--- a/providers/http/tests/unit/http/hooks/test_http.py
+++ b/providers/http/tests/unit/http/hooks/test_http.py
@@ -612,8 +612,31 @@ class TestHttpHook:
     def test_url_from_endpoint(self, base_url: str, endpoint: str, 
expected_url: str):
         hook = HttpHook()
         hook.base_url = base_url
+        hook._base_url_initialized = True  # Mark as initialized to prevent 
lazy loading
         assert hook.url_from_endpoint(endpoint) == expected_url
 
+    @mock.patch("airflow.providers.http.hooks.http.HttpHook.get_connection")
+    def test_url_from_endpoint_lazy_initialization(self, mock_get_connection):
+        """Test that url_from_endpoint works without calling get_conn() 
first."""
+        # Mock the connection
+        mock_connection = mock.MagicMock()
+        mock_connection.host = "foo.bar.com"
+        mock_connection.schema = "https"
+        mock_connection.port = None
+        mock_get_connection.return_value = mock_connection
+
+        # Create hook without calling get_conn() and verify that base_url is 
not initialized
+        hook = HttpHook(http_conn_id="test_conn")
+        assert not hook._base_url_initialized
+
+        # This should work now with our fix and verify the URL was constructed 
correctly
+        url = hook.url_from_endpoint("baz/bop")
+        assert url == "https://foo.bar.com/baz/bop";
+
+        # Verify get_connection was called and and verify that base_url is now 
initialized
+        mock_get_connection.assert_called_once_with("test_conn")
+        assert hook._base_url_initialized
+
     def test_custom_adapter(self):
         custom_adapter = HTTPAdapter()
         hook = HttpHook(method="GET", adapter=custom_adapter)

Reply via email to