mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
* fix(bedrock): forward x-pass- headers on the /bedrock/model pass-through routes
The /bedrock/model/{model}/invoke, invoke-with-response-stream, converse and
converse-stream routes built the pass-through call from the request body, so
x-pass- headers never reached Bedrock. The processor now hands the caller's
x-pass- headers to the pass-through route, keeps them out of the logged body
snapshot, and on Converse drops the invoke-only guardrail headers when the
deployment sets guardrailConfig and the request metadata header when the proxy
owns request metadata
* fix(bedrock): bill the served service tier on invoke pass-through and scope x-pass- forwarding to the Bedrock routes
* test(bedrock): assert forwarded x-pass- headers on the request Bedrock receives
* test(bedrock): gate the router-model x-pass- forwarding on the request Bedrock receives
* fix(bedrock): bill a caller's forwarded invoke guardrail and keep x-pass- headers out of guardrail vendor payloads
* fix(bedrock): bill a caller guardrail on every invoke model and replace a trace value Bedrock rejects
* fix(bedrock): keep guardrail traces out of chat responses, forward the trace header as sent, and drop credential x-pass- headers
---------
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
from typing import Final
|
|
|
|
import httpx
|
|
import pytest
|
|
|
|
from litellm.passthrough.utils import _PASS_THROUGH_PROTECTED_HEADERS, BasePassthroughUtils
|
|
|
|
|
|
def test_pass_through_prefixed_headers_keeps_only_the_x_pass_headers_forwarded_upstream() -> None:
|
|
inbound: Final = {
|
|
"authorization": "Bearer sk-litellm-key",
|
|
"x-litellm-api-key": "sk-litellm-key",
|
|
"content-type": "application/json",
|
|
"x-amzn-bedrock-guardrailidentifier": "native-guardrail",
|
|
"x-passthrough-id": "not-a-pass-header",
|
|
"x-pass-authorization": "Bearer upstream-secret",
|
|
"X-Pass-X-Api-Key": "upstream-api-key",
|
|
"x-pass-X-Amz-Security-Token": "forged-session-token",
|
|
"x-pass-x-amzn-bedrock-trace": "DISABLED",
|
|
"X-Pass-X-Amzn-Bedrock-GuardrailIdentifier": "caller-guardrail",
|
|
"X-PASS-ANTHROPIC-BETA": "beta-1",
|
|
}
|
|
|
|
selected: Final = BasePassthroughUtils.pass_through_prefixed_headers(inbound)
|
|
|
|
assert dict(selected) == {
|
|
"x-pass-x-amzn-bedrock-trace": "DISABLED",
|
|
"X-Pass-X-Amzn-Bedrock-GuardrailIdentifier": "caller-guardrail",
|
|
"X-PASS-ANTHROPIC-BETA": "beta-1",
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"header_name",
|
|
[
|
|
*(f"x-pass-{name}" for name in sorted(_PASS_THROUGH_PROTECTED_HEADERS)),
|
|
"X-Pass-Authorization",
|
|
"x-pass-X-Amz-Date",
|
|
"x-pass-x-amz-security-token",
|
|
"x-pass-X-Amzn-Bedrock-Trace",
|
|
"x-pass-anthropic-beta",
|
|
"x-pass-cookie",
|
|
"x-passthrough-id",
|
|
"authorization",
|
|
],
|
|
)
|
|
def test_pass_through_prefixed_headers_select_exactly_the_headers_forwarded_upstream(header_name: str) -> None:
|
|
inbound: Final = {header_name: "caller-value"}
|
|
|
|
selected: Final = BasePassthroughUtils.pass_through_prefixed_headers(inbound)
|
|
forwarded: Final = BasePassthroughUtils.forward_headers_from_request(
|
|
request_headers=dict(inbound), headers={}, forward_headers=False
|
|
)
|
|
|
|
assert {name[len("x-pass-") :].lower(): value for name, value in selected.items()} == forwarded
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("default_query_params", "expected"),
|
|
[
|
|
pytest.param(
|
|
{"api-version": "default", "region": "default"},
|
|
{"api-version": "url", "region": "default", "shared": "request", "tag": ["a", "b"]},
|
|
id="with_defaults",
|
|
),
|
|
pytest.param(None, {"api-version": "url", "shared": "request", "tag": ["a", "b"]}, id="without_defaults"),
|
|
],
|
|
)
|
|
def test_merged_query_parameters_let_the_request_override_the_url_and_the_url_override_defaults(
|
|
default_query_params: dict[str, str | list] | None, expected: dict[str, str | list[str]]
|
|
) -> None:
|
|
merged: Final = BasePassthroughUtils.get_merged_query_parameters(
|
|
existing_url=httpx.URL("https://upstream.test/v1?api-version=url&shared=url&tag=a&tag=b"),
|
|
request_query_params={"shared": "request"},
|
|
default_query_params=default_query_params,
|
|
)
|
|
|
|
assert merged == expected
|