Architecture

Last updated

This page shows, in one overview diagram, how the layers of node-image-server relate and what each one owns.

System Overview

graph TB
    Client[Client] --> Worker[Cloudflare Worker<br>worker/index.js]
    Client --> Nginx[Nginx<br>config/nginx/nodejs.conf]
    Worker --> Nginx
    Nginx -->|/c/img/| App[Express cluster<br>app/app.ts]
    Nginx -->|/upload/ · /del/ · /| App
    App --> MW[Middlewares<br>app/src/middlewares]
    MW --> Router[Router<br>app/src/router]
    Router --> GET[GetFromPath<br>sharp]
    Router --> POST[PostToPath<br>multer]
    Router --> DEL[DeleteFromPath]
    GET --> Upload[(storage/image/upload)]
    GET --> Cache[(storage/image/cache)]
    POST --> Upload
    DEL --> Trash[(upload/.trash/YYYY-MM-DD)]

Layers

Layer Location Responsibility
CDN worker/index.js Caches for 7 days keyed on URL plus query string; forwards to the origin on a miss
Reverse proxy config/nginx/nodejs.conf proxy_cache for /c/img/, security headers, dotfile denial, HTTP method and upload size limits
Process management app/app.json, app/app.ts PM2 loads via ts-node; the primary forks workers and respawns them on exit
Middleware app/src/middlewares/ Parsing, CORS, request logging, HTML minification, dropping requests without User-Agent
Routing app/src/router/ Dispatches by HTTP method to the GET / POST / DELETE sub-routers
Handlers GetFromPath, PostToPath, DeleteFromPath Conversion and caching, upload, moving to trash
Storage app/storage/image/ upload/ originals, cache/ conversions, upload/.trash/ deleted items

Cross-Cutting Principles

Principle Implementation
Process once Conversions are written as cache files, and the edge layers cache on top
Never hard-delete Deletion always renameSyncs into today's trash
Never upscale Every size parameter is capped at the original dimensions
Access control lives at the edge The app has no authentication; upload and delete are restricted with Nginx allow / deny

Further Reading

中文