hyperserve

package module
v2.1.3 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: MIT Imports: 27 Imported by: 0

README

HyperServe

CI Latest release Go reference

HyperServe is a Go server library built on net/http. It brings middleware, typed input, readiness, graceful shutdown, and optional streaming protocols under one server while keeping standard handlers and ServeMux patterns.

Use it when those concerns should share one HTTP boundary and lifecycle. If a service only needs routes and JSON, plain net/http is usually the better choice. HyperServe does not provide an ORM, browser sessions, identity-provider setup, or application authorization.

Quick start

HyperServe requires Go 1.27.

mkdir hello && cd hello
go mod init example.com/hello
go get github.com/osauer/hyperserve/v2@v2.1.3

Save this as main.go:

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"

    "github.com/osauer/hyperserve/v2"
)

func main() {
    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
    defer stop()

    app, err := hyperserve.New()
    if err != nil {
        log.Fatal(err)
    }

    app.HandleFunc("GET /hello/{name}", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %s!\n", r.PathValue("name"))
    })

    if err := app.Run(ctx); err != nil {
        log.Fatal(err)
    }
}

Run go run ., then request http://localhost:8080/hello/Ada. The application turns Ctrl+C or SIGTERM into cancellation; HyperServe follows that context and drains the resources it started. Handlers continue to use r.Context() for request lifetime.

For the next step, use the examples, the production guide, or the Go reference.

The application model

Phase API Purpose
Configure hyperserve.New(hyperserve.With...()) Choose addresses, timeouts, and optional capabilities.
Attach middleware app.Use(...), app.UsePrefix(...) Wrap every request or one path tree in an explicit order.
Register routes app.Handle(...), app.HandleFunc(...) Add ordinary net/http handlers and method-aware ServeMux patterns.
Run app.Run(ctx) Serve until the application context is cancelled or serving exits.

Constructor options are applied from left to right. Register middleware before Run or before the first request through Handler.

Middleware

HyperServe middleware has the standard func(http.Handler) http.Handler shape. New installs request metrics, structured request logging, and panic recovery. Add application policy with Use or UsePrefix; the first registered wrapper is the outermost one. Middleware from another package works without an adapter.

Rate limiting

Create a limiter, then attach it to the path that shares the quota:

import "github.com/osauer/hyperserve/v2/ratelimit"

apiLimit, err := ratelimit.New(ratelimit.Config{
    RequestsPerSecond: 20,
    Burst:             40,
})
if err != nil {
    log.Fatal(err)
}

app.UsePrefix("/api", apiLimit)

One returned middleware value is one quota namespace. Reuse it to share quotas; call ratelimit.New again to isolate them. The default client key is the normalized transport peer from Request.RemoteAddr; forwarding headers are not trusted. Deployments behind known proxies can opt in with ratelimit.TrustedProxyClientKey. See production rate limiting for the trust and capacity rules.

HTTP capabilities

Method-aware patterns and r.PathValue come from net/http.ServeMux. Existing handlers remain ordinary http.Handler values:

app.Handle("/admin/", existingHandler)
handler := app.Handler()

JSONHandler is the short path for typed JSON endpoints. BindJSON, BindQuery, BindForm, and Validate are available when a handler owns its response shape. Start with the binding example and the larger JSON API.

Disk-backed templates and static files are disabled until the application selects a root with WithTemplateDir or WithStaticDir. Static serving is confined with os.Root; registration fails if that boundary cannot be opened. See the static-files example.

Browser security headers are also explicit:

app.Use(hyperserve.SecureWeb(app.Options()))

Options() returns an independent snapshot. Changing it does not reconfigure the running application.

Lifecycle and configuration

The application owns process signals and the root context. Shutdown(ctx) is available when another component coordinates the deadline. MCP over standard input/output uses RunStdio().

Configuration files and process environment are opt-in:

app, err := hyperserve.New(
    hyperserve.WithConfigFile(configPath),
    hyperserve.WithEnvironment(),
    hyperserve.WithAddr("127.0.0.1:8080"),
)

Later options win, so the final address above is an application invariant. A bare New() reads neither source. See the migration guide for retired configuration keys.

Streaming and optional protocols

Need Starting point
Push progress or dashboard updates from one HTTP request Server-Sent Events example
Let client and server send independently WebSocket guide
Expose tools or resources to MCP clients MCP guide

Long-lived handlers must stop when r.Context() is cancelled. WebSocket reconnection, SSE resume policy, MCP authentication, and application authorization remain caller-owned.

Public packages

Import path Purpose
github.com/osauer/hyperserve/v2 HTTP server, middleware, lifecycle, typed input, pages, and MCP wiring
github.com/osauer/hyperserve/v2/auth Provider-neutral request authentication and stable principals
github.com/osauer/hyperserve/v2/jsonrpc Standalone JSON-RPC 2.0 engine
github.com/osauer/hyperserve/v2/mcp MCP handler, transports, discovery, tools, and resources
github.com/osauer/hyperserve/v2/mcp/builtin Opt-in built-in MCP tools and resources
github.com/osauer/hyperserve/v2/ratelimit Bounded rate-limit middleware and trusted-proxy client keys
github.com/osauer/hyperserve/v2/websocket WebSocket upgrader, connection, and outbound dialer

The runtime module has one external dependency, golang.org/x/time, used by the standalone rate-limit gate. WebSocket, JSON-RPC, and MCP are maintained in this repository. That keeps the shipped graph small while making HyperServe responsible for more protocol and security code.

Only the latest stable release receives bug fixes and security updates. Older tags remain available for reproducible builds; there are no parallel maintenance branches.

Examples, generated layouts, commands, and demonstrations are tested but are not stable import surfaces. Repository benchmarks compare revisions on the same machine; HyperServe publishes no universal throughput claim. See API stability and performance methodology.

Scaffold a service

go install github.com/osauer/hyperserve/v2/cmd/hyperserve-init@v2.1.3
hyperserve-init --module github.com/acme/payments
cd payments
go run ./cmd/server

The generated application owns its configuration, lifecycle, and limiter policy. MCP remains off by default because the generator cannot choose the application's authorization policy. See scaffolding.

Documentation

MIT — see LICENSE. Report bugs in GitHub Issues; ask usage questions in Discussions.

Documentation

Overview

Package hyperserve provides a net/http-shaped Go server with lifecycle, middleware, typed request binding, WebSocket integration, and optional Model Context Protocol (MCP) endpoints. Routes use http.ServeMux patterns, and handlers remain http.Handler values.

Use net/http directly when routes plus JSON are sufficient. HyperServe is useful when an application would otherwise assemble the same timeout, recovery, graceful shutdown, readiness, input, and protocol plumbing itself.

Index

Constants

View Source
const (
	// LevelDebug enables debug-level logging with detailed information
	LevelDebug = slog.LevelDebug
	// LevelInfo enables info-level logging for general information
	LevelInfo = slog.LevelInfo
	// LevelWarn enables warning-level logging for important but non-critical events
	LevelWarn = slog.LevelWarn
	// LevelError enables error-level logging for error conditions only
	LevelError = slog.LevelError
)

Log level constants for server configuration. These wrap slog levels to provide a consistent API while hiding the logging implementation details.

Variables

View Source
var (
	Version   = "dev"     // Version from git tags
	BuildHash = "unknown" // Git commit hash
	BuildTime = "unknown" // Build timestamp
)

Build information set at compile time using -ldflags

Functions

func Bind

func Bind(r *http.Request, dst any) error

Bind picks the decoder based on Content-Type:

  • application/json → BindJSON
  • application/x-www-form-urlencoded or multipart/form-data → BindForm
  • otherwise → BindQuery

func BindForm

func BindForm(r *http.Request, dst any) error

BindForm decodes application/x-www-form-urlencoded or multipart/form-data into dst, then runs Validate.

func BindJSON

func BindJSON(r *http.Request, dst any) error

BindJSON decodes the request body as JSON into dst, then runs Validate. dst must be a non-nil pointer to a struct. Returns ValidationError when rules fail, and the wrapped error otherwise (decode error, etc.).

func BindQuery

func BindQuery(r *http.Request, dst any) error

BindQuery decodes URL query parameters into dst (string keys → struct fields by json tag or lowercased name). Slices are populated from repeated keys. Then runs Validate.

func JSONEcho

func JSONEcho[T any]() http.HandlerFunc

JSONEcho is the shorthand for the validate-and-pass-through case: bind the body into T, run validation, and echo the validated value back as the 200 response. Useful for webhook acks, dev stubs, and "did this payload validate?" endpoints where the response shape is the same as the input.

app.POST("/users", hyperserve.JSONEcho[CreateUser]())

Reach for JSONHandler[In, Out] when the response is genuinely different from the input — assigning a server-side ID, lowercasing the email, joining a related record. An identity function is the absence of business logic; JSONEcho says so directly.

Errors follow JSONHandler: *ValidationError → per-field 400 envelope, other bind errors → 400 with {"error": err.Error()}.

func JSONHandler

func JSONHandler[In, Out any](fn func(context.Context, In) (Out, error)) http.HandlerFunc

JSONHandler wraps a typed business function as an http.HandlerFunc. It performs bind + validate + invoke + respond in a single step so handlers only contain business logic.

app.HandleFunc("POST /users", hyperserve.JSONHandler(
    func(ctx context.Context, in CreateUser) (User, error) {
        return createUser(ctx, in)
    },
))

func MCPDev

func MCPDev() mcp.TransportConfig

MCPDev configures MCP with developer tools for local development.

SECURITY WARNING: Only use in development environments. It exposes runtime status, registered routes, middleware layout, and development logs.

Tools provided:

  • mcp__hyperserve__server_control
  • mcp__hyperserve__route_inspector
  • mcp__hyperserve__dev_guide

Resources provided:

  • logs://server/stream, routes://server/all

func MCPObservability

func MCPObservability() mcp.TransportConfig

MCPObservability configures MCP with read-only observability resources. It does not authenticate or authorize requests; applications must protect the MCP endpoint or keep it on a private listener. The preset provides:

  • config://server/current (sanitized server config, no secrets)
  • health://server/status (uptime and health metrics)
  • logs://server/recent (circular buffer of recent log entries)

func RecoveryMiddleware

func RecoveryMiddleware(next http.Handler) http.Handler

RecoveryMiddleware returns a middleware function that recovers from panics in request handlers. Catches panics, logs the error, and returns a 500 Internal Server Error response.

