From 68ab12061e0fbe601ed8c04873186a39d9a7f48b Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Thu, 14 Mar 2024 18:15:51 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20missing=20source=20+?= =?UTF-8?q?=20resized=20images=20producing=20rendered=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes https://linear.app/tryghost/issue/ENG-746/http-500-responses-when-handle-image-sizes-middleware-hits-missing - in the event a request comes in for a resized image, but the source image does not exist, we return a rendered 404 page - we do this because we pass the NotFoundError to `next`, which skips over the static asset code where we return a plaintext 404 - also included a breaking test that ensure we go to the next middleware without an error --- .../web/middleware/handle-image-sizes.js | 5 +++ .../web/middleware/handle-image-sizes.test.js | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/ghost/core/core/frontend/web/middleware/handle-image-sizes.js b/ghost/core/core/frontend/web/middleware/handle-image-sizes.js index a887cc43423c..f565b87e80ce 100644 --- a/ghost/core/core/frontend/web/middleware/handle-image-sizes.js +++ b/ghost/core/core/frontend/web/middleware/handle-image-sizes.js @@ -139,6 +139,11 @@ module.exports = function handleImageSizes(req, res, next) { if (err.code === 'SHARP_INSTALLATION' || err.code === 'IMAGE_PROCESSING' || err.errorType === 'NoContentError') { return redirectToOriginal(); } + + if (err.errorType === 'NotFoundError') { + return next(); + } + next(err); }); }; diff --git a/ghost/core/test/unit/frontend/web/middleware/handle-image-sizes.test.js b/ghost/core/test/unit/frontend/web/middleware/handle-image-sizes.test.js index 80777ddd208b..348a105af094 100644 --- a/ghost/core/test/unit/frontend/web/middleware/handle-image-sizes.test.js +++ b/ghost/core/test/unit/frontend/web/middleware/handle-image-sizes.test.js @@ -3,6 +3,7 @@ const sinon = require('sinon'); const storage = require('../../../../../core/server/adapters/storage'); const activeTheme = require('../../../../../core/frontend/services/theme-engine/active'); const handleImageSizes = require('../../../../../core/frontend/web/middleware/handle-image-sizes.js'); +const errors = require('@tryghost/errors'); const imageTransform = require('@tryghost/image-transform'); const fakeResBase = { @@ -673,5 +674,36 @@ describe('handleImageSizes middleware', function () { done(); }); }); + + it('goes to next middleware with no error if source and resized image 404', function (done) { + dummyStorage.exists = async function () { + return false; + }; + dummyStorage.read = async function () { + throw new errors.NotFoundError({ + message: 'File not found' + }); + }; + + const fakeReq = { + url: '/size/w1000/2020/02/test.png', + originalUrl: '/2020/02/test.png' + }; + + const fakeRes = { + redirect() { + done(new Error('Should not have called redirect')); + }, + setHeader() {}, + type: function () {} + }; + + handleImageSizes(fakeReq, fakeRes, function next(err) { + if (err) { + return done(err); + } + done(); + }); + }); }); }); From 622860f65e4c097b12572ae5432abbba39d160e3 Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Thu, 14 Mar 2024 20:29:49 +0100 Subject: [PATCH 2/2] added e2e test --- .../test/e2e-frontend/static-files.test.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 ghost/core/test/e2e-frontend/static-files.test.js diff --git a/ghost/core/test/e2e-frontend/static-files.test.js b/ghost/core/test/e2e-frontend/static-files.test.js new file mode 100644 index 000000000000..1072806b9c69 --- /dev/null +++ b/ghost/core/test/e2e-frontend/static-files.test.js @@ -0,0 +1,25 @@ +const assert = require('assert/strict'); +const {agentProvider} = require('../utils/e2e-framework'); + +describe('Static files', function () { + let frontendAgent; + let ghostServer; + + before(async function () { + const agents = await agentProvider.getAgentsWithFrontend(); + frontendAgent = agents.frontendAgent; + ghostServer = agents.ghostServer; + }); + + after(async function () { + await ghostServer.stop(); + }); + + it('serves unstyled 404 for non-existing resized + original files', async function () { + const response = await frontendAgent + .get('/content/images/size/w2000/1995/12/daniel.jpg') + .expect(404); + + assert.ok(response.text.includes('NotFoundError: Image not found')); + }); +});