natswebgateway

package module
v0.0.0-...-cc523b4 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

README

NATS Web Gateway

An open-source Caddy module that exposes explicitly configured NATS services and streams to HTTP clients.

The project will initially provide:

  • HTTP request/reply routes backed by NATS subjects
  • NATS Service API (ADR-32) compatible behavior
  • Server-Sent Events for bounded, policy-controlled subscriptions
  • authentication and authorization delegated to NATS, including Auth Callout-backed OAuth deployments
  • per-security-context NATS connections that preserve NATS account and subject permissions
  • production-oriented limits, observability, cancellation, and graceful shutdown

The project is at an early implementation stage. See ARCHITECTURE.md for binding design rules, THREAT_MODEL.md for trust boundaries and protocol security decisions, docs/adr for accepted architecture decisions, and the tasks directory for the ordered backlog.

Declared JSON and Caddyfile route schemas, mapping options, limits, and fail-closed validation rules are documented in docs/configuration.md. Supported HTTP-to-NATS authentication mappings and their proof-of-possession and termination semantics are documented in the credential adapter guide. Optional propagation of the server-authenticated NATS user is documented in the downstream identity guide. Core NATS live-stream guarantees, limits, and SSE configuration are documented in Core NATS live SSE.

The gateway provisions an instance-owned, least-privilege NATS connection, tracks reconnect readiness, and drains deterministically across overlapping Caddy reloads. Configure credentials through Caddy placeholders backed by a secret source; never embed production credentials in checked-in configuration.

Request/reply examples

The Go orders service demonstrates a concurrency-safe in-memory create-or-replace and lookup API, validated JSON replies, deterministic domain errors, and optional Accept negotiation. The Go image service returns a bounded PNG with a fixed safe content type. Their matching Caddyfile, JSON configuration, and curl examples are in the configuration guide.

The Go Pets services demonstrate complete REST-style and RPC-style JSON APIs using the supported NATS Service API library. Their Caddyfile declares every HTTP route and subject explicitly. The shared in-memory state is concurrency-safe but non-production and resets whenever the process restarts.

Development workflow

Use the repository task lifecycle skills:

  • $choose-task recommends the next eligible task without changing the repository.
  • $start-task OSS-NNN creates or resumes an isolated task worktree and opens it in a new VS Code window.
  • $implement-task OSS-NNN implements and verifies the task from that worktree, performs a senior Go review, and opens a pull request.
  • $close-task OSS-NNN verifies the human-reviewed merge and safely removes the worktree and merged branch.

Repository agents never merge pull requests. A human reviews and merges each PR before $close-task performs cleanup.

Build and verification

Go 1.26.6 or newer is required. Development tools are pinned in go.mod and run without global installation through the canonical Mage interface:

go tool mage build       # build/custom Caddy binary
go tool mage test        # fast unit tests
go tool mage testRace    # race-enabled tests
go tool mage coverage    # coverage/coverage.out and coverage.html
go tool mage integration # protocol-boundary suite
go tool mage lint        # formatting, module, vet, and static analysis
go tool mage security    # module integrity and vulnerability checks
go tool mage sbom        # dist/nats-web-gateway.cdx.json
go tool mage verify      # normal pre-PR gate
go tool mage ci          # authoritative merge gate
go tool mage clean       # remove only build/, coverage/, and dist/

The first invocation may download pinned Go modules, tools, and container images. Tests themselves do not use public network services. go tool mage integration builds Linux binaries for the host architecture, starts the pinned local Caddy, NATS, and ADR-32 example-service containers from compose.yml, waits for the real protocol boundaries, runs the integration-tagged tests, and removes the environment. Docker Compose or Podman Compose is required.

Local integration environment

The environment binds only to loopback:

Component Address Purpose
Caddy http://127.0.0.1:18080/health Loads the local gateway module and exercises its handler chain.
NATS client nats://127.0.0.1:14222 Pinned NATS server used for request/reply tests.
NATS monitoring http://127.0.0.1:18222/healthz NATS readiness endpoint.
ADR-32 example demo.echo Echoes payloads and returns ADR-32 error code 4001 for payload error.
Pets examples pets.rest.> / pets.rpc.* REST-style and RPC-style ADR-32 services with bounded JSON payloads.

For interactive development, first build the integration binaries with go tool mage integration or go tool mage ci, then use the same checked-in orchestration directly:

