Skip to content

Commit d464f27

Browse files
yhl-csyu.hanlinWSH032
authored
fix(#56): error in handling multiple query parameters (#57)
* handling duplicate query parameters Fix: #56 Signed-off-by: yhl-cs <yuhl18@zju.edu.cn> * test(refactor): better http multiple query params tesing * test(refactor): better ws multiple query params tesing * docs: add comments for why need to shallow clone the `query_params` * docs: add changelog --------- Signed-off-by: yhl-cs <yuhl18@zju.edu.cn> Co-authored-by: yu.hanlin <yu.hanlin@jingjiamicro.com> Co-authored-by: WSH032 <614337162@qq.com>
1 parent 64a7be4 commit d464f27

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323

2424
## [Unreleased]
2525

26+
### Fixed
27+
28+
- [#57](https://github.com/WSH032/fastapi-proxy-lib/pull/57) - fix: error in handling multiple query parameters (#56). Thanks [@yhl-cs](https://github.com/yhl-cs)!
29+
30+
Now `fastapi-proxy-lib` can handle multiple query parameters (e.g. `foo?a=1&a=2`) correctly. Previously, it would only keep the last one (e.g. `foo?a=2`).
31+
2632
## [0.2.0] - 2025-01-15
2733

2834
### Added

src/fastapi_proxy_lib/core/http.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,9 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
267267
proxy_request = client.build_request(
268268
method=request.method,
269269
url=target_url,
270-
params=request.query_params,
270+
# TODO, FIXME: do not shallow clone (i.e, `tuple(...)`) the query_params,
271+
# see: <https://github.com/WSH032/fastapi-proxy-lib/pull/57#issuecomment-2750153934>
272+
params=tuple(request.query_params.multi_items()),
271273
headers=proxy_header,
272274
content=request_content, # FIXME: 一个已知问题是,流式响应头包含'transfer-encoding': 'chunked',但有些服务器会400拒绝这个头
273275
# cookies=request.cookies, # NOTE: headers中已有的cookie优先级高,所以这里不需要

src/fastapi_proxy_lib/core/websocket.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,11 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
493493
client_request_headers: "HeaderTypes" = _change_client_header(
494494
headers=websocket.headers, target_url=target_url
495495
)
496-
client_request_params: "QueryParamTypes" = websocket.query_params
496+
# TODO, FIXME: do not shallow clone (i.e, `tuple(...)`) the query_params,
497+
# see: <https://github.com/WSH032/fastapi-proxy-lib/pull/57#issuecomment-2750153934>
498+
client_request_params: "QueryParamTypes" = tuple(
499+
websocket.query_params.multi_items()
500+
)
497501

498502
# TODO: 是否可以不检查http版本?
499503
check_result = check_http_version(websocket.scope, SUPPORTED_WS_HTTP_VERSIONS)

tests/test_http.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,37 @@ async def test_if_the_header_is_properly_handled(
158158
)
159159
assert "close" in proxy_resp.headers["connection"]
160160

161+
@pytest.mark.anyio()
162+
async def test_if_the_multiple_query_params_forwarding_is_correct(
163+
self, tool_4_test_fixture: Tool4TestFixture
164+
) -> None:
165+
"""See: <https://github.com/WSH032/fastapi-proxy-lib/issues/56>."""
166+
client_for_conn_to_proxy_server = (
167+
tool_4_test_fixture.client_for_conn_to_proxy_server
168+
)
169+
proxy_server_base_url = tool_4_test_fixture.proxy_server_base_url
170+
171+
query_params = httpx.QueryParams(
172+
[
173+
("key1", "value1"),
174+
# NOTE: following two keys are same
175+
("key2", "value2"),
176+
("key2", "value3"),
177+
]
178+
)
179+
# We only need to send the query_params to any endpoint
180+
await client_for_conn_to_proxy_server.get(
181+
proxy_server_base_url + "get/echo_headers_and_params",
182+
params=query_params,
183+
)
184+
185+
target_server_recv_request = tool_4_test_fixture.get_request()
186+
187+
# Check is the multiple query_params are forwarded correctly
188+
assert sorted(target_server_recv_request.query_params.multi_items()) == sorted(
189+
query_params.multi_items()
190+
)
191+
161192
@pytest.mark.anyio()
162193
async def test_if_the_proxy_forwarding_is_correct(
163194
self, tool_4_test_fixture: Tool4TestFixture

tests/test_ws.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,31 @@ async def test_ws_proxy(self, tool_4_test_fixture: Tool4TestFixture) -> None:
175175
await ws.send_bytes(b"foo")
176176
assert await ws.receive_bytes() == b"foo"
177177

178+
########## Test multiple query params ##########
179+
# see: <https://github.com/WSH032/fastapi-proxy-lib/issues/56>
180+
181+
query_params = httpx.QueryParams(
182+
[
183+
("key1", "value1"),
184+
# NOTE: following two keys are same
185+
("key2", "value2"),
186+
("key2", "value3"),
187+
]
188+
)
189+
# We only need to send the query_params to any endpoint
190+
async with aconnect_ws(
191+
proxy_server_base_url + "just_close_with_1001",
192+
client_for_conn_to_proxy_server,
193+
params=query_params,
194+
):
195+
pass
196+
197+
target_starlette_ws = get_request()
198+
# Check is the multiple query_params are forwarded correctly
199+
assert sorted(target_starlette_ws.query_params.multi_items()) == sorted(
200+
query_params.multi_items()
201+
)
202+
178203
########## 测试子协议 ##########
179204

180205
async with aconnect_ws(

0 commit comments

Comments
 (0)