Documentation
¶
Overview ¶
Package stdentwritefence provides an HTTP middleware that gives a client read-your-writes consistency against an ro/rw transactor pair without any server-side state.
It glues two seams that already exist in stdent:
stdent.WithReadPromotion — stamped on a request ctx when the incoming request carries a valid, unexpired write-fence cookie; stdent.TransactR / stdent.TransactR0 then route reads to the rw transactor for the duration of that request.
stdent.WithWriteObserver — installed on every request ctx before the handler runs; flipped by stdent.Transact1 on the first successful commit of a non-read-only transactor. The middleware inspects the bit on the way out and pins a fresh cookie on the response when it is set.
The cookie payload is opaque and trivial (a fixed string). All the trust lives in the HMAC signature and the securecookie.MaxAge timestamp embedded by securecookie: the signature prevents a client from forging or extending the window, the embedded timestamp prevents replay past the configured TTL.
The middleware is deliberately independent of any tenancy / per-tenant Postgres role concerns — those live in fx/stdcrpcenttenancyfx and compose on top of stdent. This package only knows about pool routing; it is reusable by any caller that has an ro / rw pair behind two stdent.Transactor instances.
Failure mode for cookie verification is fail-open: any error (cookie missing, malformed, tampered, expired) is treated as "no promotion". The middleware never short-circuits the request and never writes to the response except to add the Set-Cookie header when a write was observed.
Index ¶
Constants ¶
const ( // DefaultCookieName is the cookie name used when [WithCookieName] // is not supplied. The leading underscore mirrors the "host-only, // internal" convention some browsers / proxies treat specially. DefaultCookieName = "_wfence" // DefaultTTL is the read-your-writes window applied to every // pinned response when [WithTTL] is not supplied. Three seconds // is a typical Aurora / RDS reader-lag budget; tune per // deployment. DefaultTTL = 3 * time.Second // MinHashKeyLen is the minimum hash key length enforced at // construction time. 32 bytes is the size of an HMAC-SHA-256 // key — anything shorter weakens the signature for no benefit. MinHashKeyLen = 32 )
Variables ¶
This section is empty.
Functions ¶
func Middleware ¶
Middleware builds an HTTP middleware that implements cookie-based read-your-writes routing on top of stdent's read-promotion and write-observer seams.
hashKey is the HMAC-SHA-256 key used to sign / verify cookies. It MUST be at least MinHashKeyLen bytes; shorter keys panic at construction time (programmer error). The key is the only piece of secret material in the middleware — rotating it soft- invalidates every in-flight cookie, which is the desired behaviour during key rotation.
The returned middleware:
Reads the configured cookie from the request; on a verified, unexpired cookie it calls stdent.WithReadPromotion on ctx so a subsequent stdent.TransactR / stdent.TransactR0 opens against the rw transactor instead of the ro one.
Installs a fresh stdent.WithWriteObserver on ctx so any successful non-read-only commit during the handler is observable.
Wraps the http.ResponseWriter so that the first call to WriteHeader or Write (whichever lands first) — or, failing either, the moment the handler returns — checks the observer and, if a write was observed, adds a freshly-signed cookie to the response headers BEFORE the status line is flushed to the wire.
Types ¶
type Option ¶
type Option func(*config)
Option configures a Middleware.
func WithCookieName ¶
WithCookieName overrides the cookie name used by the middleware. Use this to namespace the cookie per-app when multiple apps share the same domain.
func WithDomain ¶
WithDomain sets the cookie's Domain attribute. Empty (the default) means host-only.
func WithInsecure ¶
func WithInsecure() Option
WithInsecure drops the Secure attribute from the issued cookie. Use only for local development over plain HTTP; production deployments MUST keep Secure on (the default).
func WithSameSite ¶
WithSameSite overrides the cookie's SameSite attribute. Defaults to http.SameSiteLaxMode which is correct for typical web apps; switch to http.SameSiteStrictMode for stricter origin pinning.
func WithTTL ¶
WithTTL overrides the read-your-writes window. The same duration is set both on the issued cookie's Max-Age (browser-side expiry) and on the underlying securecookie codec (server-side validation), so a client cannot extend the window by replaying an old cookie.