From 8c01deb2e35375307a84a31c7c3fa281f7022107 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 1 Apr 2026 21:57:14 -0400 Subject: [PATCH] fix: properly decode base64 image data and detect MIME type Image endpoint was returning base64 text instead of decoded binary. Now properly decodes base64 from Odoo Binary field and detects actual content type from magic bytes (JPEG, PNG, GIF, WebP). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../fusion_woocommerce/controllers/api.py | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/fusion-woo-odoo/fusion_woocommerce/controllers/api.py b/fusion-woo-odoo/fusion_woocommerce/controllers/api.py index 11607ece..4d86b913 100644 --- a/fusion-woo-odoo/fusion_woocommerce/controllers/api.py +++ b/fusion-woo-odoo/fusion_woocommerce/controllers/api.py @@ -23,16 +23,45 @@ class WooApiController(http.Controller): try: line = request.env['woo.variant.push.line'].sudo().browse(line_id) if not line.exists() or not line.image: + _logger.warning("Image endpoint: line %d not found or no image", line_id) return request.not_found() img_data = line.image - if isinstance(img_data, str): + # Odoo Binary fields always return base64 string + if isinstance(img_data, (str, bytes)): + if isinstance(img_data, bytes): + img_data = img_data.decode('utf-8') img_data = base64.b64decode(img_data) elif isinstance(img_data, memoryview): - img_data = bytes(img_data) + # Raw bytea from DB — still base64 encoded by ORM + raw = bytes(img_data) + try: + img_data = base64.b64decode(raw) + except Exception: + img_data = raw + # Detect content type from magic bytes content_type = 'image/png' - if filename.lower().endswith('.jpg') or filename.lower().endswith('.jpeg'): + if img_data[:2] == b'\xff\xd8': content_type = 'image/jpeg' - return Response(img_data, content_type=content_type, status=200) + elif img_data[:4] == b'\x89PNG': + content_type = 'image/png' + elif img_data[:4] == b'GIF8': + content_type = 'image/gif' + elif img_data[:4] == b'RIFF': + content_type = 'image/webp' + _logger.info("Serving image for line %d: %d bytes, %s", line_id, len(img_data), content_type) + # Set extension-appropriate filename + ext = content_type.split('/')[-1] + if ext == 'jpeg': + ext = 'jpg' + return Response( + img_data, + content_type=content_type, + status=200, + headers={ + 'Content-Disposition': f'inline; filename="{filename.rsplit(".", 1)[0]}.{ext}"', + 'Cache-Control': 'no-cache', + }, + ) except Exception as e: _logger.error("Failed to serve variant image %d: %s", line_id, e) return request.not_found()