Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Supported dynamic image resizing for LocalFileStorage(#10184)
refs #10181 * Added initial handleImageSizes middleware * Implemented saveRaw method on local file storage * Wired up handleImageSizes middleware * Implemented delete for LocalFileStorage * Removed delete method from theme Storage class * Deleted sizes directory when theme is activated * Ensured that smaller images are not enlarged * Renamed sizes -> size * Exited middleware as early as possible * Called getStorage as late as possible * Updated image sizes middleware to handle dimension paths * Revert "Deleted sizes directory when theme is activated" This reverts commit 9204dfcc73a6a79d597dbf23651817bcbfc59991. * Revert "Removed delete method from theme Storage class" This reverts commit b45fdb405a05faeaf4bd87e977c4ac64ff96b057. * Revert "Implemented delete for LocalFileStorage" This reverts commit a587cd6bae45b68a293b2d5cfd9b7705a29e7bfa. * Fixed typo Co-Authored-By: allouis <fabien@allou.is> * Redirected to original image if no image_sizes config * Refactored redirection because rule of three * Updated comments * Added rubbish tests * Added @todo comment for handleImageSizes tests * Added safeResizeImage method to image manipulator * Used image manipulator lib in image_size middleware
- Loading branch information
Showing
6 changed files
with
160 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
core/server/web/shared/middlewares/image/handle-image-sizes.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
const path = require('path'); | ||
const image = require('../../../../lib/image'); | ||
const storage = require('../../../../adapters/storage'); | ||
const activeTheme = require('../../../../services/themes/active'); | ||
|
||
const SIZE_PATH_REGEX = /^\/size\/([^/]+)\//; | ||
|
||
module.exports = function (req, res, next) { | ||
if (!SIZE_PATH_REGEX.test(req.url)) { | ||
return next(); | ||
} | ||
|
||
const [sizeImageDir, requestedDimension] = req.url.match(SIZE_PATH_REGEX); | ||
const redirectToOriginal = () => { | ||
const url = req.originalUrl.replace(`/size/${requestedDimension}`, ''); | ||
return res.redirect(url); | ||
}; | ||
|
||
const imageSizes = activeTheme.get().config('image_sizes'); | ||
// CASE: no image_sizes config | ||
if (!imageSizes) { | ||
return redirectToOriginal(); | ||
} | ||
|
||
const imageDimensions = Object.keys(imageSizes).reduce((dimensions, size) => { | ||
const {width, height} = imageSizes[size]; | ||
const dimension = (width ? 'w' + width : '') + (height ? 'h' + height : ''); | ||
return Object.assign({ | ||
[dimension]: imageSizes[size] | ||
}, dimensions); | ||
}, {}); | ||
|
||
const imageDimensionConfig = imageDimensions[requestedDimension]; | ||
// CASE: unknown dimension | ||
if (!imageDimensionConfig || (!imageDimensionConfig.width && !imageDimensionConfig.height)) { | ||
return redirectToOriginal(); | ||
} | ||
|
||
const storageInstance = storage.getStorage(); | ||
// CASE: unsupported storage adapter but theme is using custom image_sizes | ||
if (typeof storageInstance.saveRaw !== 'function') { | ||
return redirectToOriginal(); | ||
} | ||
|
||
storageInstance.exists(req.url).then((exists) => { | ||
if (exists) { | ||
return; | ||
} | ||
|
||
const originalImagePath = path.relative(sizeImageDir, req.url); | ||
|
||
return storageInstance.read({path: originalImagePath}) | ||
.then((originalImageBuffer) => { | ||
return image.manipulator.safeResizeImage(originalImageBuffer, imageDimensionConfig); | ||
}) | ||
.then((resizedImageBuffer) => { | ||
return storageInstance.saveRaw(resizedImageBuffer, req.url); | ||
}); | ||
}).then(() => { | ||
next(); | ||
}).catch(next); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
module.exports = { | ||
get normalize() { | ||
return require('./normalize'); | ||
}, | ||
get handleImageSizes() { | ||
return require('./handle-image-sizes'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
core/test/unit/web/middleware/image/handle-image-sizes_spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
const should = require('should'); | ||
const handleImageSizes = require('../../../../../server/web/shared/middlewares/image/handle-image-sizes.js'); | ||
|
||
// @TODO make these tests lovely and non specific to implementation | ||
describe('handleImageSizes middleware', function () { | ||
it('calls next immediately if the url does not match /size/something/', function (done) { | ||
const fakeReq = { | ||
url: '/size/something' | ||
}; | ||
// CASE: second thing middleware does is try to match to a regex | ||
fakeReq.url.match = function () { | ||
throw new Error('Should have exited immediately'); | ||
}; | ||
handleImageSizes(fakeReq, {}, function next() { | ||
done(); | ||
}); | ||
}); | ||
|
||
it('calls next immediately if the url does not match /size/something/', function (done) { | ||
const fakeReq = { | ||
url: '/url/whatever/' | ||
}; | ||
// CASE: second thing middleware does is try to match to a regex | ||
fakeReq.url.match = function () { | ||
throw new Error('Should have exited immediately'); | ||
}; | ||
handleImageSizes(fakeReq, {}, function next() { | ||
done(); | ||
}); | ||
}); | ||
|
||
it('calls next immediately if the url does not match /size/something/', function (done) { | ||
const fakeReq = { | ||
url: '/size//' | ||
}; | ||
// CASE: second thing middleware does is try to match to a regex | ||
fakeReq.url.match = function () { | ||
throw new Error('Should have exited immediately'); | ||
}; | ||
handleImageSizes(fakeReq, {}, function next() { | ||
done(); | ||
}); | ||
}); | ||
}); |