| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Server.Context
Description
The per-request context the serve path reads through, and the handler monad over it.
Mount dispatch (Ecluse.Server) matches a request to one MountBinding — a
mount's complete ecosystem wiring — then runs the route's handler in Handler,
a reader over a RequestCtx pairing that binding with the composition-root Env.
A handler reads its per-mount dependencies (the classifier, the packument-serve
dependencies, the error renderer, the path prefix) and the shared composition root
from that one context, rather than taking them as explicit arguments threaded down
the pipeline.
RequestCtx is a concrete record with plain accessors (ctxEnv, ctxMount),
matching the concrete App newtype: there is no Has-class indirection. The
handler monad layers over the same katip base as App, so a
structured log call composes uniformly across the service and request layers.
This module sits below Ecluse.Server (dispatch) and Ecluse.Server.Pipeline (the packument handler) so both can share these types without an import cycle; the binding is constructed at the composition root (see Ecluse).
Synopsis
- data PackumentDeps = PackumentDeps {
- pdPrivateBaseUrl :: Text
- pdPublicBaseUrl :: Text
- pdMountBaseUrl :: Text
- pdMirrorTarget :: Text
- pdRules :: [PrecededRule]
- pdEffectfulRules :: [PrecededEffectfulRule]
- pdTarballHostPolicy :: TarballHostPolicy
- pdAllowedInternalHosts :: LoweredHostSet
- pdLimits :: Limits
- pdInboundToken :: Maybe Secret
- pdNow :: IO UTCTime
- pdHelp :: Maybe HelpMessage
- pdMinIntegrity :: MinIntegrity
- data MountBinding = MountBinding {}
- data RequestCtx = RequestCtx {
- ctxEnv :: Env
- ctxMount :: MountBinding
- newtype Handler a = Handler {
- unHandler :: ReaderT RequestCtx (KatipContextT IO) a
- runHandler :: RequestCtx -> Handler a -> IO a
Packument-serve dependencies
data PackumentDeps Source #
The per-mount inputs the serve handlers need beyond the composition-root
Env: the two upstream endpoints, the mount's externally-visible base URL, the
mirror-target endpoint, its resolved rule policy, the edge auth token, the
wall-clock source, and the operator help message.
These are a mount-level concern, resolved at the composition root (a separate
concern) and carried on the mount's MountBinding; a handler reads exactly what it
needs to decide and serve from the RequestCtx it runs in. Both the packument and
the tarball paths share these deps — the tarball path additionally gates one
version and enqueues a mirror job to pdMirrorTarget — so the name is retained for
continuity rather than narrowed to one route.
Constructors
| PackumentDeps | |
Fields
| |
Mount binding
data MountBinding Source #
A mount: a path prefix bound to a registry, carrying that registry's
complete ecosystem wiring. Dispatch matches a request's leading path segments
to bindingPrefix, strips them, and routes the remainder through the rest of the
binding (see Ecluse.Server).
The prefix is a NonEmpty list of segments ("npm" :| [] for a /npm mount):
every registry is path-mounted, so a root mount — which would force a URL change
on every consumer the day a second ecosystem is added — is unrepresentable
rather than merely discouraged. Bundling the classifier, serve dependencies, and
renderer into one record means a mount cannot be half-wired: there is no default
to fall back to.
Constructors
| MountBinding | |
Fields
| |
Per-request context
data RequestCtx Source #
The context one request is served through: the composition-root Env paired
with the MountBinding the request matched. A concrete record with plain
accessors — ctxEnv and ctxMount — so a handler reads the shared root and its
per-mount wiring from one place rather than as explicit arguments.
Dispatch builds it once per request (see Ecluse.Server); the handler reads it
through the Handler reader.
Constructors
| RequestCtx | |
Fields
| |
Instances
| MonadReader RequestCtx Handler Source # | |
Defined in Ecluse.Server.Context Methods ask :: Handler RequestCtx # local :: (RequestCtx -> RequestCtx) -> Handler a -> Handler a # reader :: (RequestCtx -> a) -> Handler a # | |
The handler monad
The request hot path's monad: a reader over the per-request RequestCtx
layered on katip's logging context.
A newtype over so its instances
are this module's to control and call sites name one concrete monad. The derived
instances give reader access to the context (ReaderT RequestCtx (KatipContextT IO)MonadReader RequestCtx), arbitrary
effects (MonadIO), the unlift capability (MonadUnliftIO) the serve path's
concurrently/bracket need, and the katip classes (Katip, KatipContext)
so a structured log call composes — over the same base as App, so the
service and request layers log uniformly.
The katip base is a reader, never a StateT, so logging context behaves
correctly across the serve path's concurrent fetches (see
docs/architecture/technology-stack.md → "Key Decisions").
Constructors
| Handler | |
Fields
| |
Instances
| MonadIO Handler Source # | |
Defined in Ecluse.Server.Context | |
| Applicative Handler Source # | |
| Functor Handler Source # | |
| Monad Handler Source # | |
| Katip Handler Source # | |
| KatipContext Handler Source # | |
Defined in Ecluse.Server.Context Methods getKatipContext :: Handler LogContexts Source # localKatipContext :: (LogContexts -> LogContexts) -> Handler a -> Handler a Source # getKatipNamespace :: Handler Namespace Source # localKatipNamespace :: (Namespace -> Namespace) -> Handler a -> Handler a Source # | |
| MonadUnliftIO Handler Source # | |
Defined in Ecluse.Server.Context | |
| MonadReader RequestCtx Handler Source # | |
Defined in Ecluse.Server.Context Methods ask :: Handler RequestCtx # local :: (RequestCtx -> RequestCtx) -> Handler a -> Handler a # reader :: (RequestCtx -> a) -> Handler a # | |
runHandler :: RequestCtx -> Handler a -> IO a Source #
Run a Handler against the RequestCtx dispatch built for the request,
yielding the underlying IO action Warp's continuation runs in. This is the
boundary where the serve path's Handler code is discharged to IO.
The katip context is initialised with the request's dd object (the resolved
service identity and, since the WAI server span is active by now, its trace/span ids
— see Ecluse.Telemetry.Correlation), so every line a handler emits carries dd for
trace-to-log correlation; a handler narrows the namespace or adds
package/version/rule context with katip's combinators on top as it logs.