From 7fa57e518cc1e80d37a8bac541501392076eb3eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:01:57 +0000 Subject: [PATCH 1/5] Initial plan From fcaf7bc398a681a46dd53464bc44cf60384be462 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:08:17 +0000 Subject: [PATCH 2/5] Fix format_url to preserve trailing slash when url_template is query-string only Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com> --- sdk/core/azure-core/CHANGELOG.md | 2 ++ .../azure-core/azure/core/pipeline/transport/_base.py | 2 +- sdk/core/azure-core/tests/test_pipeline.py | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index 2fb610e6bb64..1f9795415dcc 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Fixed `PipelineClient.format_url` to preserve trailing slash in the base URL when the URL template is a query-string only (e.g. `?key=value`). #40426 + ### Other Changes ## 1.38.2 (2026-02-18) diff --git a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py index 6e33aa77df73..91b43e9bb70f 100644 --- a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py +++ b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py @@ -663,7 +663,7 @@ def format_url(self, url_template: str, **kwargs: Any) -> str: parsed = urlparse(url) if not parsed.scheme or not parsed.netloc: try: - base = self._base_url.format(**kwargs).rstrip("/") + base = self._base_url.format(**kwargs) except KeyError as key: err_msg = "The value provided for the url part {} was incorrect, and resulted in an invalid url" raise ValueError(err_msg.format(key.args[0])) from key diff --git a/sdk/core/azure-core/tests/test_pipeline.py b/sdk/core/azure-core/tests/test_pipeline.py index 5612b8b2a45f..99ffe6950951 100644 --- a/sdk/core/azure-core/tests/test_pipeline.py +++ b/sdk/core/azure-core/tests/test_pipeline.py @@ -225,6 +225,14 @@ def test_format_url_query_strings(): assert formatted == "https://foo.core.windows.net/Tables?a=X&c=Y" +def test_format_url_trailing_slash_preserved_with_query_only(): + # Test that trailing slash in base URL is preserved when url_template is query-string only + # https://github.com/Azure/azure-sdk-for-python/issues/XXXXX + client = PipelineClientBase("{url}") + formatted = client.format_url("?versionid=2026-02-25", url="https://storage.blob.core.windows.net/sample//a/a/") + assert formatted == "https://storage.blob.core.windows.net/sample//a/a/?versionid=2026-02-25" + + def test_format_url_from_http_request(): client = PipelineClientBase("https://foo.core.windows.net") From 5d8bb45688aec7ba27f8089d0c8293fb635600a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 21:55:42 +0000 Subject: [PATCH 3/5] Refine format_url fix: only preserve trailing slash for query-string-only stubs Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com> --- sdk/core/azure-core/azure/core/pipeline/transport/_base.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py index 91b43e9bb70f..dc7c677fba80 100644 --- a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py +++ b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py @@ -668,6 +668,11 @@ def format_url(self, url_template: str, **kwargs: Any) -> str: err_msg = "The value provided for the url part {} was incorrect, and resulted in an invalid url" raise ValueError(err_msg.format(key.args[0])) from key + # Only strip trailing slash from base when stub has a path component. + # For query-string-only stubs (e.g. "?key=val"), preserve any trailing + # slash so it appears before the query string in the final URL. + if url.split("?", 1)[0]: + base = base.rstrip("/") url = _urljoin(base, url) else: url = self._base_url.format(**kwargs) From 7cccfe9fc7e5b5c5420e7c8bb9a2f3c1e9950966 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:34:54 +0000 Subject: [PATCH 4/5] Remove conditional rstrip from format_url (lines 671-675) Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com> --- sdk/core/azure-core/azure/core/pipeline/transport/_base.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py index dc7c677fba80..91b43e9bb70f 100644 --- a/sdk/core/azure-core/azure/core/pipeline/transport/_base.py +++ b/sdk/core/azure-core/azure/core/pipeline/transport/_base.py @@ -668,11 +668,6 @@ def format_url(self, url_template: str, **kwargs: Any) -> str: err_msg = "The value provided for the url part {} was incorrect, and resulted in an invalid url" raise ValueError(err_msg.format(key.args[0])) from key - # Only strip trailing slash from base when stub has a path component. - # For query-string-only stubs (e.g. "?key=val"), preserve any trailing - # slash so it appears before the query string in the final URL. - if url.split("?", 1)[0]: - base = base.rstrip("/") url = _urljoin(base, url) else: url = self._base_url.format(**kwargs) From 3d3886cc22bb14259dcf39b79c0f1f258fc1658b Mon Sep 17 00:00:00 2001 From: Paul Van Eck Date: Thu, 26 Feb 2026 11:27:37 -0800 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- sdk/core/azure-core/CHANGELOG.md | 2 +- sdk/core/azure-core/tests/test_pipeline.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index 1f9795415dcc..740706311091 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -8,7 +8,7 @@ ### Bugs Fixed -- Fixed `PipelineClient.format_url` to preserve trailing slash in the base URL when the URL template is a query-string only (e.g. `?key=value`). #40426 +- Fixed `PipelineClient.format_url` to preserve trailing slash in the base URL when the URL template is query-string-only (e.g., `?key=value`). #45365 ### Other Changes diff --git a/sdk/core/azure-core/tests/test_pipeline.py b/sdk/core/azure-core/tests/test_pipeline.py index 99ffe6950951..af6ca1a1a0ea 100644 --- a/sdk/core/azure-core/tests/test_pipeline.py +++ b/sdk/core/azure-core/tests/test_pipeline.py @@ -227,7 +227,7 @@ def test_format_url_query_strings(): def test_format_url_trailing_slash_preserved_with_query_only(): # Test that trailing slash in base URL is preserved when url_template is query-string only - # https://github.com/Azure/azure-sdk-for-python/issues/XXXXX + # https://github.com/Azure/azure-sdk-for-python/issues/45365 client = PipelineClientBase("{url}") formatted = client.format_url("?versionid=2026-02-25", url="https://storage.blob.core.windows.net/sample//a/a/") assert formatted == "https://storage.blob.core.windows.net/sample//a/a/?versionid=2026-02-25"