func RequestLoggerMiddleware

func RequestLoggerMiddleware(next http.Handler) http.Handler

RequestLoggerMiddleware returns a middleware function that logs structured request information. It captures and logs:

  • Client IP address
  • HTTP method and URL path
  • Trace ID (if present in X-Trace-ID header)
  • Response status code
  • Request duration
  • Response size in bytes

This middleware is included by default in New. For high-traffic applications, consider the performance impact of logging.

func SetBuiltinPresetHooks

func SetBuiltinPresetHooks(tools, standardResources, observability, developer func(*Server))

SetBuiltinPresetHooks lets mcp/builtin (and only it, in practice) wire itself into the auto-registration flow used by New when MCP is enabled. Pass nil for any preset you don't implement.

func Validate

func Validate(dst any) error

Validate runs `validate:"..."` rules over dst (must be a pointer to a struct or a struct). Returns a *ValidationError when any rule fails, or nil otherwise. Nested structs are recursed into; pointers are dereferenced.

func VersionInfo

func VersionInfo() string

VersionInfo returns formatted version information

Types

type CORSOptions

type CORSOptions struct {
	AllowedOrigins   []string `json:"allowed_origins,omitempty"`
	AllowedMethods   []string `json:"allowed_methods,omitempty"`
	AllowedHeaders   []string `json:"allowed_headers,omitempty"`
	ExposeHeaders    []string `json:"expose_headers,omitempty"`
	AllowCredentials bool     `json:"allow_credentials,omitempty"`
	MaxAgeSeconds    int      `json:"max_age_seconds,omitempty"`
}

CORSOptions captures configuration for Cross-Origin Resource Sharing handling.

type DataFunc

type DataFunc func(r *http.Request) any

DataFunc is a function type that generates data for template rendering. It receives the current HTTP request and returns data to be passed to the template.

type FieldError

type FieldError = validate.FieldError

FieldError describes one failed validation rule. Aliased to the internal/validate type so mcp can produce the same errors when validating typed-tool arguments.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware wraps an HTTP handler. It has the standard net/http middleware shape, so middleware from other packages works without an adapter.

func HeadersMiddleware

func HeadersMiddleware(options Options) Middleware

HeadersMiddleware returns middleware for content-type, framing, referrer, permissions, cross-origin, HSTS, CSP, and configured CORS policy. Automatically handles CORS preflight requests.

func MetricsMiddleware

func MetricsMiddleware(srv *Server) Middleware

MetricsMiddleware returns a middleware function that collects request metrics. It tracks total request count and response times for performance monitoring.

func SecureWeb

func SecureWeb(options Options) Middleware

SecureWeb is a convenience alias for HeadersMiddleware. Pass the Options snapshot from the Server whose TLS, CSP, CORS, and optional Server header policy should be applied.

type MiddlewareStack

type MiddlewareStack []Middleware

MiddlewareStack is a collection of middleware functions that can be applied to an http.Handler. Middleware in the stack is applied in order, with the first middleware being the outermost.

type Option

type Option func(*Server) error

Option configures a Server during construction.

func WithAddr

func WithAddr(addr string) Option

WithAddr sets the address and port for the server to listen on. The address must be in the format "host:port" (e.g., ":8080", "localhost:3000").

func WithCORS

func WithCORS(opts *CORSOptions) Option

WithCORS configures Cross-Origin Resource Sharing options for HTTP handlers.

func WithCSPWebWorkerSupport

func WithCSPWebWorkerSupport() Option

WithCSPWebWorkerSupport enables Content Security Policy support for Web Workers using blob: URLs. This is required for modern web applications that use libraries like Tone.js, PDF.js, or other libraries that create Web Workers with blob: URLs for performance optimization. By default, this is disabled for security reasons and must be explicitly enabled.

func WithConfigFile

func WithConfigFile(path string) Option

WithConfigFile overlays fields present in the JSON file at path. An explicit file is required to exist and contain one valid JSON object. The retired rate_limit and burst fields return an error with migration guidance.

func WithDebugMode

func WithDebugMode() Option

WithDebugMode enables debug logging and additional debug features. (The previously-exported WithLoglevel had no callers; use WithDebugMode or the HS_LOG_LEVEL env var to change the log level.)

func WithDeferredInit

func WithDeferredInit(fn func(context.Context, *Server) error) Option

WithDeferredInit registers a callback that runs after the server listener is active but before the server is marked ready. While the callback is executing, non-health endpoints receive 503.

func WithDeferredInitStopOnFailure

func WithDeferredInitStopOnFailure(stop bool) Option

WithDeferredInitStopOnFailure configures whether the server should shut down if the deferred initialization callback returns an error. Defaults to true.

func WithEnvironment

func WithEnvironment() Option

WithEnvironment overlays supported SERVER_ADDR, HEALTH_ADDR, and HS_* variables. It does not consult HS_CONFIG_PATH; use WithConfigFile when the application chooses to read a file. Present HS_RATE_LIMIT or HS_BURST_LIMIT variables return an error with migration guidance, including empty values.

func WithFIPSMode

func WithFIPSMode() Option

