2929from ._tool import (
3030 ProxyFilterProto ,
3131 _RejectedProxyRequestError , # pyright: ignore [reportPrivateUsage] # 允许使用本项目内部的私有成员
32+ change_necessary_client_header_for_httpx ,
3233 check_base_url ,
3334 check_http_version ,
3435 return_err_msg_response ,
@@ -121,9 +122,12 @@ def _change_client_header(
121122) -> _ConnectionHeaderParseResult :
122123 """Change client request headers for sending to proxy server.
123124
125+ - Change "host" header to `target_url.netloc.decode("ascii")`.
126+ - If "Cookie" header is not in headers,
127+ will forcibly add a empty "Cookie" header
128+ to avoid httpx.AsyncClient automatically add another user cookiejar.
124129 - Will remove "close" value in "connection" header, and add "keep-alive" value to it.
125130 - And remove "keep-alive" header.
126- - And change "host" header to `target_url.netloc.decode("ascii")`.
127131
128132 Args:
129133 headers: original client request headers.
@@ -135,9 +139,12 @@ def _change_client_header(
135139 new_headers: New requests headers, the **copy** of original input headers.
136140 """
137141 # https://www.starlette.io/requests/#headers
138- # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#syntax
139- new_headers = headers .mutablecopy ()
140142
143+ new_headers = change_necessary_client_header_for_httpx (
144+ headers = headers , target_url = target_url
145+ )
146+
147+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#syntax
141148 # NOTE: http标准中规定,connecttion头字段的值用于指示逐段头,而标头是大小写不敏感的,故认为可以转为小写处理
142149 client_connection_header = [
143150 v .strip () for v in new_headers .get ("connection" , "" ).lower ().split ("," )
@@ -160,10 +167,6 @@ def _change_client_header(
160167 if "keep-alive" in new_headers :
161168 del new_headers ["keep-alive" ]
162169
163- # 将host字段更新为目标url的host
164- # TODO: 如果查看httpx.URL源码,就会发现netloc是被字符串编码成bytes的,能否想个办法直接获取字符串来提高性能?
165- new_headers ["host" ] = target_url .netloc .decode ("ascii" )
166-
167170 return _ConnectionHeaderParseResult (whether_require_close , new_headers )
168171
169172
@@ -251,6 +254,12 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
251254 None if request .method in _NON_REQUEST_BODY_METHODS else request .stream ()
252255 )
253256
257+ # FIX: https://github.com/WSH032/fastapi-proxy-lib/security/advisories/GHSA-7vwr-g6pm-9hc8
258+ # time cost: 396 ns ± 3.39 ns
259+ # 由于这不是原子性的操作,所以不保证一定阻止cookie泄漏
260+ # 一定能保证修复的方法是通过`_tool.change_necessary_client_header_for_httpx`强制指定优先级最高的cookie头
261+ client .cookies .clear ()
262+
254263 # NOTE: 不要在这里catch `client.build_request` 和 `client.send` 的异常,因为通常来说
255264 # - 反向代理的异常需要报 5xx 错误
256265 # - 而正向代理的异常需要报 4xx 错误
0 commit comments