[Bug Fix] Fix Error code: 307 for LlamaAPI Streaming Chat (#11946)

* fix: add follow_redirects to avoid 307 error code

* feat: add error 307 test case

* feat: add follow_redirects=True to AsyncClient
This commit is contained in:
Young Han 2025-06-30 16:52:42 -07:00 • committed by GitHub
parent d65a9fdcc7
commit 042f6b187e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 1 deletions

View file

@ -200,6 +200,7 @@ class BaseOpenAILLM:
limits=httpx.Limits(max_connections=1000, max_keepalive_connections=100),
verify=litellm.ssl_verify,
transport=AsyncHTTPHandler._create_async_transport(),
follow_redirects=True,
)
@staticmethod
@ -209,4 +210,5 @@ class BaseOpenAILLM:
return httpx.Client(
limits=httpx.Limits(max_connections=1000, max_keepalive_connections=100),
verify=litellm.ssl_verify,
follow_redirects=True,
)

View file

@ -1,6 +1,6 @@
import os
import sys
from unittest.mock import MagicMock, patch
from unittest.mock import AsyncMock, patch
import pytest
@ -8,6 +8,7 @@ sys.path.insert(
0, os.path.abspath("../..")
) # Adds the parent directory to the system path
import litellm
from litellm.llms.meta_llama.chat.transformation import LlamaAPIConfig
@ -44,3 +45,69 @@ def test_map_openai_params():
assert "temperature" in result
assert result["temperature"] == 0.7
assert "response_format" in result
@pytest.mark.asyncio
async def test_llama_api_streaming_no_307_error():
"""Test that streaming works without 307 redirect errors due to follow_redirects=True"""
# Mock the httpx client to simulate a successful streaming response
with patch(
"litellm.llms.custom_httpx.http_handler.get_async_httpx_client"
) as mock_get_client:
# Create a mock client
mock_client = AsyncMock()
mock_get_client.return_value = mock_client
# Mock a successful streaming response (not a 307 redirect)
mock_response = AsyncMock()
mock_response.status_code = 200
mock_response.headers = {"content-type": "text/plain; charset=utf-8"}
# Mock streaming data that would come from a successful request
async def mock_aiter_lines():
yield 'data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1234567890,"model":"meta_llama/Llama-4-Maverick-17B-128E-Instruct-FP8","choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"},"finish_reason":null}]}'
yield 'data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1234567890,"model":"meta_llama/Llama-4-Maverick-17B-128E-Instruct-FP8","choices":[{"index":0,"delta":{"content":" there"},"finish_reason":null}]}'
yield 'data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1234567890,"model":"meta_llama/Llama-4-Maverick-17B-128E-Instruct-FP8","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}'
yield "data: [DONE]"
mock_response.aiter_lines.return_value = mock_aiter_lines()
mock_client.stream.return_value.__aenter__.return_value = mock_response
# Test the streaming completion
try:
response = await litellm.acompletion(
model="meta_llama/Llama-4-Maverick-17B-128E-Instruct-FP8",
messages=[{"role": "user", "content": "Tell me about yourself"}],
stream=True,
temperature=0.0,
)
# Verify we get a CustomStreamWrapper (streaming response)
from litellm.utils import CustomStreamWrapper
assert isinstance(response, CustomStreamWrapper)
# Verify the HTTP client was called with follow_redirects=True
mock_client.stream.assert_called_once()
call_kwargs = mock_client.stream.call_args[1]
assert (
call_kwargs.get("follow_redirects") is True
), "follow_redirects should be True to prevent 307 errors"
# Verify the response status is 200 (not 307)
assert (
mock_response.status_code == 200
), "Should get 200 response, not 307 redirect"
except Exception as e:
# If there's an exception, make sure it's not a 307 error
error_str = str(e)
assert (
"307" not in error_str
), f"Should not get 307 redirect error: {error_str}"
# Still verify that follow_redirects was set correctly
if mock_client.stream.called:
call_kwargs = mock_client.stream.call_args[1]
assert call_kwargs.get("follow_redirects") is True