Merge pull request #36092 from BerriAI/devin_ai_fix_openai_passthrough_files_route_36086
Some checks are pending
CI Coverage / assert-ci-coverage (push) Waiting to run
CodSpeed Benchmarks / benchmarks (push) Waiting to run
Publish basedpyright base counts / publish (push) Waiting to run
Code Quality Checks / code-quality (push) Waiting to run
UI Unit Tests / ui-unit-tests (push) Waiting to run
Unit Tests: Core Utilities / core-utils (push) Waiting to run
Unit Tests: Documentation Validation / documentation (push) Waiting to run
Unit Tests: Enterprise, Google GenAI & Routing / enterprise-routing (push) Waiting to run
Unit Tests: Integrations (Callbacks & Logging) / integrations (push) Waiting to run
Unit Tests: LLM Provider Transformations / Vertex AI (push) Waiting to run
Unit Tests: LLM Provider Transformations / All Other Providers (push) Waiting to run
Unit Tests: MCP, Secrets, Containers & Misc / misc (push) Waiting to run
Unit Tests: Proxy Auth & Key Management / proxy-auth (push) Waiting to run
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Proxy API Endpoints / proxy-endpoints (push) Waiting to run
Unit Tests: Proxy API Endpoints / proxy-server (push) Waiting to run
Unit Tests: Proxy Infrastructure / proxy-infra (push) Waiting to run
Unit Tests: Proxy Legacy Tests / auth-and-jwt (push) Waiting to run
Unit Tests: Proxy Legacy Tests / key-generation (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-config (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-response-and-misc (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-server (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-server-extras (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-token-counter (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-user-auth-and-spend (push) Waiting to run
Unit Tests: Proxy Legacy Tests / proxy-utils (push) Waiting to run
Unit Tests: Responses, Caching & Types / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run

fix(proxy): stop /{provider}/v1/files from capturing /openai_passthrough
This commit is contained in:
Mateo Wang 2026-08-09 12:05:20 -07:00 committed by GitHub
commit f6b9518ddb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 1 deletions

View file

@ -60,6 +60,7 @@ from .passthrough_endpoint_router import PassthroughEndpointRouter
vertex_llm_base: Final = VertexBase()
router: Final = APIRouter()
openai_passthrough_router: Final = APIRouter()
default_vertex_config: Final = None
passthrough_endpoint_router: Final = PassthroughEndpointRouter()
@ -1875,7 +1876,7 @@ async def vertex_proxy_route(
)
@router.api_route(
@openai_passthrough_router.api_route(
"/openai_passthrough/{endpoint:path}",
methods=["GET", "POST", "PUT", "DELETE", "PATCH"],
tags=["OpenAI Pass-through", "pass-through"],

View file

@ -536,6 +536,7 @@ from litellm.proxy.openai_files_endpoints.files_endpoints import (
set_files_config,
)
from litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints import (
openai_passthrough_router,
passthrough_endpoint_router,
vertex_ai_live_websocket_passthrough,
)
@ -16607,6 +16608,7 @@ app.include_router(search_router)
app.include_router(image_router)
app.include_router(fine_tuning_router)
app.include_router(credential_router)
app.include_router(openai_passthrough_router)
app.include_router(batches_router)
app.include_router(openai_files_router)
app.include_router(llm_passthrough_router)

View file

@ -2,6 +2,7 @@ import json
import os
import sys
import traceback
from typing import Final
from unittest import mock
from unittest.mock import AsyncMock, MagicMock, Mock, patch
@ -2814,6 +2815,63 @@ class TestOpenAIPassthroughRoute:
assert result == {"id": "asst_123", "object": "assistant"}
def _resolve_route_name(method: str, path: str) -> str | None:
from starlette.routing import Match
from litellm.proxy.proxy_server import app
scope: Final = {
"type": "http",
"method": method,
"path": path,
"headers": [],
"query_string": b"",
"root_path": "",
}
for route in app.router.routes:
if route.matches(scope)[0] == Match.FULL:
return getattr(route, "name", None)
return None
@pytest.mark.parametrize(
"method, path",
[
("POST", "/openai_passthrough/v1/files"),
("GET", "/openai_passthrough/v1/files"),
("GET", "/openai_passthrough/v1/files/file-abc123"),
("DELETE", "/openai_passthrough/v1/files/file-abc123"),
("GET", "/openai_passthrough/v1/files/file-abc123/content"),
("POST", "/openai_passthrough/v1/batches"),
("GET", "/openai_passthrough/v1/batches"),
("GET", "/openai_passthrough/v1/batches/batch_abc123"),
("POST", "/openai_passthrough/v1/batches/batch_abc123/cancel"),
("POST", "/openai_passthrough/v1/responses"),
],
)
def test_openai_passthrough_prefix_wins_over_native_provider_routes(method, path):
"""
/openai_passthrough exists to guarantee passthrough, so the native
/{provider}/v1/files and /{provider}/v1/batches routes must never capture it
with provider="openai_passthrough" (which 500s on the LlmProviders lookup).
"""
assert _resolve_route_name(method, path) == "openai_proxy_route"
@pytest.mark.parametrize(
"method, path, expected_name",
[
("POST", "/openai/v1/files", "create_file"),
("GET", "/azure/v1/files", "list_files"),
("POST", "/v1/files", "create_file"),
("POST", "/v1/batches", "create_batch"),
("POST", "/openai/v1/chat/completions", "openai_proxy_route"),
],
)
def test_native_provider_routes_are_unchanged(method, path, expected_name):
assert _resolve_route_name(method, path) == expected_name
class TestCursorProxyRoute:
"""Tests for the Cursor Cloud Agents pass-through route."""