This PR contains the work done to rename the _Web_ package as _Infrastructure_, to provide a clear naming and purpose to this particular package within the project. To provide further details about the work: * Infrastructure * Asset fingerprinting: an FNV-1a token derived from the static files directory, appended as ?v= to asset URLs so deploys bust caches; pre-rendered pages also revalidate via weak ETags. * New middlewares: fixed-window RateLimitMiddleware (per-client budgets keyed by trusted X-Forwarded-For or remote address) and VaryMiddleware (Accept-Encoding on every response); SecurityHeadersMiddleware now also stamps error responses. * Auto-generated HEAD endpoints, cache max-age configuration, and Docker build/Compose refinements. * Protocols and scaffolding: Asset/AssetExtension, the Page protocol (viewport, stylesheets, scripts, versioned URLs), and LocalizedRequestContext. * Rate limiter's counter store swapped from an actor to a Mutex (no executor hop per request) with amortized batch eviction instead of O(n²) scans under client floods. * FingerprintAssets reports unreadable files to a logger instead of silently producing a token that never busts their cache. Reviewed-on: rock-n-code/loud-amsterdam#25 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2.3 KiB
2.3 KiB
Infrastructure
The shared Hummingbird toolkit the Loud services build on: declarative routing, hardened HTTP middlewares, pre-rendered localized HTML responses, and the page and asset scaffolding.
Overview
The package provides, grouped by role:
| Role | Types |
|---|---|
| Routing | RouterController, RouteCollectionBuilder, the addController extension on RouterMethods |
| Middlewares | SecurityHeadersMiddleware, VaryMiddleware, RateLimitMiddleware, LocalizationMiddleware, NotFoundMiddleware |
| Pages and assets | Page, Asset, AssetExtension, FingerprintAssets |
| Responses | CachedHTMLResponse, LocalizedHTMLCollectionResponse |
| Contexts | LocalizedRequestContext |
Design rules
The package holds only what every service can reuse; anything a service owns is injected, never referenced:
- No site-specific content. No page markup, no asset catalog, no
Bundle.modulelookups. A type that needs a service's content takes it as a parameter: thebundle:whose String Catalog names the supported languages (LocalizationMiddleware,LocalizedHTMLCollectionResponse,NotFoundMiddleware), thedocument:closure that builds a page for a locale, and themetadatarequirement through which aPageconformer supplies its icon links and theme colors. - Services fill the gaps once, via extensions. A service restores its convenient call sites with retroactive extensions — the Website's
Page+Defaults,LocalizationMiddleware+Defaults, andNotFoundMiddleware+Defaultsare the pattern to follow. - Method structs. Single-operation types such as
FingerprintAssetshold their lifetime-fixed configuration ininitand take only per-call inputs incallAsFunction.
Layout
Sources are split by visibility, then by kind, one type per file:
Sources/Public/<Kind>/ public API (Protocols, Middlewares, Responses, …)
Sources/Internal/<Kind>/ implementation details (e.g. FNV1aHash)
Tests/Cases/… mirrors the source layout
Tests/Utils/… stubs and test-only extensions
Requirements
- Swift 6.3 toolchain (
swift-tools-version:6.3). - macOS 15, matching the sibling
LocalizationandPersistencepackages (the services deploy to Linux containers; the packages carry no UI platforms).