server

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package server provides the Echo v5 lifecycle shell a service wraps its HTTP surface in: construction, start, graceful stop, and the generic request-logging middlewares.

The package is deliberately thin. It owns no routes and no middleware chain — those are the service's business. What it owns is the part every service would otherwise reimplement: binding a configured address, starting Echo in a way that unblocks on context cancellation, and shutting it down.

The dependency on Echo v5 is hard and intentional: there is no abstraction over the router. Reach the underlying instance with Echo() to register routes, middlewares, a Binder, a Validator or an error handler; pass an already-configured instance in with WithEcho.

Index

Constants

View Source
const DefaultGracefulTimeout = 10 * time.Second

DefaultGracefulTimeout bounds how long a shutdown waits for in-flight requests before dropping them.

Variables

This section is empty.

Functions

func BaseMiddlewares

func BaseMiddlewares() []echo.MiddlewareFunc

BaseMiddlewares returns the minimum every server wants: panic recovery and the standard security headers.

func BodyDumpLoggingMiddleware

func BodyDumpLoggingMiddleware() echo.MiddlewareFunc

BodyDumpLoggingMiddleware logs request and response bodies at debug level.

It writes bodies verbatim: passwords from a login, refresh tokens, and whatever secrets an integration endpoint accepts all land in the log in clear text. There is no field redaction. Enable it only where the logs live no longer than the debugging session — behind a dev gate, never in an environment whose logs are shipped somewhere and retained.

The response body is capped; the request body is not, and a large upload is buffered whole in memory before being logged.

func BodyDumpLoggingMiddlewareWithSanitizer added in v0.2.1

func BodyDumpLoggingMiddlewareWithSanitizer(s sanitize.Sanitizer) echo.MiddlewareFunc

BodyDumpLoggingMiddlewareWithSanitizer is BodyDumpLoggingMiddleware with a redaction policy applied to both dumps and to the logged URI.

A sanitizer makes this middleware less dangerous, not safe. Bodies are the hardest thing to redact — their shape is arbitrary, so a secret inside one is unrecognizable to a policy written against header names — and a dump that a sanitizer failed to recognize is still a secret in a log file. The dev-gate advice on BodyDumpLoggingMiddleware applies here unchanged.

A nil sanitizer means "redact nothing" and never panics.

func NotFoundHandler

func NotFoundHandler(_ *echo.Context) error

NotFoundHandler is the default handler for unmatched routes. It is exported because a service that registers its own not-found route still wants the same response shape.

func RequestLoggingMiddleware

func RequestLoggingMiddleware() echo.MiddlewareFunc

RequestLoggingMiddleware logs one structured line per request, redacting nothing.

The field names and the REQUEST / REQUEST_ERROR message literals are a contract: log queries and alerts are written against them, so renaming one is a breaking change for every dashboard downstream.

The logged URI includes the query string verbatim. A service whose URLs carry credentials — an OAuth callback holding a live authorization code is the usual one — wants RequestLoggingMiddlewareWithSanitizer instead.

func RequestLoggingMiddlewareWithSanitizer added in v0.2.1

func RequestLoggingMiddlewareWithSanitizer(s sanitize.Sanitizer) echo.MiddlewareFunc

RequestLoggingMiddlewareWithSanitizer is RequestLoggingMiddleware with a redaction policy applied to the logged URI and header set.

A nil sanitizer means "redact nothing", the same as RequestLoggingMiddleware. It is not an error and never panics: a logging middleware must not be the reason a service fails to boot.

Types

type Config

type Config struct {
	// Name identifies the server in log lines. A process typically runs more
	// than one (a public API and an infra port), and the name is what tells
	// their lifecycle messages apart.
	Name string
	Host string
	Port int
	// GracefulTimeout bounds the wait for in-flight requests during shutdown.
	// Zero means DefaultGracefulTimeout.
	//
	// It must exceed the slowest expected in-flight request, and a service
	// draining behind a load balancer should also keep its own drain window
	// longer than the proxy's health-check interval — otherwise the proxy is
	// still routing here when the process tears down.
	GracefulTimeout time.Duration

	// ReadHeaderTimeout caps how long a client may take to send request
	// headers. This is the one that closes slowloris on the header phase.
	ReadHeaderTimeout time.Duration
	// ReadTimeout caps the whole request read, headers and body.
	ReadTimeout time.Duration
	// WriteTimeout caps how long a response may take to write.
	//
	// It must stay above any per-request timeout the service enforces in
	// middleware: a shorter socket deadline severs a slow handler that the
	// application was still willing to run. Leave it zero for SSE or streaming
	// responses, which a fixed write deadline would cut off mid-stream.
	WriteTimeout time.Duration
	// IdleTimeout caps how long an idle keep-alive connection is held open.
	//
	// Keep it above the polling interval of anything that talks to this server
	// on a schedule — health checks, metric scrapes, client heartbeats — or
	// every poll pays for a fresh handshake, which is a cost multiplier rather
	// than a saving.
	IdleTimeout time.Duration
}

Config is the bind configuration for a Server.

func (Config) BuildHostPort

func (c Config) BuildHostPort() string

BuildHostPort renders the address the server binds to.

type Option

type Option func(*Server)

Option configures a Server.

func WithEcho

func WithEcho(e *echo.Echo) Option

WithEcho replaces the Echo instance the server wraps. Use it when the service needs to configure Echo itself (a custom Binder, Validator or HTTPErrorHandler) before any route is registered.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the logger Echo uses.

Echo v5 logs through *slog.Logger. A service logging through something else passes an adapter — the lifecycle lines this package writes itself go through xlog and are unaffected by this option.

func WithNotFoundHandler

func WithNotFoundHandler(h echo.HandlerFunc) Option

WithNotFoundHandler overrides the handler used for unmatched routes.

type Server

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

Server is an Echo instance plus its lifecycle. Construct it with New.

func New

func New(cfg Config, opts ...Option) *Server

New creates a Server bound to cfg.

func (*Server) Echo

func (s *Server) Echo() *echo.Echo

Echo returns the underlying Echo instance, so the service can register routes and middlewares.

It is meant for configuration between New and Start. Mutating the router after Start is not supported.

func (*Server) NotFoundHandlerFunc

func (s *Server) NotFoundHandlerFunc() echo.HandlerFunc

NotFoundHandlerFunc returns the handler this server uses for unmatched routes — NotFoundHandler unless WithNotFoundHandler replaced it. A service registering the not-found route itself reads it from here rather than hardcoding a choice the option was meant to make.

func (*Server) Start

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

Start begins listening and blocks until the server stops. Returns an error only if startup fails, otherwise blocks until shutdown. The provided context is used to stop blocking when canceled. Actual shutdown is performed by the Stop method.

func (*Server) Stop

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

Stop signals the server to shut down.

It does NOT wait for in-flight requests: it cancels the context Start is blocked on and returns immediately, leaving Echo to drain in the goroutine Start launched. A caller that must not tear down its dependencies while requests are still running has to hold its own drain window — closing a database right after Stop returns can fail a request that is still being served.

Jump to

Keyboard shortcuts

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