mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
fix(realtime): disable SSL for ws:// WebSocket connections (#19345)
When using http:// api_base (converted to ws://), the websockets library throws "ssl argument is incompatible with a ws:// URI". Only pass SSL context for secure wss:// connections. Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
This commit is contained in:
parent
1678f621db
commit
4ad5de10cb
2 changed files with 61 additions and 1 deletions
|
|
@ -56,7 +56,9 @@ class OpenAIRealtime(OpenAIChatCompletion):
|
|||
url = self._construct_url(api_base, query_params)
|
||||
|
||||
try:
|
||||
ssl_context = get_shared_realtime_ssl_context()
|
||||
# Only use SSL context for secure websocket connections (wss://)
|
||||
# websockets library doesn't accept ssl argument for ws:// URIs
|
||||
ssl_context = None if url.startswith("ws://") else get_shared_realtime_ssl_context()
|
||||
# Log a masked request preview consistent with other endpoints.
|
||||
logging_obj.pre_call(
|
||||
input=None,
|
||||
|
|
|
|||
|
|
@ -265,3 +265,61 @@ async def test_async_realtime_uses_max_size_parameter():
|
|||
|
||||
mock_realtime_streaming.assert_called_once()
|
||||
mock_streaming_instance.bidirectional_forward.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_realtime_ws_url_has_no_ssl():
|
||||
"""
|
||||
Test that when using http:// api_base (converted to ws://), the ssl argument
|
||||
is set to None. The websockets library doesn't accept ssl argument for ws:// URIs.
|
||||
|
||||
This verifies the fix for: https://github.com/BerriAI/litellm/issues/19222
|
||||
"""
|
||||
from litellm.llms.openai.realtime.handler import OpenAIRealtime
|
||||
from litellm.types.realtime import RealtimeQueryParams
|
||||
|
||||
handler = OpenAIRealtime()
|
||||
api_base = "http://localhost:8113" # Non-SSL local server
|
||||
api_key = "test-key"
|
||||
model = "test-model"
|
||||
query_params: RealtimeQueryParams = {"model": model}
|
||||
|
||||
dummy_websocket = AsyncMock()
|
||||
dummy_logging_obj = MagicMock()
|
||||
mock_backend_ws = AsyncMock()
|
||||
|
||||
class DummyAsyncContextManager:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
async def __aenter__(self):
|
||||
return self.value
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
return None
|
||||
|
||||
with patch("websockets.connect", return_value=DummyAsyncContextManager(mock_backend_ws)) as mock_ws_connect, \
|
||||
patch("litellm.llms.openai.realtime.handler.RealTimeStreaming") as mock_realtime_streaming:
|
||||
|
||||
mock_streaming_instance = MagicMock()
|
||||
mock_realtime_streaming.return_value = mock_streaming_instance
|
||||
mock_streaming_instance.bidirectional_forward = AsyncMock()
|
||||
|
||||
await handler.async_realtime(
|
||||
model=model,
|
||||
websocket=dummy_websocket,
|
||||
logging_obj=dummy_logging_obj,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
query_params=query_params,
|
||||
)
|
||||
|
||||
# Verify websockets.connect was called
|
||||
mock_ws_connect.assert_called_once()
|
||||
called_url = mock_ws_connect.call_args[0][0]
|
||||
called_kwargs = mock_ws_connect.call_args[1]
|
||||
|
||||
# Verify URL was converted from http:// to ws://
|
||||
assert called_url.startswith("ws://localhost:8113/v1/realtime?")
|
||||
assert f"model={model}" in called_url
|
||||
|
||||
# Verify ssl is None for ws:// URLs (the fix for issue #19222)
|
||||
assert called_kwargs["ssl"] is None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue