mirror of
https://github.com/debpalash/VoiceStudio.git
synced 2026-10-02 01:26:35 +08:00
Keep SDK loopback requests direct and disable shared cookies
This commit is contained in:
@@ -4,9 +4,18 @@ from __future__ import annotations
|
||||
import os
|
||||
import atexit
|
||||
from functools import lru_cache
|
||||
from http.cookiejar import CookieJar, DefaultCookiePolicy
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
class _NoCookies(DefaultCookiePolicy):
|
||||
def set_ok(self, cookie, request):
|
||||
return False
|
||||
|
||||
def return_ok(self, cookie, request):
|
||||
return False
|
||||
|
||||
|
||||
def _check_sdk_request(request):
|
||||
"""Validate the effective URL after SDK environment/provider resolution."""
|
||||
from ipaddress import ip_address
|
||||
@@ -28,7 +37,12 @@ def _sdk_http_client():
|
||||
# A shared thread-safe pool also keeps streaming responses alive after
|
||||
# completion() returns. It carries no provider credentials of its own.
|
||||
import httpx
|
||||
client = httpx.Client(follow_redirects=False, event_hooks={"request": [_check_sdk_request]})
|
||||
client = httpx.Client(
|
||||
follow_redirects=False,
|
||||
trust_env=False,
|
||||
cookies=CookieJar(policy=_NoCookies()),
|
||||
event_hooks={"request": [_check_sdk_request]},
|
||||
)
|
||||
atexit.register(client.close)
|
||||
return client
|
||||
|
||||
|
||||
@@ -150,3 +150,5 @@ LM Studio automatic discovery accepts only loaded `llm`/`vlm` entries from its n
|
||||
SDK transport validates the final request URL, including environment-derived
|
||||
OpenAI endpoints, and disables redirects for OpenAI-compatible and native
|
||||
Anthropic, Bedrock, and Vertex requests.
|
||||
The shared HTTP client ignores environment proxies so loopback prompts stay local,
|
||||
and never stores response cookies between provider requests.
|
||||
|
||||
@@ -159,3 +159,33 @@ def test_anthropic_does_not_follow_credentialed_redirect(registry):
|
||||
assert seen == ["/v1/messages"]
|
||||
finally:
|
||||
server.shutdown(); server.server_close(); thread.join(timeout=2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("proxy_enabled", [False, True])
|
||||
def test_sdk_pool_keeps_loopback_direct_and_does_not_persist_cookies(monkeypatch, proxy_enabled):
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from threading import Thread
|
||||
from services.llm_transport import _sdk_http_client
|
||||
seen = []
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def log_message(self, *args): pass
|
||||
def do_GET(self):
|
||||
seen.append(self.headers.get("Cookie"))
|
||||
self.send_response(200)
|
||||
self.send_header("Set-Cookie", "session=private; Path=/")
|
||||
self.send_header("Content-Length", "0")
|
||||
self.end_headers()
|
||||
for key in ("HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"):
|
||||
monkeypatch.setenv(key, "http://127.0.0.1:1" if proxy_enabled else "")
|
||||
monkeypatch.setenv("NO_PROXY", "")
|
||||
monkeypatch.setenv("no_proxy", "")
|
||||
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
|
||||
thread = Thread(target=server.serve_forever, daemon=True); thread.start()
|
||||
try:
|
||||
with _sdk_http_client.__wrapped__() as client:
|
||||
for _ in range(2):
|
||||
assert client.get(f"http://127.0.0.1:{server.server_port}/", timeout=2).status_code == 200
|
||||
assert not list(client.cookies.jar)
|
||||
assert seen == [None, None]
|
||||
finally:
|
||||
server.shutdown(); server.server_close(); thread.join(timeout=2)
|
||||
|
||||
Reference in New Issue
Block a user