mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
fix(bedrock): use actual file size when Content-Length missing (#36388)
This commit is contained in:
parent
dee667edb7
commit
2d2b32c3f8
2 changed files with 65 additions and 1 deletions
|
|
@ -861,6 +861,9 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
|
|||
)
|
||||
|
||||
litellm_params["upload_url"] = api_base
|
||||
# Store file size for response transformation (S3 PUT response
|
||||
# doesn't include Content-Length, so we pass it through).
|
||||
litellm_params["_file_content_size"] = len(file_content) if isinstance(file_content, (str, bytes)) else 0
|
||||
|
||||
# Return a dict that tells the HTTP handler exactly what to do
|
||||
return {
|
||||
|
|
@ -1024,6 +1027,12 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
|
|||
# S3 PUT object returns ETag and other metadata in headers
|
||||
content_length: Final = response_headers.get("Content-Length", "0")
|
||||
|
||||
# S3 PUT responses may not include Content-Length, so fall back
|
||||
# to the actual content size captured during request transformation.
|
||||
file_size: int = int(content_length) if content_length.isdigit() else 0
|
||||
if file_size == 0:
|
||||
file_size = litellm_params.get("_file_content_size", 0)
|
||||
|
||||
# Use the actual upload URL that was used for the S3 upload
|
||||
upload_url: Final = litellm_params.get("upload_url")
|
||||
file_id: str = ""
|
||||
|
|
@ -1038,7 +1047,7 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
|
|||
filename=filename,
|
||||
created_at=int(time.time()), # Current timestamp
|
||||
status="uploaded",
|
||||
bytes=int(content_length) if content_length.isdigit() else 0,
|
||||
bytes=file_size,
|
||||
object="file",
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2038,6 +2038,61 @@ class TestBedrockFilesS3SignatureEncoding:
|
|||
headers=signed["headers"],
|
||||
)
|
||||
|
||||
def test_transform_create_file_response_bytes_from_content_length(self):
|
||||
"""bytes should reflect actual file size when Content-Length is present."""
|
||||
import httpx
|
||||
|
||||
from litellm.llms.bedrock.files.transformation import BedrockFilesConfig
|
||||
|
||||
raw_response = httpx.Response(
|
||||
status_code=200,
|
||||
headers={"Content-Length": "4096"},
|
||||
content=b"",
|
||||
request=httpx.Request(
|
||||
"PUT",
|
||||
"https://s3.us-east-1.amazonaws.com/my-bucket/litellm-bedrock-files-anthropic.claude-3-5-sonnet-20240620-v1:0-abc123.jsonl",
|
||||
),
|
||||
)
|
||||
|
||||
result = BedrockFilesConfig().transform_create_file_response(
|
||||
model=None,
|
||||
raw_response=raw_response,
|
||||
logging_obj=MagicMock(),
|
||||
litellm_params={},
|
||||
)
|
||||
|
||||
assert result.bytes == 4096
|
||||
|
||||
def test_transform_create_file_response_bytes_falls_back_to_content_size(self):
|
||||
"""When S3 PUT response omits Content-Length, bytes should fall back
|
||||
to the actual content size captured during request transformation.
|
||||
|
||||
Regression test for #36388.
|
||||
"""
|
||||
import httpx
|
||||
|
||||
from litellm.llms.bedrock.files.transformation import BedrockFilesConfig
|
||||
|
||||
raw_response = httpx.Response(
|
||||
status_code=200,
|
||||
# S3 PUT responses typically omit Content-Length
|
||||
headers={},
|
||||
content=b"",
|
||||
request=httpx.Request(
|
||||
"PUT",
|
||||
"https://s3.us-east-1.amazonaws.com/my-bucket/litellm-bedrock-files-anthropic.claude-3-5-sonnet-20240620-v1:0-abc123.jsonl",
|
||||
),
|
||||
)
|
||||
|
||||
result = BedrockFilesConfig().transform_create_file_response(
|
||||
model=None,
|
||||
raw_response=raw_response,
|
||||
logging_obj=MagicMock(),
|
||||
litellm_params={"_file_content_size": 2048},
|
||||
)
|
||||
|
||||
assert result.bytes == 2048
|
||||
|
||||
def test_file_content_signs_spaced_object_key_the_way_s3_does(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue