@@ -202,6 +202,18 @@ async def _send_capped_async(client: httpx2.AsyncClient, request: httpx2.Request
202202 await flow .aclose ()
203203
204204
205+ @contextlib .asynccontextmanager
206+ async def _stream_async (
207+ client : httpx2 .AsyncClient , method : str , url : httpx2 .URL | str , kwargs : dict [str , typing .Any ]
208+ ) -> AsyncIterator [httpx2 .Response ]:
209+ """Mirror of `httpx2.AsyncClient.stream` that builds via `_build_request`."""
210+ response = await client .send (_build_request (client , method , url , kwargs ), stream = True )
211+ try :
212+ yield response
213+ finally :
214+ await response .aclose ()
215+
216+
205217@contextlib .asynccontextmanager
206218async def _stream_capped_async (
207219 client : httpx2 .AsyncClient ,
@@ -211,7 +223,7 @@ async def _stream_capped_async(
211223 cap : int ,
212224) -> AsyncIterator [httpx2 .Response ]:
213225 """Async mirror of `httpx2.AsyncClient.stream` that sends via `_send_capped_async`."""
214- response = await _send_capped_async (client , client . build_request ( method , url , ** kwargs ), cap )
226+ response = await _send_capped_async (client , _build_request ( client , method , url , kwargs ), cap )
215227 try :
216228 yield response
217229 finally :
@@ -271,6 +283,18 @@ def _send_capped(client: httpx2.Client, request: httpx2.Request, cap: int) -> ht
271283 flow .close ()
272284
273285
286+ @contextlib .contextmanager
287+ def _stream (
288+ client : httpx2 .Client , method : str , url : httpx2 .URL | str , kwargs : dict [str , typing .Any ]
289+ ) -> Iterator [httpx2 .Response ]:
290+ """Sync mirror of `_stream_async`."""
291+ response = client .send (_build_request (client , method , url , kwargs ), stream = True )
292+ try :
293+ yield response
294+ finally :
295+ response .close ()
296+
297+
274298@contextlib .contextmanager
275299def _stream_capped (
276300 client : httpx2 .Client ,
@@ -280,7 +304,7 @@ def _stream_capped(
280304 cap : int ,
281305) -> Iterator [httpx2 .Response ]:
282306 """Sync mirror of `_stream_capped_async`."""
283- response = _send_capped (client , client . build_request ( method , url , ** kwargs ), cap )
307+ response = _send_capped (client , _build_request ( client , method , url , kwargs ), cap )
284308 try :
285309 yield response
286310 finally :
@@ -322,14 +346,17 @@ def _assemble_request_kwargs( # noqa: PLR0913 — 9 per-request kwargs from htt
322346 return kwargs
323347
324348
325- def _merge_url_query (
326- url : httpx2 .URL | str , params : typing . Any | None , client_params : httpx2 . QueryParams
327- ) -> tuple [ httpx2 .URL | str , typing . Any | None ] :
328- """Fold the URL's own query into ` params`; httpx2 would otherwise replace it ."""
349+ def _build_request (
350+ client : httpx2 .Client | httpx2 . AsyncClient , method : str , url : httpx2 . URL | str , kwargs : dict [ str , typing . Any ]
351+ ) -> httpx2 .Request :
352+ """Build via `client`, keeping the URL's own query bytes ahead of any params, which httpx2 would replace."""
329353 parsed = httpx2 .URL (url )
330- if not parsed .query or (params is None and not client_params ):
331- return url , params
332- return parsed .copy_with (query = None ), parsed .params .merge (params )
354+ if not parsed .query :
355+ return client .build_request (method , url , ** kwargs )
356+ request = client .build_request (method , parsed .copy_with (query = None ), ** kwargs )
357+ built_query = request .url .query
358+ request .url = request .url .copy_with (query = parsed .query + b"&" + built_query if built_query else parsed .query )
359+ return request
333360
334361
335362class AsyncClient :
@@ -430,8 +457,7 @@ async def send_with_response(
430457
431458 def build_request (self , method : str , url : str , ** kwargs : typing .Any ) -> httpx2 .Request :
432459 """Delegate request construction to the wrapped httpx2.AsyncClient, keeping the URL's own query."""
433- merged_url , params = _merge_url_query (url , kwargs .pop ("params" , None ), self ._httpx2_client .params )
434- return self ._httpx2_client .build_request (method , merged_url , params = params , ** kwargs )
460+ return _build_request (self ._httpx2_client , method , url , kwargs )
435461
436462 def _prepare_request ( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwargs-forwarding complexity is structural
437463 self ,
@@ -448,7 +474,6 @@ def _prepare_request( # noqa: PLR0913 — mirrors httpx2 per-method signatures;
448474 data : typing .Any | None = None ,
449475 files : typing .Any | None = None ,
450476 ) -> httpx2 .Request :
451- merged_url , params = _merge_url_query (url , params , self ._httpx2_client .params )
452477 kwargs = _assemble_request_kwargs (
453478 params = params ,
454479 headers = headers ,
@@ -460,7 +485,7 @@ def _prepare_request( # noqa: PLR0913 — mirrors httpx2 per-method signatures;
460485 data = data ,
461486 files = files ,
462487 )
463- request = self ._httpx2_client . build_request ( method , merged_url , ** kwargs )
488+ request = _build_request ( self ._httpx2_client , method , url , kwargs )
464489 if _is_streaming_body_async (content ) or _is_streaming_body_async (data ) or _is_streaming_body_async (files ):
465490 request .extensions [STREAMING_BODY_MARKER ] = True
466491 return request
@@ -1216,7 +1241,6 @@ async def stream( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwa
12161241 Maps httpx2 exceptions raised during the request OR body consumption to
12171242 httpware exceptions via _httpx2_exception_mapper.
12181243 """
1219- merged_url , params = _merge_url_query (url , params , self ._httpx2_client .params )
12201244 kwargs = _assemble_request_kwargs (
12211245 params = params ,
12221246 headers = headers ,
@@ -1231,9 +1255,9 @@ async def stream( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwa
12311255
12321256 cap = self ._max_response_body_bytes
12331257 opened = (
1234- self ._httpx2_client . stream ( method , merged_url , ** kwargs )
1258+ _stream_async ( self ._httpx2_client , method , url , kwargs )
12351259 if cap is None
1236- else _stream_capped_async (self ._httpx2_client , method , merged_url , kwargs , cap )
1260+ else _stream_capped_async (self ._httpx2_client , method , url , kwargs , cap )
12371261 )
12381262 async with _httpx2_exception_mapper (), opened as response :
12391263 if HTTPStatus .BAD_REQUEST <= response .status_code < 600 : # noqa: PLR2004 — 600 is the synthetic upper bound for 5xx
@@ -1392,8 +1416,7 @@ def send_with_response(
13921416
13931417 def build_request (self , method : str , url : str , ** kwargs : typing .Any ) -> httpx2 .Request :
13941418 """Delegate request construction to the wrapped httpx2.Client, keeping the URL's own query."""
1395- merged_url , params = _merge_url_query (url , kwargs .pop ("params" , None ), self ._httpx2_client .params )
1396- return self ._httpx2_client .build_request (method , merged_url , params = params , ** kwargs )
1419+ return _build_request (self ._httpx2_client , method , url , kwargs )
13971420
13981421 def _prepare_request ( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwargs-forwarding complexity is structural
13991422 self ,
@@ -1410,7 +1433,6 @@ def _prepare_request( # noqa: PLR0913 — mirrors httpx2 per-method signatures;
14101433 data : typing .Any | None = None ,
14111434 files : typing .Any | None = None ,
14121435 ) -> httpx2 .Request :
1413- merged_url , params = _merge_url_query (url , params , self ._httpx2_client .params )
14141436 kwargs = _assemble_request_kwargs (
14151437 params = params ,
14161438 headers = headers ,
@@ -1422,7 +1444,7 @@ def _prepare_request( # noqa: PLR0913 — mirrors httpx2 per-method signatures;
14221444 data = data ,
14231445 files = files ,
14241446 )
1425- request = self ._httpx2_client . build_request ( method , merged_url , ** kwargs )
1447+ request = _build_request ( self ._httpx2_client , method , url , kwargs )
14261448 if _is_streaming_body_sync (content ) or _is_streaming_body_sync (data ) or _is_streaming_body_sync (files ):
14271449 request .extensions [STREAMING_BODY_MARKER ] = True
14281450 return request
@@ -2175,7 +2197,6 @@ def stream( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwargs-fo
21752197 Maps httpx2 exceptions raised during the request OR body consumption to
21762198 httpware exceptions via _httpx2_exception_mapper_sync.
21772199 """
2178- merged_url , params = _merge_url_query (url , params , self ._httpx2_client .params )
21792200 kwargs = _assemble_request_kwargs (
21802201 params = params ,
21812202 headers = headers ,
@@ -2190,9 +2211,9 @@ def stream( # noqa: PLR0913 — mirrors httpx2 per-method signatures; kwargs-fo
21902211
21912212 cap = self ._max_response_body_bytes
21922213 opened = (
2193- self ._httpx2_client . stream ( method , merged_url , ** kwargs )
2214+ _stream ( self ._httpx2_client , method , url , kwargs )
21942215 if cap is None
2195- else _stream_capped (self ._httpx2_client , method , merged_url , kwargs , cap )
2216+ else _stream_capped (self ._httpx2_client , method , url , kwargs , cap )
21962217 )
21972218 with _httpx2_exception_mapper_sync (), opened as response :
21982219 if HTTPStatus .BAD_REQUEST <= response .status_code < 600 : # noqa: PLR2004 — 600 is the synthetic upper bound for 5xx
0 commit comments