WithFIPSMode selects AES-GCM cipher suites for TLS 1.2 and the P-256/P-384 elliptic curves. It does not restrict TLS 1.3 cipher suites: crypto/tls controls those independently of tls.Config.CipherSuites.

Applications requiring approved algorithms across TLS versions must enable Go's FIPS mode themselves; see https://go.dev/doc/security/fips140. This option does not change process-wide cryptographic policy or establish FIPS 140-3 compliance.

func WithHealthAddr

func WithHealthAddr(addr string) Option

WithHealthAddr sets the address for the separate health server.

func WithHealthServer

func WithHealthServer() Option

WithHealthServer enables the health server on a separate port. The health server provides /healthz/, /readyz/, and /livez/ endpoints for monitoring.

func WithLogLevel

func WithLogLevel(level string) Option

WithLogLevel sets the configured server log level. Accepted values are DEBUG, INFO, WARN, and ERROR.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger gives one Server its logger without changing slog's process-wide default. Configure the handler's level in the application when supplying a custom logger.

func WithMCPBuiltinResources

func WithMCPBuiltinResources(enabled bool) Option

WithMCPBuiltinResources toggles the standard built-in MCP resources: Config, Metrics, System, and ServerLog. ServerHealth belongs to the MCPObservability preset. Default off. Same blank-import requirement as WithMCPBuiltinTools.

func WithMCPBuiltinTools

func WithMCPBuiltinTools(enabled bool) Option

WithMCPBuiltinTools toggles the built-in MCP tools (Calculator plus sandboxed FileRead / ListDirectory when WithMCPFileToolRoot is set). Default off. Requires `_ "github.com/osauer/hyperserve/v2/mcp/builtin"` to be blank-imported by the consumer; otherwise New logs a warning and registers nothing.

func WithMCPDiscoveryFilter

func WithMCPDiscoveryFilter(filter func(toolName string, r *http.Request) bool) Option

WithMCPDiscoveryFilter sets a custom filter function for MCP discovery.

The filter function receives the tool name and HTTP request, allowing for context-aware filtering based on auth tokens, IP addresses, etc.

Example - Hide admin tools from external requests:

app, _ := hyperserve.New(
    hyperserve.WithMCPDiscoveryFilter(func(toolName string, r *http.Request) bool {
        if strings.Contains(toolName, "admin") {
            return strings.HasPrefix(r.RemoteAddr, "10.") ||
                   strings.HasPrefix(r.RemoteAddr, "192.168.")
        }
        return true
    }),
)

func WithMCPDiscoveryPolicy

func WithMCPDiscoveryPolicy(policy mcp.DiscoveryPolicy) Option

WithMCPDiscoveryPolicy sets the discovery policy for MCP tools and resources.

Example:

app, _ := hyperserve.New(
    hyperserve.WithMCPDiscoveryPolicy(mcp.DiscoveryCount),
)

func WithMCPEndpoint

func WithMCPEndpoint(endpoint string) Option

WithMCPEndpoint configures the MCP endpoint path. The path must be a clean, unescaped, non-root literal without a trailing slash and must not be the reserved /.well-known/mcp.json discovery path. Default is "/mcp".

func WithMCPFileToolRoot

func WithMCPFileToolRoot(rootDir string) Option

WithMCPFileToolRoot scopes MCP file tools to rootDir via os.Root, so they cannot read or list paths outside it.

func WithMCPLegacyRoutedSSE deprecated

func WithMCPLegacyRoutedSSE(enabled bool) Option

WithMCPLegacyRoutedSSE enables HyperServe's proprietary X-SSE-* routed transport. It is disabled by default and should be used only while clients migrate to MCP 2026-07-28 Streamable HTTP subscriptions/listen.

Deprecated: use MCP 2026-07-28 Streamable HTTP.

func WithMCPOriginValidator

func WithMCPOriginValidator(validator func(*http.Request) bool) Option

WithMCPOriginValidator overrides MCP's default same-origin browser policy. The validator receives every MCP request and should allow requests without Origin when non-browser clients are expected. Use an explicit allowlist and do not trust Origin as authentication. Passing nil restores the default.

func WithMCPProtocolVersion

func WithMCPProtocolVersion(version string) Option

WithMCPProtocolVersion overrides the MCP protocol version advertised to clients. Empty values reset to mcp.DefaultProtocolVersion.

func WithMCPSupport

func WithMCPSupport(name, version string, configs ...mcp.TransportConfig) Option

WithMCPSupport enables MCP (Model Context Protocol) support on the server. Server name and version identify the server to MCP clients. By default, MCP uses HTTP transport on the "/mcp" endpoint; pass mcp.TransportConfig values to switch to stdio or to install a preset (DeveloperMode, ObservabilityMode).

Example:

hyperserve.New(hyperserve.WithMCPSupport("MyServer", "1.0.0"))

func WithMCPToolCallTimeout

func WithMCPToolCallTimeout(d time.Duration) Option

WithMCPToolCallTimeout sets the per-tool execution budget enforced by the MCP handler. Tools that exceed the timeout return context.DeadlineExceeded to the caller. Go cannot stop an uncooperative function: a tool that ignores its context can continue in a background goroutine until it returns. Zero or negative values fall back to the package default (30s).

func WithOnReady

func WithOnReady(hook func(context.Context, *Server) error) Option