The credentials in integration/local/nats-server.conf are deliberately weak, checked-in fixtures. They are restricted to the example subjects, must never be reused outside this loopback-only environment, and must not be treated as a deployment configuration. The gateway fixture can publish only declared application subjects and subscribe only to its NATS inbox. A separate discovery fixture can access the exact $SRV.PING, $SRV.INFO, and $SRV.STATS scopes used by compatibility tests; $SRV.* is not exposed through Caddy. Each example service can consume only its application and ADR-32 control subjects and publish only replies.

The root package is the thin Caddy module boundary. Transport-independent route enforcement, credential presentation, and HTTP/NATS translation live under internal/routes, internal/credentials, and internal/translation respectively so they remain testable without Caddy or network processes.

Licence

Apache License 2.0. See LICENSE.

Documentation

Overview

Package natswebgateway implements the NATS Web Gateway Caddy HTTP handler.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CoreSSE

type CoreSSE struct {
	BufferMessages    int            `json:"buffer_messages"`
	BufferBytes       int64          `json:"buffer_bytes"`
	HeartbeatInterval caddy.Duration `json:"heartbeat_interval"`
	MaxDuration       caddy.Duration `json:"max_duration"`
	MaxConnections    int            `json:"max_connections"`
}

CoreSSE declares bounded runtime policy for an ephemeral Core NATS stream.

type DownstreamIdentity

type DownstreamIdentity struct {
	Source        string `json:"source"`
	Header        string `json:"header"`
	MaxValueBytes int    `json:"max_value_bytes"`
}

DownstreamIdentity declares a NATS-authenticated attribute to add to service requests. The configured header is generated by the gateway and can never be populated from the HTTP request.

type Handler

type Handler struct {
	NATS          NATSConnection `json:"nats"`
	RouteProfiles []RouteProfile `json:"route_profiles,omitempty"`
	Routes        []Route        `json:"routes"`
	// contains filtered or unexported fields
}

Handler is the NATS Web Gateway Caddy HTTP middleware.

Routes are validated before Caddy begins serving. HTTP-to-NATS execution is introduced by later tasks.

func (Handler) CaddyModule

func (Handler) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information for Handler.

func (*Handler) Cleanup

func (h *Handler) Cleanup() error

Cleanup drains and closes only this handler instance's connection. This permits old and new Caddy configurations to overlap safely during reloads.

func (*Handler) Provision

func (h *Handler) Provision(ctx caddy.Context) error

Provision compiles routes and establishes this handler instance's operator connection when at least one route uses it. Protected-only handlers connect lazily with each request's adapted security context.

func (*Handler) Ready

func (h *Handler) Ready() bool

Ready reports whether this instance currently has a usable NATS connection. It is deliberately separate from process liveness.

func (Handler) ServeHTTP

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error

ServeHTTP executes the first matching declared request/reply route. Requests outside this handler's declared surface continue through the Caddy chain.

func (*Handler) UnmarshalCaddyfile

func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

UnmarshalCaddyfile adapts nats_web_gateway route blocks into JSON-equivalent configuration.

func (Handler) Validate

func (h Handler) Validate() error

Validate rejects unsafe, incomplete, or ambiguous route configuration.

type NATSConnection

type NATSConnection struct {
	URLs           []string       `json:"urls"`
	Username       string         `json:"username,omitempty"`
	Password       string         `json:"password,omitempty"`
	ConnectTimeout caddy.Duration `json:"connect_timeout,omitempty"`
	ReconnectWait  caddy.Duration `json:"reconnect_wait,omitempty"`
	MaxReconnects  int            `json:"max_reconnects,omitempty"`
	DrainTimeout   caddy.Duration `json:"drain_timeout,omitempty"`
}

NATSConnection declares the operator-owned connection used by routes which do not carry an end-user security context. Protected-route connections are introduced separately with credential adapters.

type Parameter

type Parameter struct {
	Source  string `json:"source"`
	Name    string `json:"name"`
	Pattern string `json:"pattern"`
}

Parameter declares the sole HTTP source and accepted grammar for a template value.

type Response

type Response struct {
	Mode                 string         `json:"mode"`
	Headers              []string       `json:"headers,omitempty"`
	ContentType          string         `json:"content_type,omitempty"`
	Representations      []string       `json:"representations,omitempty"`
	NegotiateAccept      bool           `json:"negotiate_accept,omitempty"`
	ServiceErrorStatuses map[string]int `json:"service_error_statuses,omitempty"`
}

