Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions providers/http/src/airflow/providers/http/hooks/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def __init__(
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

Expand Down Expand Up @@ -203,6 +204,7 @@ def _set_base_url(self, connection) -> None:
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)
Expand Down Expand Up @@ -383,6 +385,10 @@ def run_with_advanced_retry(self, _retry_args: dict[Any, Any], *args: Any, **kwa

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):
Expand Down
23 changes: 23 additions & 0 deletions providers/http/tests/unit/http/hooks/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,8 +612,31 @@ def test_keep_alive_disabled(self):
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)
Expand Down
Loading