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.
- Defining presets: adding presets and request
defaults to
image_pipe_serveror the Plug. - Storing presets in a database: loading definitions while serving a request.
- Named presets: using presets in a URL.
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:
- The request defaults, in the first group only.
- Presets, in the order the URL lists them. In
preset=card,dark,darkwins where both set an option. - 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=webpA 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:
| Request | Message |
|---|---|
/preset=framed/w=500 | pipeline preset "framed" cannot be combined with group options |
/w=800/-/preset=framed | the same |
/preset=framed/-/sharpen=1 | the same |
/preset=framed,card | pipeline preset "framed" cannot be combined with preset "card", which sets group options |
/preset=framed/-/preset=card | the same |
/preset=framed,other, both pipeline presets | pipeline 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.