WithOnReady registers hooks that run after deferred initialization succeeds but before the server is marked ready. Hooks are executed sequentially in the order they were registered.

func WithOnShutdown

func WithOnShutdown(hook func(context.Context) error) Option

WithOnShutdown registers a function to be called when the server begins shutdown. Multiple hooks can be registered and are executed sequentially in the order they were added. Hooks are called before the HTTP server shutdown begins, allowing applications to cleanly stop their own goroutines and release resources.

Each hook receives a context with a timeout (typically 5 seconds of the total 10-second shutdown budget). Hooks should respect the context deadline and return promptly. Errors from hooks are logged but don't prevent shutdown from proceeding.

Example:

app, _ := hyperserve.New(
	hyperserve.WithOnShutdown(func(ctx context.Context) error {
		log.Println("Stopping background workers...")
		return stopWorkers(ctx)
	}),
)

func WithOptions

func WithOptions(options Options) Option

WithOptions replaces the current option snapshot with a defensive copy of options. Options passed later to New override this snapshot.

func WithServerHeader

func WithServerHeader(value string) Option

WithServerHeader opts into a Server response header when HeadersMiddleware is installed. The empty string omits identification. Invalid HTTP control bytes cause New to return an error.

func WithStartupBanner

func WithStartupBanner() Option

WithStartupBanner opts into HyperServe's ASCII startup banner. Library consumers are silent by default apart from configured structured logs.

func WithStaticDir

func WithStaticDir(dir string) Option

WithStaticDir sets the directory root used by Server.HandleStatic. The directory is opened and validated when the static route is registered.

func WithTLS

func WithTLS(certFile, keyFile string) Option

WithTLS enables TLS on the server with the specified certificate and key files. Returns a Option that configures TLS settings and validates file existence.

func WithTemplateDir

func WithTemplateDir(dir string) Option

WithTemplateDir sets the directory path where HTML templates are located. Templates in this directory can be used with HandleTemplate and HandleFuncDynamic methods. Returns an error if the specified directory does not exist or is not accessible.

func WithTimeouts

func WithTimeouts(readTimeout, writeTimeout, idleTimeout time.Duration) Option

WithTimeouts configures the HTTP server timeouts. readTimeout: maximum duration for reading the entire request writeTimeout: maximum duration before timing out writes of the response idleTimeout: maximum time to wait for the next request when keep-alives are enabled

type Options

type Options struct {
	Addr              string        `json:"addr,omitempty"`
	EnableTLS         bool          `json:"tls,omitempty"`
	TLSAddr           string        `json:"tls_addr,omitempty"`
	KeyFile           string        `json:"key_file,omitempty"`
	CertFile          string        `json:"cert_file,omitempty"`
	HealthAddr        string        `json:"health_addr,omitempty"`
	ReadTimeout       time.Duration `json:"read_timeout,omitempty"`
	WriteTimeout      time.Duration `json:"write_timeout,omitempty"`
	IdleTimeout       time.Duration `json:"idle_timeout,omitempty"`
	ReadHeaderTimeout time.Duration `json:"read_header_timeout,omitempty"`
	StaticDir         string        `json:"static_dir,omitempty"`
	TemplateDir       string        `json:"template_dir,omitempty"`
	RunHealthServer   bool          `json:"run_health_server,omitempty"`
	FIPSMode          bool          `json:"fips_mode,omitempty"`
	// ServerHeader is emitted by HeadersMiddleware when non-empty.
	ServerHeader string `json:"server_header,omitempty"`
	// MCP (Model Context Protocol) configuration
	MCPEnabled          bool                                        `json:"mcp_enabled,omitempty"`
	MCPEndpoint         string                                      `json:"mcp_endpoint,omitempty"`
	MCPServerName       string                                      `json:"mcp_server_name,omitempty"`
	MCPServerVersion    string                                      `json:"mcp_server_version,omitempty"`
	MCPToolsEnabled     bool                                        `json:"mcp_tools_enabled,omitempty"`
	MCPResourcesEnabled bool                                        `json:"mcp_resources_enabled,omitempty"`
	MCPFileToolRoot     string                                      `json:"mcp_file_tool_root,omitempty"`
	MCPLogResourceSize  int                                         `json:"mcp_log_resource_size,omitempty"`
	MCPToolCallTimeout  time.Duration                               `json:"mcp_tool_call_timeout,omitempty"`
	MCPTransport        mcp.TransportType                           `json:"mcp_transport,omitempty"`
	MCPProtocolVersion  string                                      `json:"mcp_protocol_version,omitempty"`
	MCPLegacyRoutedSSE  bool                                        `json:"mcp_legacy_routed_sse,omitempty"`
	MCPDev              bool                                        `json:"mcp_dev,omitempty"`
	MCPObservability    bool                                        `json:"mcp_observability,omitempty"`
	MCPDiscoveryPolicy  mcp.DiscoveryPolicy                         `json:"mcp_discovery_policy,omitempty"`
	MCPDiscoveryFilter  func(toolName string, r *http.Request) bool `json:"-"` // Custom filter function
	MCPOriginValidator  func(r *http.Request) bool                  `json:"-"`

	// CSP (Content Security Policy) configuration
	CSPWebWorkerSupport bool         `json:"csp_web_worker_support,omitempty"`
	CORS                *CORSOptions `json:"cors,omitempty"`
	// Logging configuration
	LogLevel  string `json:"log_level,omitempty"`
	DebugMode bool   `json:"debug_mode,omitempty"`
	// Banner configuration
	StartupBanner bool `json:"startup_banner,omitempty"`
	BannerColor   bool `json:"banner_color,omitempty"`

	// OnShutdownHooks are functions called when the server begins shutdown.
	// Hooks are executed sequentially in the order they were added, before HTTP server shutdown.
	// Each hook receives a context with timeout and should respect the deadline.
	// Errors from hooks are logged but don't prevent shutdown.
	OnShutdownHooks []func(context.Context) error `json:"-"`

	// OnReadyHooks run after deferred initialization succeeds and before the server is marked ready.
	OnReadyHooks []func(context.Context, *Server) error `json:"-"`
	// StopOnDeferredInitFailure indicates whether the server should shut down if deferred init fails.
	StopOnDeferredInitFailure bool `json:"stop_on_deferred_init_failure,omitempty"`
	// contains filtered or unexported fields
}

