fix: Keep query params embedded in OpenAPI paths when using httpx

The migration from requests to httpx in v1.24.0 broke ApplicationIntegrationToolset because httpx replaces the URL query string when a `params` dict is passed, even if empty. The requests library merged them instead. This extracts any query parameters embedded in the URL path into the explicit params dict before passing to httpx.

Close #4555

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874112143
This commit is contained in:
George Weale
2026-02-23 09:29:22 -08:00
committed by Copybara-Service
parent 87fcd77caa
commit ffbcc0a626
2 changed files with 167 additions and 0 deletions
@@ -24,6 +24,9 @@ from typing import Literal
from typing import Optional
from typing import Tuple
from typing import Union
from urllib.parse import parse_qs
from urllib.parse import urlparse
from urllib.parse import urlunparse
from fastapi.openapi.models import Operation
from fastapi.openapi.models import Schema
@@ -375,6 +378,14 @@ class RestApiTool(BaseTool):
base_url = base_url[:-1] if base_url.endswith("/") else base_url
url = f"{base_url}{self.endpoint.path.format(**path_params)}"
# Move query params embedded in the path into query_params, since httpx
# replaces (rather than merges) the URL query string when `params` is set.
parsed_url = urlparse(url)
if parsed_url.query or parsed_url.fragment:
for key, values in parse_qs(parsed_url.query).items():
query_params.setdefault(key, values[0] if len(values) == 1 else values)
url = urlunparse(parsed_url._replace(query="", fragment=""))
# Construct body
body_kwargs: Dict[str, Any] = {}
request_body = self.operation.requestBody