Image Pipeline

Last updated

This page walks through every step GET /c/img/{path} takes from request to response, and what happens when a step fails.

Steps

Step Behavior Implementation
1. Parse parameters Reads s/size, w/width, h/height, q/quality, o/origin, d/dark, t/type; the short name wins GetFromPath.ts
2. Map the original Replaces /c/img/ with storage/image/upload/ and drops the query string Same
3. PDF / SVG For .pdf / .svg, streams the original and stops streamFile()
4. Normalize format type outside jpeg/jpg/png/avif/webp becomes webp; jpeg becomes jpg Same
5. Build cache path Builds the cache filename from parameters; see Caching Layers Same
6. Original mode With o=1, streams the original and stops streamFile()
7. Cache hit Reads the cache file with readFileSync and returns it on success Same
8. Convert sharp reads the original and its metadata, calls resize() per the Sizing Rules, then encodes sharp
9. Respond and write Sends the response first, then writes the cache file with writeFileSync Same

Encoding

Format sharp call Default quality Content-Type
webp image.webp({ quality }) 75 image/webp
avif image.avif({ quality }) 50 image/avif
jpg image.jpeg({ quality }) 75 image/jpeg
png image.png() Not used image/png

Quality is parseInt-ed and clamped to 0–100.

Streaming Originals

.pdf, .svg, and o=1 stream through createReadStream (8 KB highWaterMark) with Transfer-Encoding: chunked. For o=1, Content-Type follows the extension: .jpg/.jpeg → image/jpeg, .png → image/png, .webp → image/webp, otherwise application/octet-stream. A read error returns an empty 404.

Failure Handling

Case Response
Original missing storage/static/404-light.svg (404-dark.svg with d=1), HTTP status 200
sharp cannot decode or a parameter is invalid (e.g. w=abc) Same
Response headers Content-Type: image/svg+xml, Cache-Control: no-cache, Expires: -1, Pragma: no-cache
中文