Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/sentry/models/eventattachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,9 @@ def putfile(cls, project_id: int, attachment: CachedAttachment) -> PutfileResult

def normalize_content_type(content_type: str | None, name: str) -> str:
if content_type:
return content_type.split(";")[0].strip()
normalized = content_type.split(";")[0].strip()
if normalized.lower() != "application/octet-stream":
return normalized
return mimetypes.guess_type(name)[0] or "application/octet-stream"


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,15 +523,15 @@ def test_process_stored_attachment(
@pytest.mark.parametrize(
"attachment",
[
([b"Hello ", b"World!"], "event.attachment", "application/octet-stream"),
([b""], "event.attachment", "application/octet-stream"),
([], "event.attachment", "application/octet-stream"),
([b"Hello ", b"World!"], "event.attachment", "text/plain"),
([b""], "event.attachment", "text/plain"),
([], "event.attachment", "text/plain"),
(
[b'{"rendering_system":"flutter","windows":[]}'],
"event.view_hierarchy",
"application/json",
),
(b"inline attachment", "event.attachment", "application/octet-stream"),
(b"inline attachment", "event.attachment", "text/plain"),
],
ids=["basic", "zerolen", "nochunks", "view_hierarchy", "inline"],
)
Expand Down
28 changes: 27 additions & 1 deletion tests/sentry/models/test_eventattachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from unittest import mock
from uuid import uuid4

from sentry.models.eventattachment import EventAttachment
from sentry.models.eventattachment import EventAttachment, normalize_content_type
from sentry.testutils.cases import TestCase


Expand Down Expand Up @@ -48,3 +48,29 @@ def test_v2_delete_skips_objectstore_during_cleanup(

mock_get_session.return_value.delete.assert_not_called()
assert not EventAttachment.objects.filter(id=attachment.id).exists()


class NormalizeContentTypeTest(TestCase):
def test_returns_explicit_content_type(self):
assert normalize_content_type("image/png", "file.png") == "image/png"

def test_strips_charset_from_content_type(self):
assert normalize_content_type("text/plain; charset=utf-8", "file.txt") == "text/plain"

def test_infers_from_filename_when_none(self):
assert normalize_content_type(None, "screenshot.png") == "image/png"

def test_infers_from_filename_when_octet_stream(self):
assert normalize_content_type("application/octet-stream", "screenshot.png") == "image/png"

def test_falls_back_to_octet_stream_when_unrecognized(self):
assert normalize_content_type(None, "data.bin") == "application/octet-stream"

def test_octet_stream_with_unrecognized_name(self):
assert (
normalize_content_type("application/octet-stream", "noext")
== "application/octet-stream"
)

def test_octet_stream_case_insensitive(self):
assert normalize_content_type("Application/Octet-Stream", "screenshot.png") == "image/png"
Loading