idempotency

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package idempotency provides HTTP middleware that implements the Idempotency-Key header semantics (Stripe-style). When a client retries a request with the same key + same body, the server replays the original response byte-for-byte instead of executing again.

Storage is provided by the service (per-schema table) via the Store interface. The middleware is opt-in per service via Require(store, ...).

Default behavior: applies to POST/PUT/PATCH/DELETE; bypasses GET/HEAD/OPTIONS. Use WithExclude to bypass specific routes (e.g., auth flows).

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("idempotency: record not found")

ErrNotFound is returned by Store.Get when no record exists for the key.

Functions

func FromContext

func FromContext(ctx context.Context) (uuid.UUID, bool)

FromContext extracts the org_id from the request context. Returns false when absent — middleware will bypass idempotency in that case.

func Require

func Require(store Store, opts ...Option) func(http.Handler) http.Handler

Require returns an HTTP middleware that implements Idempotency-Key semantics.

func WithOrgID

func WithOrgID(ctx context.Context, orgID uuid.UUID) context.Context

WithOrgID returns a context carrying the org_id for idempotency lookups. The service's auth middleware should call this after extracting org_id from the JWT/API-key.

Types

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is an in-memory Store for testing only.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

func (*MemoryStore) Get

func (m *MemoryStore) Get(ctx context.Context, orgID uuid.UUID, key string) (*Record, error)

func (*MemoryStore) Put

func (m *MemoryStore) Put(ctx context.Context, rec *Record) error

type Option

type Option func(*config)

func WithExclude

func WithExclude(routes ...string) Option

WithExclude bypasses the middleware for the given routes. Format: "METHOD /path" (e.g., "POST /v1/auth/login").

type Record

type Record struct {
	OrgID           uuid.UUID
	Key             string
	RequestHash     string
	ResponseStatus  int
	ResponseBody    []byte
	ResponseHeaders map[string][]string
	CreatedAt       time.Time
	ExpiresAt       time.Time
}

Record captures a server response keyed by (org_id, key).

type Store

type Store interface {
	Get(ctx context.Context, orgID uuid.UUID, key string) (*Record, error)
	Put(ctx context.Context, rec *Record) error
}

Store persists idempotency records per-tenant.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL