test(proxy): expect litellm_error_type in Messages integration tests and type middleware tests

This commit is contained in:
mateo-berri 2026-10-28 13:01:05 -07:00
parent ef24f406a0
commit a5e86700c2
4 changed files with 12 additions and 13 deletions

View file

@ -151,9 +151,6 @@ def error_type(response: httpx.Response) -> str:
def budget_refusal_error_type(route: str) -> str:
"""The ``error.type`` a budget refusal carries on a route label from ``ROUTES``: the
Anthropic envelope on Messages (its budget refusal is raised in
``user_api_key_auth``), the OpenAI ``budget_exceeded`` type on the other routes."""
return "invalid_request_error" if route == "messages" else "budget_exceeded"

View file

@ -55,6 +55,7 @@ class _AnthropicErrorDetail(BaseModel):
type: str
message: str
litellm_error_type: str
class _AnthropicErrorResponse(BaseModel):
@ -67,7 +68,9 @@ class _AnthropicErrorResponse(BaseModel):
GENERIC_ERROR: Final = _ProxyError(message=GENERIC_MESSAGE, type="token_not_found_in_db", param="key", code="401")
MESSAGES_PATH: Final = "/v1/messages"
ANTHROPIC_ENVELOPE_PATHS: Final = frozenset({MESSAGES_PATH, "/anthropic/v1/messages"})
ANTHROPIC_GENERIC_ERROR: Final = _AnthropicErrorDetail(type="authentication_error", message=GENERIC_MESSAGE)
ANTHROPIC_GENERIC_ERROR: Final = _AnthropicErrorDetail(
type="authentication_error", message=GENERIC_MESSAGE, litellm_error_type=GENERIC_ERROR.type
)
@dataclass(frozen=True, slots=True)
@ -146,7 +149,6 @@ def _assert_messages_refusal(response: httpx.Response, *secrets: str) -> None:
def _assert_refusal(path: str, response: httpx.Response, *secrets: str) -> None:
"""The Messages and Anthropic pass-through routes answer the Anthropic envelope, every other route the OpenAI one."""
if path in ANTHROPIC_ENVELOPE_PATHS:
_assert_messages_refusal(response, *secrets)
else:
@ -398,8 +400,6 @@ async def _send_async(client: httpx.AsyncClient, route: _Route, key: str) -> htt
async def _burst(owned: OwnedProxy, keys: tuple[str, ...]) -> tuple[tuple[_Route, httpx.Response], ...]:
"""Each key's response paired with the route it was sent on, so the caller asserts the
envelope the route actually answered with."""
routes: Final = tuple(ROUTES[BURST_ROUTES[index % len(BURST_ROUTES)]] for index in range(len(keys)))
async with httpx.AsyncClient(base_url=str(owned.gateway.client.base_url), timeout=60, trust_env=False) as client:
responses: Final = await asyncio.gather(

View file

@ -683,7 +683,7 @@ async def test_non_http_scopes_reach_the_app_untouched(scope: Scope):
)
def test_a_messages_body_the_proxy_cannot_take_gets_the_anthropic_envelope(
body: bytes, max_mb: float, status_code: int, anthropic_type: str, message: str | None
):
) -> None:
response: Final = _post(
_client(max_decompressed_body_size_mb=max_mb),
ZSTD_FRAME_MAGIC + body if message is None else body,

View file

@ -1,7 +1,9 @@
from typing import Final
import pytest
from starlette.responses import JSONResponse
from starlette.testclient import TestClient
from starlette.types import Message
from starlette.types import Message, Receive, Scope, Send
from litellm.proxy.middleware.request_size_limit_middleware import (
RequestSizeLimitMiddleware,
@ -135,15 +137,15 @@ async def test_request_size_limit_middleware_rejects_streamed_body_without_conte
assert received_body_bytes == 1024 * 1024
def test_an_oversized_messages_request_gets_the_anthropic_request_too_large_error():
async def app(scope, receive, send):
def test_an_oversized_messages_request_gets_the_anthropic_request_too_large_error() -> None:
async def app(scope: Scope, receive: Receive, send: Send) -> None:
await JSONResponse({"ok": True})(scope, receive, send)
client = TestClient(
client: Final = TestClient(
RequestSizeLimitMiddleware(app, get_max_request_size_mb=lambda: 1, is_request_size_limit_enabled=lambda: True)
)
response = client.post(
response: Final = client.post(
"/v1/messages", content=b"x" * (1024 * 1024 + 1), headers={"content-type": "application/json"}
)