Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- [#30](https://github.com/WSH032/fastapi-proxy-lib/pull/30) - fix(internal): use `websocket` in favor of `websocket_route`. Thanks [@WSH032](https://github.com/WSH032)!

### Removed

- [#49](https://github.com/WSH032/fastapi-proxy-lib/pull/49) - Drop support for `Python 3.8`.

### Fixed

- [#46](https://github.com/WSH032/fastapi-proxy-lib/pull/46) - fix: don't use module-level logging methods. Thanks [@dvarrazzo](https://github.com/dvarrazzo)
- [#49](https://github.com/WSH032/fastapi-proxy-lib/pull/49) - fix!: bump `httpx-ws >= 0.7.1` to fix frankie567/httpx-ws#29. Thanks [@WSH032](https://github.com/WSH032)!

### Removed

- [#49](https://github.com/WSH032/fastapi-proxy-lib/pull/49) - Drop support for `Python 3.8`.

### Internal

- [#47](https://github.com/WSH032/fastapi-proxy-lib/pull/47) - test: do not use deprecated and removed APIs of httpx. Thanks [@WSH032](https://github.com/WSH032)!
Expand Down
4 changes: 3 additions & 1 deletion src/fastapi_proxy_lib/core/_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"_RejectedProxyRequestError",
)

_logger = logging.getLogger(__name__)

#################### Constant ####################


Expand Down Expand Up @@ -361,7 +363,7 @@ def check_http_version(
return return_err_msg_response(
error,
status_code=status.HTTP_505_HTTP_VERSION_NOT_SUPPORTED,
logger=logging.info,
logger=_logger.info,
)


Expand Down
10 changes: 6 additions & 4 deletions src/fastapi_proxy_lib/core/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"ForwardHttpProxy",
)

_logger = logging.getLogger(__name__)

#################### Data Model ####################


Expand Down Expand Up @@ -272,7 +274,7 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
)

# DEBUG: 用于调试的记录
logging.debug(
_logger.debug(
"HTTP: client:%s ; url:%s ; head:%s",
request.client,
proxy_request.url,
Expand Down Expand Up @@ -434,7 +436,7 @@ async def proxy( # pyright: ignore [reportIncompatibleMethodOverride]
"Oops! Something wrong! Please contact the server maintainer!"
),
status_code=starlette_status.HTTP_502_BAD_GATEWAY,
logger=logging.exception,
logger=_logger.exception,
_msg=msg,
_exc_info=e,
)
Expand Down Expand Up @@ -550,7 +552,7 @@ async def proxy( # pyright: ignore [reportIncompatibleMethodOverride]
return return_err_msg_response(
e,
status_code=starlette_status.HTTP_400_BAD_REQUEST,
logger=logging.critical,
logger=_logger.critical,
)

# 进行请求过滤
Expand All @@ -575,7 +577,7 @@ async def proxy( # pyright: ignore [reportIncompatibleMethodOverride]
return return_err_msg_response(
e,
status_code=starlette_status.HTTP_500_INTERNAL_SERVER_ERROR,
logger=logging.exception,
logger=_logger.exception,
_exc_info=e,
)
# 请注意,我们不返回其他错误给客户端,因为这可能涉及到服务器内部的信息泄露
21 changes: 11 additions & 10 deletions src/fastapi_proxy_lib/core/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
# 这些是私有模块,无法确定以后版本是否会改变,为了保证运行时不会出错,我们使用TYPE_CHECKING
from httpx._types import HeaderTypes, QueryParamTypes

_logger = logging.getLogger(__name__)

#################### Data Model ####################

Expand Down Expand Up @@ -196,7 +197,7 @@ async def _httpx_ws_receive_bytes_or_str(
return bytes(event.data)
else: # pragma: no cover # 无法测试这个分支,因为无法发送这种消息,正常来说也不会被执行,所以我们这里记录critical
msg = f"Invalid message type received: {type(event)}"
logging.critical(msg)
_logger.critical(msg)
raise httpx_ws.WebSocketInvalidTypeReceived(event)


Expand Down Expand Up @@ -365,12 +366,12 @@ async def _close_ws(
client_error: {client_error}
server_error: {server_error}\
"""
logging.warning(msg)
_logger.warning(msg)

except (
Exception
) as e: # pragma: no cover # 这个分支是一个保险分支,通常无法执行,所以只进行记录
logging.error(
_logger.error(
f"{e} when close ws connection. client: {client_to_server_task}, server:{server_to_client_task}"
)
raise
Expand All @@ -389,7 +390,7 @@ async def _close_ws(
except Exception as e: # pragma: no cover
# 这个分支是一个保险分支,通常无法执行,所以只进行记录
# 不会触发的原因是,负责服务端 ws 连接的 httpx_ws 支持重复调用close而不引发错误
logging.debug("Unexpected error for debug", exc_info=e)
_logger.debug("Unexpected error for debug", exc_info=e)


#################### # ####################
Expand Down Expand Up @@ -502,7 +503,7 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
return check_result

# DEBUG: 用于调试的记录
logging.debug(
_logger.debug(
"WS: client:%s ; url:%s ; params:%s ; headers:%s",
websocket.client,
target_url,
Expand Down Expand Up @@ -620,14 +621,14 @@ async def send_request_to_target( # pyright: ignore [reportIncompatibleMethodOv
try:
await asyncio.wait_for(pending_task, timeout=1)
except asyncio.TimeoutError:
logging.debug(f"{pending} TimeoutError, it's normal.")
except Exception as e:
_logger.debug(f"{pending} TimeoutError, it's normal.")
except Exception as e: # pragma: no cover # usually unreachable
# 取消期间可能另一个ws会发生异常,这个是正常情况,且会被 asyncio.wait_for 传播
logging.debug(
_logger.debug(
f"{pending} raise error when being canceled, it's normal. error: {e}"
)
except Exception as e: # pragma: no cover # 这个是保险分支,通常无法执行
logging.warning(
except Exception as e: # pragma: no cover # usually unreachable
_logger.warning(
f"Something wrong, please contact the developer. error: {e}"
)
raise
Expand Down
23 changes: 23 additions & 0 deletions tests/test_http.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# noqa: D100


import logging

import httpx
import pytest
from fastapi_proxy_lib.core.tool import default_proxy_filter
Expand Down Expand Up @@ -244,6 +246,27 @@ async def test_cookie_leakage(
assert "foo" not in r.json() # not leaked
assert r.json()["a"] == "b" # send cookies normally

@pytest.mark.anyio()
async def test_no_logging_basic_config_call(
self, tool_4_test_fixture: Tool4TestFixture, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Test that we don't accidentally call `logging.basicConfig()`.

See issue #45
"""
root = logging.getLogger()
monkeypatch.setattr(root, "handlers", [])

client_for_conn_to_proxy_server = (
tool_4_test_fixture.client_for_conn_to_proxy_server
)
proxy_server_base_url = tool_4_test_fixture.proxy_server_base_url

resp = await client_for_conn_to_proxy_server.get(proxy_server_base_url)
assert resp.is_success

assert not root.handlers, "logging handler added"


class TestForwardHttpProxy(AbstractTestProxy):
"""For testing forward http proxy."""
Expand Down
Loading