From 64ef7bd2248677d72b6492782624a2b699f9e504 Mon Sep 17 00:00:00 2001 From: Fahim Murshed Date: Mon, 27 Jul 2026 14:55:19 +0600 Subject: [PATCH] Improve error handling and fix format issues - Fix serializer error format to be DRF-compliant in OembedRequestSerializer - Add error handling and logging for image dimension fetching in oEmbed endpoint - Add HTTP status check before processing image content - Escape special characters in dag-sync.sh JSON payload for robustness - Update skip button CSS selector for better browser compatibility --- api/api/serializers/image_serializers.py | 2 +- api/api/views/image_views.py | 38 ++++++++++++------- dag-sync.sh | 3 ++ .../src/components/VSkipToContentButton.vue | 2 +- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/api/api/serializers/image_serializers.py b/api/api/serializers/image_serializers.py index 6b08058025c..d3d44201586 100644 --- a/api/api/serializers/image_serializers.py +++ b/api/api/serializers/image_serializers.py @@ -118,7 +118,7 @@ def to_internal_value(self, data): uuid = UUID(identifier) except ValueError: raise serializers.ValidationError( - {"Could not parse identifier from URL.": data["url"]} + {"url": ["Could not parse identifier from URL."]} ) data["identifier"] = uuid diff --git a/api/api/views/image_views.py b/api/api/views/image_views.py index 0ccafd19200..2ca61884470 100644 --- a/api/api/views/image_views.py +++ b/api/api/views/image_views.py @@ -7,6 +7,7 @@ from drf_spectacular.utils import extend_schema, extend_schema_view from PIL import Image as PILImage +import structlog from api.constants.media_types import IMAGE_TYPE from api.docs.image_docs import ( @@ -31,6 +32,9 @@ from api.views.media_views import MediaViewSet +logger = structlog.get_logger(__name__) + + @extend_schema(tags=["images"]) @extend_schema_view( list=search, @@ -81,20 +85,26 @@ async def oembed(self, request, *_, **__): image = await aget_object_or_404(Image, identifier=identifier) if not (image.height and image.width): - session = await get_aiohttp_session() - - async with session.get( - image.url, headers=self.OEMBED_HEADERS - ) as image_file: - image_content = await image_file.content.read() - - with PILImage.open(io.BytesIO(image_content)) as image_file: - width, height = image_file.size - - context |= { - "width": width, - "height": height, - } + try: + session = await get_aiohttp_session() + + async with session.get( + image.url, headers=self.OEMBED_HEADERS + ) as image_file: + if image_file.status == 200: + image_content = await image_file.content.read() + with PILImage.open(io.BytesIO(image_content)) as image_file_obj: + width, height = image_file_obj.size + context |= { + "width": width, + "height": height, + } + except Exception: + logger.warning( + "failed_to_get_image_dimensions_for_oembed", + image_identifier=image.identifier, + image_url=image.url, + ) serializer = self.get_serializer(image, context=context) return Response(data=await serializer.adata) diff --git a/dag-sync.sh b/dag-sync.sh index 7be861315c3..60e412097e4 100755 --- a/dag-sync.sh +++ b/dag-sync.sh @@ -36,6 +36,9 @@ fi # Pull out the subject from the new commit subject=$(git log -1 --format='%s') +# Escape backslashes and double quotes for JSON payload safety +subject=${subject//\\/\\\\} +subject=${subject//\"/\\\"} # Swap the < & > characters for their HTML entities so they aren't # interpreted as delimiters by Slack subject=${subject//>/>} diff --git a/frontend/src/components/VSkipToContentButton.vue b/frontend/src/components/VSkipToContentButton.vue index 90fddf63fca..7bbd1a324d5 100644 --- a/frontend/src/components/VSkipToContentButton.vue +++ b/frontend/src/components/VSkipToContentButton.vue @@ -16,7 +16,7 @@ import VButton from "~/components/VButton.vue"