server

package
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package server adapts the engine to network protocols and serves it.

Handler is the HTTP protocol adapter (milestone 2): a thin http.Handler that maps a real HTTP request onto the engine's normalized request and the engine's response back onto the wire. gRPC is served too, over the same engine, using a document's descriptorSet (spec §3.4) to translate protobuf wire bytes to and from the engine's proto3-JSON message model with dynamic messages — no generated stubs. GraphQL is served over HTTP (GraphQL-over-HTTP): the adapter derives the operation type and name from the query document and returns the engine's data/errors/extensions. When a GraphQL server carries a schema (spec §3.5), it is loaded to answer introspection queries (__schema/__type) so tooling can explore the mock; this is additive and never changes how a normal request resolves. WebSocket is served over an HTTP upgrade: the connection is routed once at establishment (an unroutable path is refused, not accepted, spec §5.9), then every client message resolves against the operation, keyed by a per-connection call counter.

Serve runs the standalone-server serving profile of openmock-dev/openmock's docs/serving.md — port resolution (§2), one listener per server in a document (all four v0.2 protocols), and the admin/discovery API (§3: GET /servers, GET /health, POST /reset).

A gRPC server that carries no descriptorSet (whose messages cannot be decoded without one) is reported as unbound in the admin topology.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Handler

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

Handler is the HTTP protocol adapter (milestone 2): an http.Handler bound to one document server that maps a real HTTP request onto the engine's normalized request model and the engine's response back onto the wire. It is a thin layer — all matching, templating, and state live in the engine.

One Handler serves one named server of a document; a serving process mounts a Handler per HTTP server, all sharing a single *engine.Engine so the call counters (keyed by server name) stay coherent.

func NewHandler

func NewHandler(eng *engine.Engine, serverName string) *Handler

NewHandler returns an HTTP adapter that resolves requests as the named server of eng's document.

func (*Handler) ServeHTTP

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

type Options

type Options struct {
	// Bind is the interface mock servers and the admin API listen on.
	// Empty defaults to 127.0.0.1 (loopback); "0.0.0.0" exposes beyond it.
	Bind string
	// Ports maps server name to an explicit port (rung 1 of §2), from
	// --port / OPENMOCK_PORTS.
	Ports map[string]int
	// AdminPort is the admin API port; 0 uses the default 4400. Use
	// AdminPortEphemeral to request an OS-assigned admin port.
	AdminPort int
	// AdminPortEphemeral binds the admin API on an OS-assigned port
	// (--admin-port 0), reported via Logf and Server.AdminAddr.
	AdminPortEphemeral bool
	// Logf receives startup diagnostics (the name -> port topology, §2). Nil
	// discards them.
	Logf func(format string, args ...any)
	// BaseDir is the directory a gRPC server's descriptorSet path is resolved
	// against (spec §3.4/§14). Empty means the current directory. The CLI
	// sets it to the document's directory.
	BaseDir string
}

Options configures a standalone HTTP Server (docs/serving.md).

type Server

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

Server is a running standalone HTTP server for one document: an http.Server per HTTP server in the document, all backed by one engine, plus the admin API. Create it with Serve; stop it with Shutdown.

func Serve

func Serve(doc *engine.Document, opts Options) (*Server, error)

Serve resolves ports (§2), binds an HTTP listener for every HTTP server in doc, mounts the admin API (§3), and starts serving in the background. It returns once every listener is bound (so the admin GET /health is immediately truthful) or with an error if any bind fails — ports resolved from configuration or a hint fail loudly rather than being silently reassigned (§2). Non-HTTP servers are reported as unbound in the topology.

func (*Server) AdminAddr

func (s *Server) AdminAddr() string

AdminAddr is the admin API's bound address (host:port), useful when the admin port was ephemeral.

func (*Server) Err

func (s *Server) Err() error

Err returns the first non-graceful serving error, if any.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the mock servers (HTTP and gRPC) and the admin API. A gRPC server is drained with GracefulStop, falling back to a hard Stop if ctx is cancelled first.

func (*Server) Topology

func (s *Server) Topology() []ServerInfo

Topology returns the served name -> port mapping (admin GET /servers).

func (*Server) Wait

func (s *Server) Wait()

Wait blocks until every server has stopped (after Shutdown).

type ServerInfo

type ServerInfo struct {
	Name      string  `json:"name"`
	Type      string  `json:"type"`
	Transport *string `json:"transport"`
	Port      *int    `json:"port"`
	URL       *string `json:"url"`
	Note      string  `json:"note,omitempty"`
}

ServerInfo is one entry of the admin GET /servers topology (docs/serving.md §3). Port and URL are null (nil) for a server this process does not bind. Note, when present, is the human-readable reason a server is not bound — an extra field, which §3 permits ("Servers MAY add fields; consumers MUST ignore fields they do not know").

Jump to

Keyboard shortcuts

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