[images]
The /_gio/image optimizer behind <GioImage>: widths, quality, output formats, remote sources and the limits on what one image may cost.
[images]
allowed_widths = [640, 828, 1080, 1200, 1920]
quality = 80
formats = ["webp"]
[[images.remote_patterns]]
hostname = "images.example.com"
pathname = "/uploads/*"Image Optimization shows how <GioImage> uses these settings.
Reference
| Key | Default | Description |
|---|---|---|
enabledboolean | true | Run the optimizer. Turn it off behind an image CDN, or to have no CPU-heavy endpoint: every image is then served as the file it names, at full size, without a srcset. |
allowed_widthsinteger[] | [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840] | The only widths the optimizer resizes to (any other w is a 400), and the <GioImage> srcset candidates. Order does not matter; 0 entries are ignored for srcsets. |
qualityinteger | 75 | Default output quality, 1 to 100. 0 is used as 1 and 101 to 255 as 100; a larger number is a startup error (invalid value: integer `300`, expected u8).<GioImage quality> and the q parameter override it per image. |
formatsstring[] | ["avif", "webp"] | Modern formats to serve when the browser's Accept names them, in order of preference: "avif", "webp" (or "image/avif", "image/webp"). Everything else gets JPEG. AVIF is several times slower to encode than WebP; leave it out to save CPU. |
remote_patternstable[] | [] | Remote sources the optimizer may fetch, one [[images.remote_patterns]] table each (keys below). None by default: a remote src is a 403. |
disk_max_bytesinteger | 536870912 | Size cap of the optimized-image disk cache (512 MiB) under .gio/cache/images; past it the oldest files are deleted. GIO_IMAGE_CACHE_DIR moves the directory. |
max_remote_bytesinteger | 20971520 | Largest remote source downloaded, in bytes (20 MiB). A bigger one is a 400. |
remote_timeout_secsinteger | 30 | Deadline for downloading a whole remote source. The 5-second connect timeout applies either way. |
max_source_dimensioninteger | 10000 | Largest source width or height decoded, in pixels. A larger source is a 500: a small file can declare huge dimensions. |
max_decode_bytesinteger | 268435456 | Most memory decoding one source may allocate (256 MiB). |
remote_patterns
| Key | Default | Description |
|---|---|---|
protocolstring | "https" | "https" or "http"; must equal the source's scheme. |
hostname (required)string | - | An exact host (images.example.com), *.example.com (exactly one more label), or **.example.com (any depth, example.com itself included). An IP address only matches an exact entry, never a wildcard. |
pathnamestring | - | An exact path, or a prefix with a trailing * (/uploads/*). Unset: any path. |
Behavior
/_gio/image takes src (a public/ file as served, /hero.png or /public/hero.png, or an allowed remote URL), w (an allowed width), q (1-100) and f (avif, webp, jpeg, png; a modern format not in formats falls back to negotiation).
| Status | When |
|---|---|
200 | The image, Cache-Control: public, max-age=31536000, immutable, Vary: Accept (private, no-cache for a file a guard admitted this visitor to). |
400 | A width not in allowed_widths, a q outside 1-100, a remote source over max_remote_bytes. |
403 | A remote source no pattern allows, a redirect from a remote source, a path outside public/, a file a guard denies this visitor. |
404 | No src, a missing file, or the optimizer is off. |
500 | A source that fails to download or decode, or exceeds the decode limits. |
The server hands enabled, the sorted widths and the quality to the worker in GIO_IMAGE_CONFIG, so <GioImage> renders only srcsets the optimizer accepts. Those settings are part of the deployment id: changing them drops persisted pages. [[rate_limits]] rules apply to /_gio/image, the only built-in endpoint they cover.
Startup warnings
While the optimizer is on, each limit lifted to 0 logs one line:
| When | Startup warning |
|---|---|
max_remote_bytes = 0 | [images] max_remote_bytes = 0: remote sources of any size are downloaded into memory |
remote_timeout_secs = 0 | [images] remote_timeout_secs = 0: a slow remote source holds its request open indefinitely |
max_source_dimension = 0 | [images] max_source_dimension = 0: a small file declaring huge dimensions can exhaust memory and CPU |
max_decode_bytes = 0 | [images] max_decode_bytes = 0: decoding one source may allocate any amount of memory |
enabled = false logs image optimizer disabled ([images] enabled = false): /_gio/image is not routed at info level.
Examples
Images from a CMS
[[images.remote_patterns]]
hostname = "**.ctfassets.net"
[[images.remote_patterns]]
hostname = "cdn.sanity.io"
pathname = "/images/*"WebP only, to save CPU
[images]
formats = ["webp"]An image CDN in front
[images]
enabled = false # <GioImage> renders plain src; the CDN resizesGood to know
- Optimized images are cached in memory and on disk by source, width, quality and format; a changed source file under the same URL keeps its old variants until they are evicted. Give edited images new names.
- Unknown
formatsare a startup error (unknown variant `png`, expected one of `avif`, `image/avif`, `image/webp`, `webp`): PNG and JPEG are always available throughf=. - A
remote_patternsentry that could never match is a startup error naming its line: aprotocolother than"https"or"http"(lowercase), an emptyhostnameor one with a scheme, path, port or uppercase letters, and apathnamethat does not start with/(pathname "uploads/*" must start with '/', or it matches no path - did you mean "/uploads/*"?). - In a static export there is no optimizer: every image renders its plain
src.
Not configurable
- Path traversal checks. A local
srcmust resolve (symlinks included) to a file insidepublic/. - Redirect blocking. A remote source that answers with a redirect is refused (
403): the redirect target was never checked againstremote_patterns. - Guard enforcement. A local file is held to the
[[guards]]of both URLs it is served at, so the optimizer cannot be used to read a guarded file.
Related
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Added enabled, remote_timeout_secs, max_source_dimension and max_decode_bytes; formats is honored (it also bounds f=). max_remote_bytes = 0 means unlimited (it used to reject every remote image). Lifted limits log a startup warning. |
v0.1.0-beta.6 | remote_patterns are matched on the parsed URL, wildcards match only domains, and pathname is enforced. Fixed decode limits (10000 px, 256 MB). |
v0.1.0-beta.5 | Added disk_max_bytes and max_remote_bytes. |
v0.1.0-beta.1 | Introduced with allowed_widths, quality and remote_patterns. |