Response declares safe HTTP behavior for a NATS reply.

type Route

type Route struct {
	Name                string               `json:"name"`
	Path                string               `json:"path"`
	Methods             []string             `json:"methods"`
	Profile             string               `json:"profile,omitempty"`
	Clear               []string             `json:"clear,omitempty"`
	Extend              *RouteExtensions     `json:"extend,omitempty"`
	Subject             string               `json:"subject"`
	Parameters          map[string]Parameter `json:"parameters,omitempty"`
	RequestHeaders      []string             `json:"request_headers,omitempty"`
	Timeout             caddy.Duration       `json:"timeout"`
	MaxRequestBodyBytes int64                `json:"max_request_body_bytes"`
	MaxReplyBytes       int64                `json:"max_reply_bytes"`
	Response            Response             `json:"response"`
	StreamMode          string               `json:"stream_mode"`
	CoreSSE             *CoreSSE             `json:"core_sse,omitempty"`
	SecurityContext     *SecurityContext     `json:"security_context,omitempty"`
}

Route declares one bounded HTTP-to-NATS operation.

type RouteExtensions

type RouteExtensions struct {
	Parameters           map[string]Parameter `json:"parameters,omitempty"`
	RequestHeaders       []string             `json:"request_headers,omitempty"`
	ResponseHeaders      []string             `json:"response_headers,omitempty"`
	Representations      []string             `json:"representations,omitempty"`
	ServiceErrorStatuses map[string]int       `json:"service_error_statuses,omitempty"`
}

RouteExtensions adds entries to inherited collection fields. Ordinary route fields replace inherited collections; clear removes them before validation.

type RouteProfile

type RouteProfile struct {
	Name    string `json:"name"`
	Extends string `json:"extends,omitempty"`
	Route
}

RouteProfile is a named, reusable collection of route policy. Identity and HTTP matching fields deliberately cannot be inherited.

type SecurityContext

type SecurityContext struct {
	Mechanism          credentials.Mechanism `json:"mechanism"`
	MaxCredentialBytes int                   `json:"max_credential_bytes,omitempty"`
	MaxConnections     int                   `json:"max_connections"`
	IdleTimeout        caddy.Duration        `json:"idle_timeout"`
	MaxLifetime        caddy.Duration        `json:"max_lifetime"`
	DownstreamIdentity *DownstreamIdentity   `json:"downstream_identity,omitempty"`
}

SecurityContext declares credential adaptation and bounded connection ownership for a protected route.

Directories

Path Synopsis
cmd
adr32-example command
Command adr32-example runs the non-production NATS service used by the local integration environment.
Command adr32-example runs the non-production NATS service used by the local integration environment.
auth-callout command
Command auth-callout is a test-only NATS Auth Callout service backed by OAuth2 token introspection.
Command auth-callout is a test-only NATS Auth Callout service backed by OAuth2 token introspection.
auth-echo command
Command auth-echo is the least-privilege application fixture for OSS-020.
Command auth-echo is the least-privilege application fixture for OSS-020.
examples
images-service command
Command images-service demonstrates a binary NATS service for the gateway configuration in docs/configuration.md.
Command images-service demonstrates a binary NATS service for the gateway configuration in docs/configuration.md.
orders-service command
Command orders-service is a small stateful NATS request/reply service for the gateway configuration shown in docs/configuration.md.
Command orders-service is a small stateful NATS request/reply service for the gateway configuration shown in docs/configuration.md.
pets-service command
Command pets-service runs the non-production REST-style and RPC-style Pets services used by the example and integration environment.
Command pets-service runs the non-production REST-style and RPC-style Pets services used by the example and integration environment.
internal
credentials
Package credentials contains mechanism-specific adapters that translate supported HTTP credential presentations into NATS client authentication options.
Package credentials contains mechanism-specific adapters that translate supported HTTP credential presentations into NATS client authentication options.
routes
Package routes contains declared-route enforcement and subject construction.
Package routes contains declared-route enforcement and subject construction.
translation
Package translation contains the transport-independent HTTP-to-NATS translation core.
Package translation contains the transport-independent HTTP-to-NATS translation core.

Jump to

Keyboard shortcuts

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