Options contains all configuration settings for the HTTP server. Values can be set via WithXXX functions when creating a new server. Bind a configuration file or environment variables explicitly with WithConfigFile or WithEnvironment.

Use DefaultOptions to obtain HyperServe's defaults before modifying a complete snapshot; a zero Options value is not implicitly filled.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns an independent copy of HyperServe's deterministic defaults. Nested slices and CORS configuration are cloned so callers may safely modify the result before passing it to WithOptions.

type SSEMessage

type SSEMessage struct {
	Event string `json:"event"` // Optional: Allows sending multiple event types
	Data  any    `json:"data"`  // The actual data payload
}

SSEMessage represents a Server-Sent Events message with an optional event type and data payload. It follows the SSE format with event and data fields that can be sent to clients.

func NewSSEMessage

func NewSSEMessage(data any) *SSEMessage

NewSSEMessage creates a new SSE message with the given data and a default "message" event type. This is a convenience function for creating standard SSE messages.

func (*SSEMessage) String

func (sse *SSEMessage) String() string

String formats the SSE message according to the Server-Sent Events specification. Multi-line data is emitted as one data field per line.

type Server

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

Server represents an HTTP server with built-in middleware support, health checks, template rendering, and various configuration options.

The Server manages both the main HTTP server and an optional health check server. It handles graceful shutdown, request metrics, and can be extended with custom middleware.

Example:

app, _ := hyperserve.New(
	hyperserve.WithAddr(":8080"),
	hyperserve.WithHealthServer(),
)

app.HandleFunc("/api/users", handleUsers)
if err := app.Run(ctx); err != nil {
	log.Fatal(err)
}

func New

func New(options ...Option) (*Server, error)

New creates a Server with the given options. By default, the server includes request logging, panic recovery, and metrics collection middleware. The server will listen on ":8080" unless configured otherwise.

Options can be provided to customize the server behavior:

app, err := hyperserve.New(
	hyperserve.WithAddr(":3000"),
	hyperserve.WithHealthServer(),             // Enable health checks on :9080
	hyperserve.WithTLS("cert.pem", "key.pem"), // Enable HTTPS
)

Returns an error if any of the options fail to apply.

func (*Server) AddMetrics deprecated

func (srv *Server) AddMetrics(deltaRequests uint64, deltaResponseTime int64)

AddMetrics adds to the request count and cumulative response time in microseconds.

Deprecated: metrics are owned by request middleware. Tests should exercise requests through Handler instead of updating server counters.

func (*Server) CompleteDeferredInit

func (srv *Server) CompleteDeferredInit(ctx context.Context, err error) error

CompleteDeferredInit allows applications to manually finalize deferred initialization after addressing failures. Passing a nil error reruns any pending OnReady hooks and marks the server ready. Passing a non-nil error records the failure and leaves the server in an initializing state.

func (*Server) DELETE

func (srv *Server) DELETE(pattern string, handler http.HandlerFunc)

DELETE registers handler for DELETE requests matching pattern.

func (*Server) GET

func (srv *Server) GET(pattern string, handler http.HandlerFunc)

GET registers handler for GET requests matching pattern.

func (*Server) HEAD

func (srv *Server) HEAD(pattern string, handler http.HandlerFunc)

HEAD registers handler for HEAD requests matching pattern.

func (*Server) Handle

func (srv *Server) Handle(pattern string, handler http.Handler)

Handle registers an http.Handler with the server's ServeMux and records the pattern for route inspection. Use HandleFunc for handler functions.

srv.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))

func (*Server) HandleFunc

func (srv *Server) HandleFunc(pattern string, handler http.HandlerFunc)

HandleFunc registers a handler function using http.ServeMux patterns. Requests pass through global middleware and matching UsePrefix middleware.

func (*Server) HandleFuncDynamic

func (srv *Server) HandleFuncDynamic(pattern, tmplName string, dataFunc DataFunc) error

HandleFuncDynamic registers a handler that renders templates with dynamic data. The dataFunc is called for each request to generate the data passed to the template. Returns an error if template parsing fails.

func (*Server) HandleStatic

func (srv *Server) HandleStatic(pattern string) error

