A preset is a named set of URL options defined in the server's configuration, such as card for w=400/h=300/fit=cover. URLs carry only the name, preset=card, so changing the definition changes the image every preset=card URL serves, without generating new URLs.

Presets and existing URLs

The signature of a signed URL covers the preset's name, not its definition, so a changed definition keeps every URL valid. The server caches the processed image by the options a preset expands to. /preset=card and /w=400/h=300/fit=cover share one cached copy and one ETag, and changing card changes the cache key of every request that uses it, so those images are processed again.

Removing a definition breaks its URLs, which then answer 400 with unknown preset. A preset defined as an empty string adds no options, so it retires a name while keeping its URLs working: /preset=old/w=600 then serves the same image as /w=600. Decide this per preset. URLs that relied on a preset to add a watermark, crop out part of the image, or cap the size would quietly lose it.

Request defaults

The server's configuration can also set request defaults: one group of options, such as q=80, applied to every request. They apply to the first group, under any presets and options the URL writes there. Request defaults never appear in URLs and can't name presets.

Precedence within a group

Within one group, three layers combine, each overriding the one before it:

  1. The request defaults, in the first group only.
  2. Presets, in the order the URL lists them. In preset=card,dark, dark wins where both set an option.
  3. Options written in the URL.

An option written in the URL overrides presets only in its own group, so /w=300/-/preset=card resizes twice. Presets in separate groups stack, so /preset=frame/-/preset=frame pads twice.

Some options override a related set of options rather than one value, so a URL can't end up with a half-inherited setting. Writing focus in a URL replaces the preset's whole crop target, including an anchor and its offset. Named presets lists these sets.

Clearing inherited values

unset removes a value that a preset or the request defaults set, as if no layer had set it, and takes the options that depended on it along. /preset=card/w=unset drops the width, and the inherited fit and enlarge go too unless h still uses them. Options written in the same URL are kept, so /preset=card/w=unset/fit=cover still fails when nothing else resizes. Because unset has this meaning, no watermark or detection class can be named unset.

In format-q and the encoder options, unset can also come first in the list. jpeg-options=unset,progressive drops the inherited JPEG fields, then turns on progressive.

Request-wide options in presets

Some options, such as format and q, apply to the whole request rather than to one group. A preset's request-wide options apply to the whole request, whichever group the preset is written in. When presets in different groups set the same request-wide option, the later one in the URL wins, and an option written in the URL wins over every preset. A group whose presets add only request-wide options adds no group: with webp defined as format=webp, /w=800/-/preset=webp is the same request as /w=800/format=webp.

format-q and the encoder options combine field by field instead. With a preset of jpeg-options=progressive, a URL's jpeg-options=quant-table:3 keeps progressive. A field set in both takes the later value.

q covers every format that a format-q in the same layer doesn't list, so a URL's q replaces the format-q of presets and the request defaults. In /preset=print/q=80/format-q=avif:50, AVIF is encoded at 50 and every other format at 80, whatever qualities print sets.

Single-group and pipeline presets

A preset without - is a single-group preset. It works like an ingredient: a set of options you could have written yourself, applied to the group it is written in. In /w=800/-/trim=auto/preset=frame, frame pads the image after the trim, in the second group.

A preset containing - is a pipeline preset: a complete recipe that supplies every group of the request. Building recipes from ingredients keeps the ingredients available for requests that need something slightly different:

card   = w=400/h=300/fit=cover
frame  = pad=20/bg=fff
framed = preset=card/-/preset=frame/format=webp

A preset named inside another preset applies to the group it is written in, so frame pads the second group of framed. Request-wide options can still come from anywhere: /preset=framed/format=png and /preset=framed,webp both work. Any other option or preset added to a pipeline preset is rejected, because no rule says which of the recipe's groups it would join.

Pipeline preset errors

With framed defined as above, these requests answer 400 with the message in the response body:

RequestMessage
/preset=framed/w=500pipeline preset "framed" cannot be combined with group options
/w=800/-/preset=framedthe same
/preset=framed/-/sharpen=1the same
/preset=framed,cardpipeline preset "framed" cannot be combined with preset "card", which sets group options
/preset=framed/-/preset=cardthe same
/preset=framed,other, both pipeline presetspipeline presets "framed" and "other" cannot be combined

The URL builder returns the same errors as ImagePipe.Plan.Spec.Issue reasons.

The same rules apply inside preset definitions. A definition that breaks them stops the server at startup, or answers 500 when it comes from a preset lookup.

Stored presets

The Plug and ImagePipe.run/4 can also load presets from a database or another service while they serve a request, through a preset lookup. image_pipe_server reads presets only from its configuration. Stored presets follow the same rules as presets in the configuration, with three differences:

  • A name defined in the configuration always wins, and the lookup is never asked for it.
  • A stored preset may name presets from the configuration, but a preset in the configuration can't name a stored one.
  • Errors in a stored definition show up when a request uses it, as 500, rather than at startup.

Storing presets in a database sets one up.