Documentation

Image Pipeline

This page walks through GET /c/img/*path: deciding whether to transform, the libvips processing order, and the streamed response.

Routing Decisions

GetFromPath checks these in order and responds on the first match:

Order Condition Behavior
1 Path ends in .pdf Stream the original as application/pdf
2 Path ends in .svg Stream the original as image/svg+xml
3 o=1 Infer MIME from the extension (GetMimeType) and stream the original
4 Local cache file exists Set Content-Type from t and stream the cache file
5 Otherwise Transform with libvips

Every branch first sets 7-day Cache-Control and Expires headers.

Transform Steps

The transform runs in a goroutine under a 30-second timeout:

Step Call Notes
1 os.MkdirAll Create the cache file's directory
2 os.ReadFile → vips.NewImageFromBuffer Read and decode the original
3 GetNewSize → Resize(scale, KernelLanczos3) Scale proportionally with Lanczos3 when the size changes (rules in Sizing Rules)
4 GaussianBlur(GetBlur(b)) Gaussian blur, sigma clamped to 0–100
5 Linear([B], [0]) Brightness: multiply every band by B; a non-numeric B fails the transform
6 ExportJpeg / ExportPng / ExportAvif / ExportWebp Export by t; PNG ignores quality
7 os.WriteFile Write the local cache file

Any failed step returns the 404 placeholder SVG instead (dark variant for d=1 or d=dark) with Cache-Control: no-cache.

Streamed Output

streamImage (in-memory buffer) and streamFile (original file) both respond with Transfer-Encoding: chunked, flushing after each buffer fills:

File size Buffer
≤ 50 KiB 2 KiB
≤ 500 KiB 4 KiB
≤ 2 MiB 8 KiB
Larger 16 KiB

streamFile also sends Content-Length; when the ResponseWriter does not implement http.Flusher, it falls back to a single c.File.

中文