HandleStatic registers a handler that serves files only through an os.Root confined to Options.StaticDir. It returns an error without registering the route if the configured root cannot be opened.

func (*Server) HandleTemplate

func (srv *Server) HandleTemplate(pattern, t string, data any) error

HandleTemplate registers a handler that renders a specific template with static data. Unlike HandleFuncDynamic, the data is provided once at registration time. Returns an error if template parsing fails.

func (*Server) Handler

func (srv *Server) Handler() http.Handler

Handler returns an ordinary http.Handler. Middleware registration remains open until the handler serves its first request, then its compiled plan and the server's middleware configuration are frozen.

func (*Server) IsReady

func (srv *Server) IsReady() bool

IsReady reports whether the server is ready to accept traffic.

func (*Server) IsRunning

func (srv *Server) IsRunning() bool

IsRunning reports whether the server is currently running.

func (*Server) MCPEnabled

func (srv *Server) MCPEnabled() bool

MCPEnabled reports whether MCP support has been initialized for this server.

func (*Server) MCPHandler

func (srv *Server) MCPHandler() *mcp.Handler

MCPHandler returns the MCP handler attached to this server, or nil if MCP is not enabled.

func (*Server) MiddlewareRoutes

func (srv *Server) MiddlewareRoutes() map[string]MiddlewareStack

MiddlewareRoutes returns a snapshot of the registered route-to-middleware mapping. The map and its stacks are independent snapshots.

func (*Server) OPTIONS

func (srv *Server) OPTIONS(pattern string, handler http.HandlerFunc)

OPTIONS registers handler for OPTIONS requests matching pattern.

func (*Server) Options

func (srv *Server) Options() Options

Options returns an independent snapshot of the server configuration. Mutating the returned value does not reconfigure the running server.

func (*Server) PATCH

func (srv *Server) PATCH(pattern string, handler http.HandlerFunc)

PATCH registers handler for PATCH requests matching pattern.

func (*Server) POST

func (srv *Server) POST(pattern string, handler http.HandlerFunc)

POST registers handler for POST requests matching pattern.

func (*Server) PUT

func (srv *Server) PUT(pattern string, handler http.HandlerFunc)

PUT registers handler for PUT requests matching pattern.

func (*Server) RegisterMCPExtension

func (srv *Server) RegisterMCPExtension(ext mcp.Extension) error

RegisterMCPExtension registers all tools and resources from an extension.

func (*Server) RegisterMCPNamespace

func (srv *Server) RegisterMCPNamespace(name string, configs ...mcp.NamespaceConfig) error

RegisterMCPNamespace registers an entire MCP namespace with its tools and resources. Per-tool/per-resource namespace registration goes through this path — callers that need a single tool in a namespace pass it inside a NamespaceConfig rather than reaching for two separate helpers.

func (*Server) RegisterMCPResource

func (srv *Server) RegisterMCPResource(resource mcp.Resource) error

RegisterMCPResource registers a custom MCP resource.

func (*Server) RegisterMCPResourceTemplate

func (srv *Server) RegisterMCPResourceTemplate(template mcp.ResourceTemplate) error

RegisterMCPResourceTemplate registers a custom MCP resource template.

func (*Server) RegisterMCPTool

func (srv *Server) RegisterMCPTool(tool mcp.Tool) error

RegisterMCPTool registers a custom MCP tool. Must be called after server creation but before Run().

func (*Server) RegisteredRoutes

func (srv *Server) RegisteredRoutes() []string

RegisteredRoutes returns a sorted snapshot of patterns registered through Handle, HandleFunc, and the method-aware route helpers.

func (*Server) Run

func (srv *Server) Run(ctx context.Context) error

Run starts the HTTP/HTTPS server and blocks until ctx requests a graceful shutdown, the server exits, or deferred initialization fails. It does not subscribe to process signals; the application owns the lifecycle. The context is a shutdown trigger; its values are not installed as HTTP request values. Use middleware for request-scoped data. Cancellation is a normal shutdown trigger and returns nil when shutdown succeeds. Run returns an error for MCP stdio transport because a context cannot portably interrupt its blocking stdin read; use RunStdio instead. A Server must not be run concurrently or reused after Run returns.

func (*Server) RunStdio

func (srv *Server) RunStdio() error

RunStdio runs an MCP stdio server until stdin reaches EOF. Stdio is kept separate from Run because an arbitrary io.Reader cannot be interrupted by a context without closing an object the application may own.

func (*Server) ServerStart

func (srv *Server) ServerStart() time.Time

ServerStart returns the timestamp when the server began serving.

func (*Server) SetMetrics deprecated

func (srv *Server) SetMetrics(totalRequests uint64, totalResponseTime int64)

SetMetrics overrides the request count and cumulative response time in microseconds.

Deprecated: metrics are owned by request middleware. Tests should exercise requests through Handler instead of overwriting server counters.

func (*Server) Shutdown

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

Shutdown gracefully stops the server within the caller's deadline.

func (*Server) TotalRequests

func (srv *Server) TotalRequests() uint64

TotalRequests returns the total number of requests served so far.

func (*Server) TotalResponseTime

func (srv *Server) TotalResponseTime() int64

TotalResponseTime returns the cumulative response time in microseconds.

func (*Server) Use

func (srv *Server) Use(middleware ...Middleware)

