The serverless-image-handler mono repository contains the source code and documentation for the image-handler and image-thumbs AWS Lambda functions.
The Image-handler is a solution Image Handler is a serverless image processing project built with Node.js 18 and the Sharp library. It allows you to dynamically scale images on the fly and serves them through AWS Lambda, AWS CloudFront, and AWS S3.
It aws originally forked from aws-solutions/serverless-image-handler repository, but has been heavily modified to suit our needs.
- Node.js v20.x or later
- Terraform
- Make / npm
- AWS credentials with sufficient permissions to read images from S3
To scale images dynamically on the fly, you can make HTTP requests to the AWS CloudFront distribution URL. The images are fetched from AWS S3, processed using Node.js 20 and Sharp / libvips, and then served through CloudFront.
Example URL:
https://images.t-online.de/4k_hdr.jpg
For more details see the Usage documentation.
The following environment variables are used by the image-handler:
Name | Description |
---|---|
AUTO_WEBP |
Flag if the AUTO WEBP feature should be enabled |
CORS_ENABLED |
Flag if CORS should be enabled |
CORS_ORIGIN |
CORS origin. |
SOURCE_BUCKETS |
S3 Bucket with source images |
To build the package run:
make FUNC=image-handler build
Run tests using the following Make command:
make npm/test
Deploy the infrastructure using Terraform with the following Make command:
make FUNC=image-handler tf
Useful links:
- Image too large with default settings:
2023/02/JPCPt616git7/image.png
The way we process our images does not depend on the file name. The part that copies the images from
the CMS into our delivery bucket will rename all images to image.${extension}
.
When rendering the image, the image-handler will always look for this filename, so it does not matter what the original file name was. e.g.
2023/02/JPCPt616git7/seo-title.png
will be served asimage.png
2023/02/JPCPt616git7/other-usage-different-title.png
will be served asimage.png
resulting in the same response.
- the original solution introduced thumbor cropping in v6
- we have implemented this feature in advance, but with a slightly different syntax:
- The original solution uses
crop=left,top,right,bottom
- We use
crop=left,top,width,height
to be more consistent with the CMS
- The original solution uses
- The original solution uses the
Expires
header to cache images in the browser - Our solution:
- reduces the
Cache-Control: max-age
according to theExpires
header to handle expired content - Also, once the Expires header is reached, the image-handler will return a
http/410 (GONE)
status code
- reduces the
/filters:thumbhash()/
will trigger a hash-based thumbnail generation. See https://evanw.github.io/thumbhash/- The image can be cropped prior to this filter, but will ultimately be resized to
100x100
pixel to generate an efficient thumbnail - The response will be
base64
encoded binary that can be converted viaThumbhash.thumbHashToDataURL()
Within the HTML markup resides the next-data
attribute
Within this data structure there are some image URLs that are not directly intended to be rendered. Consider
them as templates.
Google (and other bots) will find and use this URL nonetheless. This image-handler will replace all calls that
contain template variables /__WIDTH__x0/
with an actual size to mitigate this.
If required once more, they need to be pulled from the original repository:
- Recognition and the corresponding code:
- "Smart Crop" (aka face recognition)
- Content Moderation (e.g. NSFW detection)
- Watermarking/Overlaying
- Secretsmanager and URL signing
- Dynamic S3 bucket selection