Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added timeout when resizing an image #20087

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 10 additions & 2 deletions ghost/core/core/frontend/web/middleware/handle-image-sizes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const {imageSize} = require('../../../server/lib/image');

const SIZE_PATH_REGEX = /^\/size\/([^/]+)\//;
const FORMAT_PATH_REGEX = /^\/format\/([^./]+)\//;

const TRAILING_SLASH_REGEX = /\/+$/;

const RESIZE_TIMEOUT_SECONDS = 10;

module.exports = function handleImageSizes(req, res, next) {
// In admin we need to read images and calculate the average color (blocked by CORS otherwise)
res.setHeader('Access-Control-Allow-Origin', '*');
Expand Down Expand Up @@ -123,7 +124,12 @@ module.exports = function handleImageSizes(req, res, next) {
if (originalImageBuffer.length <= 0) {
throw new NoContentError();
}
return imageTransform.resizeFromBuffer(originalImageBuffer, {withoutEnlargement: requestUrlFileExtension !== '.svg', ...imageDimensionConfig, format});
return imageTransform.resizeFromBuffer(originalImageBuffer, {
withoutEnlargement: requestUrlFileExtension !== '.svg',
...imageDimensionConfig,
format,
timeout: RESIZE_TIMEOUT_SECONDS
});
})
.then((resizedImageBuffer) => {
return storageInstance.saveRaw(resizedImageBuffer, req.url);
Expand All @@ -147,3 +153,5 @@ module.exports = function handleImageSizes(req, res, next) {
next(err);
});
};

module.exports.RESIZE_TIMEOUT_SECONDS = RESIZE_TIMEOUT_SECONDS;
2 changes: 1 addition & 1 deletion ghost/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"@tryghost/html-to-plaintext": "0.0.0",
"@tryghost/http-cache-utils": "0.1.11",
"@tryghost/i18n": "0.0.0",
"@tryghost/image-transform": "1.2.11",
"@tryghost/image-transform": "1.3.0",
"@tryghost/importer-handler-content-files": "0.0.0",
"@tryghost/importer-revue": "0.0.0",
"@tryghost/job-manager": "0.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,47 @@ describe('handleImageSizes middleware', function () {
});
});

it('redirects if timeout is exceeded', function (done) {
sinon.stub(imageTransform, 'canTransformFiles').returns(true);

dummyStorage.exists = async function () {
return false;
};

dummyStorage.read = async function () {
return buffer;
};

const error = new Error('Resize timeout');
error.code = 'IMAGE_PROCESSING';

resizeFromBufferStub.throws(error);

const fakeReq = {
url: '/size/w1000/blank.png',
originalUrl: '/blog/content/images/size/w1000/blank.png'
};

const fakeRes = {
redirect(url) {
try {
url.should.equal('/blog/content/images/blank.png');
} catch (e) {
return done(e);
}
done();
},
setHeader() {}
};

handleImageSizes(fakeReq, fakeRes, function next(err) {
if (err) {
return done(err);
}
done(new Error('Should not have called next'));
});
});

it('continues if file exists', function (done) {
dummyStorage.exists = async function (path) {
if (path === '/size/w1000/blank.png') {
Expand Down Expand Up @@ -526,7 +567,12 @@ describe('handleImageSizes middleware', function () {
return done(err);
}
try {
resizeFromBufferStub.calledOnceWithExactly(buffer, {withoutEnlargement: false, width: 1000, format: 'png'}).should.be.true();
resizeFromBufferStub.calledOnceWithExactly(buffer, {
withoutEnlargement: false,
width: 1000,
format: 'png',
timeout: handleImageSizes.RESIZE_TIMEOUT_SECONDS
}).should.be.true();
typeStub.calledOnceWithExactly('png').should.be.true();
} catch (e) {
return done(e);
Expand Down Expand Up @@ -561,7 +607,12 @@ describe('handleImageSizes middleware', function () {
return done(err);
}
try {
resizeFromBufferStub.calledOnceWithExactly(buffer, {withoutEnlargement: true, width: 1000, format: 'webp'}).should.be.true();
resizeFromBufferStub.calledOnceWithExactly(buffer, {
withoutEnlargement: true,
width: 1000,
format: 'webp',
timeout: handleImageSizes.RESIZE_TIMEOUT_SECONDS
}).should.be.true();
typeStub.calledOnceWithExactly('webp').should.be.true();
} catch (e) {
return done(e);
Expand Down Expand Up @@ -596,7 +647,12 @@ describe('handleImageSizes middleware', function () {
return done(err);
}
try {
resizeFromBufferStub.calledOnceWithExactly(buffer, {withoutEnlargement: true, width: 1000, format: 'avif'}).should.be.true();
resizeFromBufferStub.calledOnceWithExactly(buffer, {
withoutEnlargement: true,
width: 1000,
format: 'avif',
timeout: handleImageSizes.RESIZE_TIMEOUT_SECONDS
}).should.be.true();
typeStub.calledOnceWithExactly('image/avif').should.be.true();
} catch (e) {
return done(e);
Expand Down Expand Up @@ -631,7 +687,12 @@ describe('handleImageSizes middleware', function () {
return done(err);
}
try {
resizeFromBufferStub.calledOnceWithExactly(buffer, {withoutEnlargement: true, width: 1000, format: 'webp'}).should.be.true();
resizeFromBufferStub.calledOnceWithExactly(buffer, {
withoutEnlargement: true,
width: 1000,
format: 'webp',
timeout: handleImageSizes.RESIZE_TIMEOUT_SECONDS
}).should.be.true();
typeStub.calledOnceWithExactly('webp').should.be.true();
} catch (e) {
return done(e);
Expand Down Expand Up @@ -666,7 +727,12 @@ describe('handleImageSizes middleware', function () {
return done(err);
}
try {
resizeFromBufferStub.calledOnceWithExactly(buffer, {withoutEnlargement: true, width: 1000, format: 'gif'}).should.be.true();
resizeFromBufferStub.calledOnceWithExactly(buffer, {
withoutEnlargement: true,
width: 1000,
format: 'gif',
timeout: handleImageSizes.RESIZE_TIMEOUT_SECONDS
}).should.be.true();
typeStub.calledOnceWithExactly('gif').should.be.true();
} catch (e) {
return done(e);
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7066,10 +7066,10 @@
"@tryghost/errors" "^1.3.1"
"@tryghost/request" "^1.0.3"

"@tryghost/image-transform@1.2.11":
version "1.2.11"
resolved "https://registry.yarnpkg.com/@tryghost/image-transform/-/image-transform-1.2.11.tgz#82463d97f8747db6db70165a04e824eed6791fee"
integrity sha512-O4DRZw3lXj9E4LCV8Mm/gMchhyH9rq4/4h4f4+8tb/dhanz7DMhP5yXHH4WBooF2SG1HWV/XITVSY1erFYQFyA==
"@tryghost/image-transform@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@tryghost/image-transform/-/image-transform-1.3.0.tgz#e68e630c4e42e1af193a18894a864e9e2da9fc1f"
integrity sha512-WQFSMh1eAWbZqiheMR5TuTOTll4RDRKZ5p/JIOvejiBzgu/OLBLGKrFKpPb9JSVySTFxpj1dInKmMu8z1so7nQ==
dependencies:
"@tryghost/errors" "^1.2.26"
fs-extra "^11.0.0"
Expand Down