Use registers middleware for every request. Middleware is applied in the order provided, with the first item outermost. Register middleware before calling Run or serving Handler; registration after serving starts panics.

func (*Server) UsePrefix

func (srv *Server) UsePrefix(prefix string, middleware ...Middleware)

UsePrefix registers middleware for a URL path and its child paths at a slash boundary. For example, "/api" matches "/api/users" but not "/apiv2". A non-empty prefix must begin with "/"; malformed prefixes panic at registration time so a security middleware cannot be silently bypassed. Register middleware before calling Run or serving Handler; registration after serving starts panics.

func (*Server) WebSocketUpgrader

func (srv *Server) WebSocketUpgrader() *websocket.Upgrader

WebSocketUpgrader returns a WebSocket upgrader that tracks the upgrade in server telemetry. Use this instead of a standalone Upgrader so WS upgrades land in totalWebSocketUpgrades alongside the totalRequests counter that MetricsMiddleware already maintains for every request.

type StatusError

type StatusError struct {
	Code    int
	Message string
	Err     error
}

StatusError carries an HTTP status code so handler errors can opt into a specific 4xx/5xx response without inventing a new error type per call site. Use NewStatusError, or any error that implements `HTTPStatus() int`.

func NewStatusError

func NewStatusError(code int, message string) *StatusError

NewStatusError builds a StatusError. Message is the public string sent in the response body; pass an empty message to fall back to http.StatusText.

func (*StatusError) Error

func (e *StatusError) Error() string

Error implements error.

func (*StatusError) HTTPStatus

func (e *StatusError) HTTPStatus() int

HTTPStatus is the contract JSONHandler keys off when mapping handler errors to response codes.

func (*StatusError) Unwrap

func (e *StatusError) Unwrap() error

Unwrap exposes the inner cause for errors.Is / errors.As.

type ValidationError

type ValidationError = validate.ValidationError

ValidationError is the aggregate error returned by Validate / Bind* when one or more fields fail their rules. Aliased to internal/validate.

Directories

Path Synopsis
Package auth provides the small authentication boundary needed by HTTP applications without owning identity-provider setup, sessions, or application authorization.
Package auth provides the small authentication boundary needed by HTTP applications without owning identity-provider setup, sessions, or application authorization.
benchmarks
load command
Command load runs a bounded concurrent HTTP workload using only the Go standard library.
Command load runs a bounded concurrent HTTP workload using only the Go standard library.
server command
Command server is the maintained loopback fixture for HyperServe load tests.
Command server is the maintained loopback fixture for HyperServe load tests.
cmd
hyperserve-init command
examples
best-practices command
Package main demonstrates several HyperServe features in one process.
Package main demonstrates several HyperServe features in one process.
binding command
Example: request binding + validation, three ways.
Example: request binding + validation, three ways.
complete command
configuration command
deferred-init command
Deferred-init example.
Deferred-init example.
devops command
Example demonstrating DevOps features: debug logging and MCP resources
Example demonstrating DevOps features: debug logging and MCP resources
enterprise command
Command enterprise demonstrates HyperServe's restricted TLS handshake policy.
Command enterprise demonstrates HyperServe's restricted TLS handshake policy.
hello-world command
htmx-dynamic command
htmx-stream command
json-api command
mcp-basic command
Smallest MCP-enabled HyperServe binary: built-in MCP tools/resources, a custom tool, a custom resource, and a sandboxed file-tool root.
Smallest MCP-enabled HyperServe binary: built-in MCP tools/resources, a custom tool, a custom resource, and a sandboxed file-tool root.
mcp-cli command
Example: Using command-line flags to configure MCP
Example: Using command-line flags to configure MCP
mcp-discovery command
mcp-extensions command
Example: typed MCP tools — one tool per verb.
Example: typed MCP tools — one tool per verb.
mcp-sse command
Example: legacy HyperServe routed SSE.
Example: legacy HyperServe routed SSE.
mcp-stdio command
Package main demonstrates HyperServe's MCP support as a stdio server for Claude Desktop.
Package main demonstrates HyperServe's MCP support as a stdio server for Claude Desktop.
static-files command
web-worker-csp command
websocket-demo command
internal
validate
Package validate implements the tag-driven struct validator used by the root hyperserve package (HTTP request binding) and mcp (typed-tool argument binding).
Package validate implements the tag-driven struct validator used by the root hyperserve package (HTTP request binding) and mcp (typed-tool argument binding).
Package jsonrpc implements JSON-RPC 2.0 request parsing and method dispatch.
Package jsonrpc implements JSON-RPC 2.0 request parsing and method dispatch.
mcp
Package mcp implements the Model Context Protocol (MCP) over JSON-RPC 2.0.
Package mcp implements the Model Context Protocol (MCP) over JSON-RPC 2.0.
builtin
Package builtin provides ready-to-register MCP tools and resources.
Package builtin provides ready-to-register MCP tools and resources.
Package ratelimit provides bounded, per-client HTTP rate limiting.
Package ratelimit provides bounded, per-client HTTP rate limiting.
Package websocket implements RFC 6455 WebSocket servers and outbound clients for net/http applications.
Package websocket implements RFC 6455 WebSocket servers and outbound clients for net/http applications.

Jump to

Keyboard shortcuts

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