From 1c844a4415f7896576e5d482a9fc5480aed6c63f Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Tue, 12 Mar 2024 15:21:57 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20HTTP=20500=20error=20whe?= =?UTF-8?q?n=20image=20processing=20fails=20during=20upload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes ENG-740 fixes https://linear.app/tryghost/issue/ENG-740/http-500-error-when-image-processing-fails - in the event the image transform library throws (which can happen for many reasons; sharp/libvips can come across a number of errors), we currently return this as a HTTP 500 error to the user - in this case, we should just try-catch the call and jump to the non-processing flow where it just saves the original image - also added breaking test --- ghost/core/core/server/api/endpoints/images.js | 7 ++++++- ghost/core/test/e2e-api/admin/images.test.js | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ghost/core/core/server/api/endpoints/images.js b/ghost/core/core/server/api/endpoints/images.js index 7b6fc2d26bdb..e2c26718587a 100644 --- a/ghost/core/core/server/api/endpoints/images.js +++ b/ghost/core/core/server/api/endpoints/images.js @@ -33,7 +33,12 @@ module.exports = { width: config.get('imageOptimization:defaultMaxWidth') }, imageOptimizationOptions); - await imageTransform.resizeFromPath(options); + try { + await imageTransform.resizeFromPath(options); + } catch (err) { + // If the image processing fails, we just want to store the original image + return store.save(frame.file); + } // Store the processed/optimized image const processedImageUrl = await store.save({ diff --git a/ghost/core/test/e2e-api/admin/images.test.js b/ghost/core/test/e2e-api/admin/images.test.js index 8d6467e7aa1d..e5f08322de7d 100644 --- a/ghost/core/test/e2e-api/admin/images.test.js +++ b/ghost/core/test/e2e-api/admin/images.test.js @@ -301,4 +301,14 @@ describe('Images API', function () { await uploadImageCheck({path: originalFilePath, filename: 'a.png', contentType: 'image/png'}); clock.restore(); }); + + it('Does not return HTTP 500 when image processing fails', async function () { + sinon.stub(imageTransform, 'resizeFromPath').rejects(new Error('Image processing failed')); + + const originalFilePath = p.join(__dirname, '/../../utils/fixtures/images/ghost-logo.png'); + const fileContents = await fs.readFile(originalFilePath); + + await uploadImageRequest({fileContents, filename: 'test.png', contentType: 'image/png'}) + .expectStatus(201); + }); });