mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-10 05:00:19 +08:00
feat(tunnel): 请求体流式传输 & OpenAI CLI 请求 key 排序优化
Hub 端: - open_local_stream 不再接收 body 参数,改为通过 push_local_request_body 分块推送 - 请求体按 32KB 分帧发送,避免大请求一次性压缩和传输 - local_relay 改为流式解析 envelope 和转发请求体 Proxy 端: - stream_handler 改为流式传输请求体到上游,不再预先收集完整 body - upstream_client 请求体类型从 Full<Bytes> 改为 UnsyncBoxBody 以支持流式传输 - dispatcher 将 StreamEnd/StreamError 事件转发给 stream handler Python 端: - hub_transport relay envelope 改为异步生成器流式发送 - 提取 reorder_openai_cli_request_prefix_keys 为公共函数 - Codex passthrough 路径也应用稳定的前缀 key 排序
This commit is contained in:
@@ -15,6 +15,7 @@ class _FakeRelayClient:
|
||||
def __init__(self, response: httpx.Response) -> None:
|
||||
self.response = response
|
||||
self.sent_request: httpx.Request | None = None
|
||||
self.sent_body: bytes | None = None
|
||||
|
||||
def build_request(self, method: str, url: str, **kwargs: Any) -> httpx.Request:
|
||||
return httpx.Request(method, url, **kwargs)
|
||||
@@ -22,6 +23,7 @@ class _FakeRelayClient:
|
||||
async def send(self, request: httpx.Request, *, stream: bool = False) -> httpx.Response:
|
||||
_ = stream
|
||||
self.sent_request = request
|
||||
self.sent_body = await request.aread()
|
||||
self.response.request = request
|
||||
return self.response
|
||||
|
||||
@@ -56,7 +58,7 @@ async def test_transport_encodes_local_relay_envelope(monkeypatch: pytest.Monkey
|
||||
await response.aclose()
|
||||
|
||||
assert fake_client.sent_request is not None
|
||||
payload = fake_client.sent_request.content
|
||||
payload = fake_client.sent_body
|
||||
assert payload is not None
|
||||
meta_len = struct.unpack("!I", payload[:4])[0]
|
||||
meta = json.loads(payload[4 : 4 + meta_len].decode("utf-8"))
|
||||
@@ -88,3 +90,33 @@ async def test_transport_maps_relay_timeout_to_read_timeout(
|
||||
|
||||
with pytest.raises(httpx.ReadTimeout, match="relay timed out"):
|
||||
await transport.handle_async_request(request)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_transport_streams_request_body_from_async_generator(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
transport = HubTunnelTransport("node-1", timeout=12.0)
|
||||
fake_client = _FakeRelayClient(httpx.Response(200, content=b"ok"))
|
||||
monkeypatch.setattr("src.services.proxy_node.hub_transport.get_hub_config", _relay_config)
|
||||
monkeypatch.setattr(transport, "_relay_client", fake_client)
|
||||
|
||||
async def body() -> Any:
|
||||
yield b'{"hello":'
|
||||
yield b'"world"}'
|
||||
|
||||
request = httpx.Request(
|
||||
"POST",
|
||||
"https://example.com/v1/chat/completions",
|
||||
headers={"content-type": "application/json"},
|
||||
content=body(),
|
||||
)
|
||||
|
||||
response = await transport.handle_async_request(request)
|
||||
assert response.status_code == 200
|
||||
await response.aclose()
|
||||
|
||||
payload = fake_client.sent_body
|
||||
assert payload is not None
|
||||
meta_len = struct.unpack("!I", payload[:4])[0]
|
||||
assert payload[4 + meta_len :] == b'{"hello":"world"}'
|
||||
|
||||
Reference in New Issue
Block a user