Documentation
¶
Overview ¶
Package zerohttp provides configuration structs for zerohttp servers.
The main Config struct holds server configuration including address, TLS settings, lifecycle hooks, and middleware configuration.
Basic Usage ¶
app := zerohttp.New(zerohttp.Config{
Addr: ":8080",
})
TLS Configuration ¶
app := zerohttp.New(zerohttp.Config{
TLS: zerohttp.TLSConfig{
Addr: ":8443",
CertFile: "server.crt",
KeyFile: "server.key",
},
})
Package zerohttp provides a lightweight, zero-dependency HTTP framework for building REST APIs and web applications in Go.
Built on Go's standard library, zerohttp adds essential features for production services: routing, middleware, request binding, validation, rendering, metrics, and more - all without external dependencies.
Quick Start ¶
Create and start a server in a few lines:
package main
import (
"log"
"net/http"
zh "github.com/alexferl/zerohttp"
)
func main() {
app := zh.New()
app.GET("/hello/{name}", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
name := zh.Param(r, "name")
return zh.Render.JSON(w, http.StatusOK, zh.M{"message": "Hello, " + name})
}))
log.Fatal(app.Start())
}
Routing ¶
zerohttp uses Go's standard net/http.ServeMux for routing, supporting path parameters, wildcards, and method-based routes:
app := zh.New()
// Path parameters
app.GET("/users/{id}", getUserHandler)
// Wildcards
app.GET("/files/{path...}", serveFileHandler)
// Route groups with middleware
app.Group(func(api zh.Router) {
api.Use(basicauth.New(basicauth.Config{
Credentials: map[string]string{"admin": "secret"},
}))
api.GET("/admin/dashboard", dashboardHandler)
})
Handlers ¶
Handlers return errors for cleaner error handling. Errors are automatically converted to appropriate HTTP responses:
app.POST("/users", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
var req CreateUserRequest
if err := zh.BindAndValidate(r, &req); err != nil {
return err // Returns 400 for binding errors, 422 for validation errors
}
user, err := createUser(req)
if err != nil {
return err // Returns 500 for unexpected errors
}
return zh.Render.JSON(w, http.StatusCreated, user)
}))
Request Binding ¶
Bind request data to structs using Bind:
JSON Binding ¶
Parse JSON request bodies with strict validation (rejects unknown fields):
var req struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := zh.Bind.JSON(r.Body, &req); err != nil {
return err // Returns 400 Bad Request
}
Form Binding ¶
Parse application/x-www-form-urlencoded data:
var form struct {
Username string `form:"username"`
Password string `form:"password"`
Remember bool `form:"remember"`
Tags []string `form:"tags"` // Supports slices
}
if err := zh.Bind.Form(r, &form); err != nil {
return err
}
Multipart Form Binding ¶
Handle file uploads with multipart/form-data:
var form struct {
Description string `form:"description"`
Document *zh.FileHeader `form:"document"` // Single file
Images []*zh.FileHeader `form:"images"` // Multiple files
}
// maxMemory: bytes to store in memory before temp files
if err := zh.Bind.MultipartForm(r, &form, 32<<20); err != nil {
return err
}
// Access uploaded files
if form.Document != nil {
file, err := form.Document.Open()
if err != nil {
return err
}
defer file.Close()
data, _ := io.ReadAll(file)
// Process file data...
}
Query Parameter Binding ¶
Bind query parameters to structs with query tags:
var req struct {
Query string `query:"q"`
Category string `query:"category"`
Tags []string `query:"tags"` // Multiple values: ?tags=a&tags=b
Page int `query:"page"`
Limit int `query:"limit"`
IsActive *bool `query:"is_active"` // Pointer = optional
}
if err := zh.Bind.Query(r, &req); err != nil {
return err
}
Embedded Structs ¶
Reuse common patterns like pagination:
type Pagination struct {
Page int `query:"page"`
Limit int `query:"limit"`
}
type ListRequest struct {
Pagination
Search string `query:"search"`
}
var req ListRequest
if err := zh.Bind.Query(r, &req); err != nil {
return err
}
Path Parameters ¶
Type-safe path parameter extraction:
// Basic string extraction
id := zh.Param(r, "id")
// Typed extraction (returns error if invalid)
itemID, err := zh.ParamAs[int](r, "itemID")
if err != nil {
return zh.NewProblemDetail(http.StatusBadRequest, "Invalid itemID").Render(w)
}
// With default value
category := zh.ParamOrDefault(r, "category", "all")
Individual Parameter Extraction ¶
Extract single query parameters:
// With type conversion userID, err := zh.QueryParamAs[int](r, "user_id") // With default value page := zh.QueryParamAsOrDefault(r, "page", 1) // Simple string sort := zh.QueryParam(r, "sort")
Custom Binders ¶
Implement the Binder interface for custom binding logic:
type MyBinder struct{}
func (b *MyBinder) JSON(r io.Reader, dst any) error {
decoder := json.NewDecoder(r)
decoder.UseNumber() // Use json.Number instead of float64
return decoder.Decode(dst)
}
// Replace default binder
zh.Bind = &MyBinder{}
Type Conversion ¶
Form and query binders automatically convert string values to Go types:
string -> "name=John" -> "John" int -> "age=25" -> 25 bool -> "active=true" -> true []string -> "tags=a&tags=b" -> ["a", "b"] []int -> "ids=1&ids=2" -> [1, 2] *string -> "optional=" or missing -> nil or ""
Supported types: string, all int/uint types, float32, float64, bool, slices, and pointers.
Validation ¶
Validate structs using struct tags with the built-in validator:
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2,max=50"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"min=13,max=120"`
Password string `json:"password" validate:"required,min=8"`
}
if err := zh.Validate.Struct(&req); err != nil {
// Returns ValidationErrors map keyed by field name
return err
}
Available Validators ¶
Core validators: required, omitempty, eq, ne
String validators: min, max, len, contains, startswith, endswith, excludes, alpha, alphanum, lowercase, uppercase, ascii, printascii, numeric, oneof
Numeric validators: min, max, gt, lt, gte, lte
Format validators: email, uuid, datetime, base64, hexadecimal, hexcolor, e164, semver, jwt, boolean, json
Network validators: ip, ipv4, ipv6, cidr, hostname, uri, url
Collection validators: unique, each
Combining Validators ¶
Multiple validators can be combined with commas:
type Product struct {
Name string `validate:"required,min=2,max=100"`
Price float64 `validate:"required,gt=0"`
Tags []string `validate:"unique,each,min=2,max=20"`
}
Nested Struct Validation ¶
Validation automatically recurses into nested structs:
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
}
type Person struct {
Name string `validate:"required"`
Address Address // validated recursively
}
For slices of structs, use the each validator:
type Order struct {
Items []LineItem `validate:"each"` // validates each LineItem
}
Pointer Fields ¶
Pointer fields are dereferenced before validation. Use omitempty to make optional:
type User struct {
Name *string `validate:"omitempty,min=2"` // nil or valid
Nickname *string `validate:"required,min=2"` // must not be nil
}
Custom Validators ¶
Register custom validators with V.Register:
zh.Validate.Register("even", func(value reflect.Value, param string) error {
if value.Kind() != reflect.Int {
return fmt.Errorf("even only validates integers")
}
if value.Int()%2 != 0 {
return fmt.Errorf("must be even")
}
return nil
})
type Config struct {
Port int `validate:"required,even"`
}
Validation Error Handling ¶
Validate.Struct returns a ValidationErrors map keyed by field name:
if err := zh.Validate.Struct(&user); err != nil {
var ve zh.ValidationErrors
if errors.As(err, &ve) {
errs := ve.FieldErrors("Email")
for _, e := range errs {
fmt.Println(e) // "required" or "must be a valid email"
}
if ve.HasErrors() {
pd := zh.NewValidationProblemDetail("Validation failed", ve)
pd.Render(w)
}
}
}
Errors use JSON field names when available.
Response Rendering ¶
Render responses using Render:
// JSON response
zh.Render.JSON(w, http.StatusOK, zh.M{"users": users})
// Text response
zh.Render.Text(w, http.StatusOK, "Hello, World!")
// HTML response
zh.Render.HTML(w, http.StatusOK, "<h1>Hello</h1>")
// File download
zh.Render.File(w, r, "/path/to/file.pdf")
// Redirect
zh.Render.Redirect(w, r, "/new-path", http.StatusFound)
Error Handling ¶
zerohttp converts errors to RFC 9457 Problem Details responses:
// Return custom problem detail return zh.NewProblemDetail(http.StatusNotFound, "User not found").Render(w) // Return validation errors (422 Unprocessable Entity) return zh.Validate.Struct(&req)
Middleware ¶
Apply middleware at application, group, or route level:
// Application-level
app.Use(cors.New(cors.DefaultConfig))
app.Use(requestid.New())
// Route-level
app.GET("/admin", adminHandler,
basicauth.New(basicauth.Config{
Credentials: map[string]string{"admin": "secret"},
}),
)
Available middleware: cors, basicauth, jwtauth, ratelimit, compress, requestlogger, circuitbreaker, timeout, and more in subpackages. See package middleware for complete documentation.
Metrics ¶
Prometheus-compatible metrics are automatically collected:
// Metrics exposed at /metrics by default
app := zh.New() // No configuration needed
// Access registry in handlers
reg := metrics.GetRegistry(r.Context())
counter := reg.Counter("orders_total", "status")
counter.WithLabelValues("completed").Inc()
See package metrics for detailed metrics documentation.
Pluggable Features ¶
zerohttp provides pluggable interfaces for optional features. Configure via Config:
app := zh.New(zh.Config{
Validator: myValidator,
Tracer: myTracer,
Extensions: zh.ExtensionsConfig{
AutocertManager: myCertManager,
HTTP3Server: myH3Server,
SSEProvider: mySSEProvider,
WebSocketUpgrader: myWSUpgrader,
WebTransportServer: myWTServer,
},
})
Custom Validator ¶
Bring your own struct validator (e.g., go-playground/validator/v10):
type myValidator struct {
v *validator.Validate
}
func (m *myValidator) Struct(dst any) error {
return m.v.Struct(dst)
}
func (m *myValidator) Register(name string, fn func(reflect.Value, string) error) {
m.v.RegisterValidation(name, func(fl validator.FieldLevel) bool {
err := fn(fl.Field(), fl.Param())
return err == nil
})
}
app := zh.New(zh.Config{Validator: &myValidator{v: validator.New()}})
Distributed Tracing ¶
Integrate your preferred tracing solution:
app := zh.New(zh.Config{Tracer: myTracer})
app.Use(tracer.New(myTracer))
// In handlers
span := trace.SpanFromContext(r.Context())
span.SetAttributes(trace.String("user.id", userID))
See package trace for interface details.
Auto-TLS ¶
Automatic certificate management via Let's Encrypt:
manager := &autocert.Manager{
Cache: autocert.DirCache("/tmp/certs"),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.com"),
}
app := zh.New(zh.Config{
Extensions: zh.ExtensionsConfig{
AutocertManager: manager,
},
})
app.StartAutoTLS()
HTTP/3 ¶
HTTP/3 support over QUIC:
h3Server := &http3.Server{
Addr: ":443",
Handler: app,
}
app.SetHTTP3Server(h3Server)
app.StartTLS("cert.pem", "key.pem") // HTTP/3 starts automatically
Server-Sent Events ¶
Real-time unidirectional streaming:
app := zh.New(zh.Config{
Extensions: zh.ExtensionsConfig{
SSEProvider: sse.NewDefaultProvider(),
},
})
app.GET("/events", func(w http.ResponseWriter, r *http.Request) error {
provider := app.SSEProvider()
stream, err := provider.New(w, r)
if err != nil {
return err
}
defer stream.Close()
for i := 0; i < 10; i++ {
stream.Send(sse.Event{Name: "message", Data: []byte("hello")})
time.Sleep(1 * time.Second)
}
return nil
})
WebSocket ¶
Real-time bidirectional communication. Bring your own library:
app := zh.New(zh.Config{
Extensions: zh.ExtensionsConfig{
WebSocketUpgrader: &myUpgrader{upgrader: websocketUpgrader},
},
})
app.GET("/ws", func(w http.ResponseWriter, r *http.Request) error {
ws, err := app.WebSocketUpgrader().Upgrade(w, r)
if err != nil {
return err
}
defer ws.Close()
// Handle connection...
return nil
})
WebTransport ¶
Low-latency bidirectional communication over HTTP/3:
h3 := &http3.Server{Addr: ":8443", Handler: app}
wtServer := &webtransport.Server{H3: h3, CheckOrigin: func(r *http.Request) bool { return true }}
webtransport.ConfigureHTTP3Server(h3)
app.SetWebTransportServer(wtServer)
app.ListenAndServeTLS("cert.pem", "key.pem")
Configuration ¶
Configure the server using Config:
app := zh.New(zh.Config{
Server: &http.Server{
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
MaxHeaderBytes: 1 << 20,
},
})
Server Lifecycle ¶
Start the server with various methods:
// HTTP
app.Start() // Uses config.Addr or :8080
app.ListenAndServe() // Uses configured address
// HTTPS
app.StartTLS("cert.pem", "key.pem")
app.StartAutoTLS() // Let's Encrypt
// With graceful shutdown
go app.Start()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := app.Shutdown(ctx); err != nil {
log.Fatal(err)
}
Testing ¶
The zhtest package provides fluent test helpers:
func TestGetUser(t *testing.T) {
app := setupRouter()
req := zhtest.NewRequest(http.MethodGet, "/users/123").Build()
w := zhtest.Serve(app, req)
zhtest.AssertWith(t, w).
Status(http.StatusOK).
Header("Content-Type", "application/json").
JSONPathEqual("name", "John Doe")
}
See package zhtest for detailed testing documentation.
Short Aliases ¶
For convenience, common types have short aliases:
zh.M // map[string]any - for JSON responses zh.B // Bind (alias for Bind) zh.R // Render (alias for Render) zh.V // Validate (alias for Validate)
Package zerohttp provides path parameter extraction with type conversion.
Path parameters are extracted from URL patterns like /users/{id}:
app.GET("/users/{id}", func(w http.ResponseWriter, r *http.Request) error {
// String value
id := zh.Param(r, "id")
// Typed extraction
userID, err := zh.ParamAs[int](r, "id")
if err != nil {
return zh.NewProblemDetail(http.StatusBadRequest, "Invalid ID")
}
// With default
category := zh.ParamOrDefault(r, "category", "all")
// ...
})
Supported types: string, all int/uint types, float32, float64, bool.
Package zerohttp provides query parameter extraction with type conversion.
The Query extractor provides type-safe access to URL query parameters:
// String value
q := zh.QueryParam(r, "search")
// Typed extraction
page, err := zh.QueryParamAs[int](r, "page")
if err != nil {
return err
}
// With default
limit := zh.QueryParamAsOrDefault(r, "limit", 20)
// Struct binding
var req struct {
Search string `query:"search"`
Page int `query:"page"`
}
if err := zh.Bind.Query(r, &req); err != nil {
return err
}
Package zerohttp provides HTTP/3 server support. See Server.ListenAndServeHTTP3.
Package zerohttp provides server lifecycle hooks. See Server.RegisterPreStartupHook, Server.RegisterStartupHook, and Server.RegisterShutdownHook.
Package zerohttp provides metrics server support. See Server.Metrics and Server.MetricsAddr.
Package zerohttp provides SSE provider configuration. See Server.SetSSEProvider and Server.SSEProvider.
Package zerohttp provides TLS and HTTPS server support. See Server.ListenAndServeTLS and Server.StartAutoTLS.
Package zerohttp provides WebSocket upgrader configuration. See Server.SetWebSocketUpgrader and Server.WebSocketUpgrader.
Package zerohttp provides WebTransport server support. See Server.SetWebTransportServer.
Package zerohttp provides HTML template rendering support using Go's standard html/template package.
The TemplateManager simplifies template rendering from embedded filesystems:
//go:embed templates/*
var templatesFS embed.FS
tmpl := zh.NewTemplateManager(templatesFS, "templates/*.html")
app.GET("/", func(w http.ResponseWriter, r *http.Request) error {
return tmpl.Render(w, http.StatusOK, "index.html", zh.M{"title": "Home"})
})
Index ¶
- Constants
- Variables
- func BindAndValidate(r *http.Request, dst any) error
- func BindMultipartFormFiles(r *http.Request, dst any) error
- func DefaultHTTPServer() *http.Server
- func DefaultTLSServer() *http.Server
- func IsBindError(err error) bool
- func IsUnknownFieldError(err error) bool
- func IsValidationError(err error) bool
- func Param(r *http.Request, name string) string
- func ParamAs[T ParamType](r *http.Request, name string) (T, error)
- func ParamAsOrDefault[T ParamType](r *http.Request, name string, defaultVal T) T
- func ParamOrDefault(r *http.Request, name, defaultVal string) string
- func QueryParam(r *http.Request, name string) string
- func QueryParamAs[T ParamType](r *http.Request, name string) (T, error)
- func QueryParamAsOrDefault[T ParamType](r *http.Request, name string, defaultVal T) T
- func QueryParamOrDefault(r *http.Request, name, defaultVal string) string
- func RenderAndValidate(w http.ResponseWriter, status int, data any) error
- type Binder
- type Config
- type ExtensionsConfig
- type FileHeader
- type HandlerFunc
- type LifecycleConfig
- type M
- type MiddlewareFunc
- type ParamExtractor
- type ParamType
- type ProblemDetail
- type QueryExtractor
- type Renderer
- type Router
- type Server
- func (s *Server) Close() error
- func (s *Server) ListenAndServe() error
- func (s *Server) ListenAndServeHTTP3(certFile, keyFile string) error
- func (s *Server) ListenAndServeTLS(certFile, keyFile string) error
- func (s *Server) ListenerAddr() string
- func (s *Server) ListenerTLSAddr() string
- func (s *Server) Logger() log.Logger
- func (s *Server) Metrics() metrics.Registry
- func (s *Server) MetricsAddr() string
- func (s *Server) RegisterPostShutdownHook(name string, hook ShutdownHook)
- func (s *Server) RegisterPostStartupHook(name string, hook StartupHook)
- func (s *Server) RegisterPreShutdownHook(name string, hook ShutdownHook)
- func (s *Server) RegisterPreStartupHook(name string, hook StartupHook)
- func (s *Server) RegisterShutdownHook(name string, hook ShutdownHook)
- func (s *Server) RegisterStartupHook(name string, hook StartupHook)
- func (s *Server) SSEProvider() sse.Provider
- func (s *Server) SetHTTP3Server(server http3.Server)
- func (s *Server) SetSSEProvider(provider sse.Provider)
- func (s *Server) SetValidator(validator Validator)
- func (s *Server) SetWebSocketUpgrader(upgrader websocket.Upgrader)
- func (s *Server) SetWebTransportServer(server webtransport.Server)
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Start() error
- func (s *Server) StartAutoTLS() error
- func (s *Server) StartHTTP3(certFile, keyFile string) error
- func (s *Server) StartTLS(certFile, keyFile string) error
- func (s *Server) Validator() Validator
- func (s *Server) WebSocketUpgrader() websocket.Upgrader
- type ShutdownHook
- type ShutdownHookConfig
- type StartupHook
- type StartupHookConfig
- type TLSConfig
- type TemplateManager
- type TemplateRenderer
- type ValidationError
- type Validator
Constants ¶
const ( DefaultReadTimeout = 10 * time.Second DefaultReadHeaderTimeout = 5 * time.Second DefaultWriteTimeout = 15 * time.Second // DefaultIdleTimeout is explicitly set to 60s. // Note: If IdleTimeout is 0, Go falls back to ReadTimeout. We set this // explicitly to avoid confusion and ensure the intended timeout is used. DefaultIdleTimeout = 60 * time.Second DefaultMaxHeaderBytes = 16 * 1024 // 16 KB -> actual limit is ~20 KB (Go adds +4096) )
Variables ¶
var B = Bind
B is a short alias for Bind.
if err := zh.B.JSON(r.Body, &req); err != nil {
return err
}
var DefaultConfig = Config{ Addr: "localhost:8080", TLS: TLSConfig{ Addr: "localhost:8443", Server: nil, RedirectHTTP: true, }, DisableDefaultMiddlewares: false, DefaultMiddlewares: nil, Recover: recover.DefaultConfig, RequestBodySize: requestbodysize.DefaultConfig, RequestID: requestid.DefaultConfig, RequestLogger: requestlogger.DefaultConfig, SecurityHeaders: securityheaders.DefaultConfig, Metrics: metrics.DefaultConfig, Logger: nil, Server: nil, }
DefaultConfig contains all default values used by Config. Update this file if you want to change system-wide defaults.
var DefaultMultipartMaxMemory int64 = 32 << 20
DefaultMultipartMaxMemory is the default max memory for multipart form parsing in BindAndValidate. This can be changed globally. Default is 32MB.
var Params = &defaultParamsExtractor{}
Params is the default params extractor instance used by the package
var Query = &defaultQueryExtractor{}
Query is the default query extractor instance used by the package
var R = Render
R is a short alias for Render.
return zh.R.JSON(w, http.StatusOK, data)
var V = Validate
V is a short alias for Validate.
if err := zh.V.Struct(&req); err != nil {
return err
}
var Validate = validator.New()
Validate is the default Validator instance used by the package. Use it to validate structs using struct tags:
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
if err := zh.Validate.Struct(&req); err != nil {
// Returns 422 Unprocessable Entity with field errors
return err
}
For convenience, use the V alias or BindAndValidate for combined binding and validation.
Functions ¶
func BindAndValidate ¶ added in v0.18.0
BindAndValidate binds request data based on Content-Type and validates the result. It returns appropriate errors:
- 400 Bad Request for binding failures (malformed JSON, type mismatches)
- 422 Unprocessable Entity for unknown fields or validation failures
Supported Content-Types:
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
- (no content-type) - parses query parameters
Example:
func handler(w http.ResponseWriter, r *http.Request) error {
var req CreateUserRequest
if err := zh.BindAndValidate(r, &req); err != nil {
return err // 400 or 422 auto-detected
}
// ...
}
func BindMultipartFormFiles ¶ added in v0.9.0
BindMultipartFormFiles binds file uploads to struct fields after the main form binding. This is called internally by handler logic when processing multipart forms. Exported for advanced use cases.
func DefaultHTTPServer ¶ added in v0.74.0
DefaultHTTPServer returns a new http.Server with sensible defaults. Use this as a base when you need to customize only specific server fields while keeping the other defaults.
Example:
srv := zerohttp.DefaultHTTPServer()
srv.ReadTimeout = 30 * time.Second
app := zerohttp.New(zerohttp.Config{
Server: srv,
})
func DefaultTLSServer ¶ added in v0.74.0
DefaultTLSServer returns a new http.Server with sensible defaults for TLS. Use this as a base when you need to customize only specific TLS server fields while keeping the other defaults.
Example:
srv := zerohttp.DefaultTLSServer()
srv.ReadTimeout = 30 * time.Second
app := zerohttp.New(zerohttp.Config{
TLS: TLSConfig{
Server: srv,
},
})
func IsBindError ¶ added in v0.25.0
IsBindError checks if an error is a binding error (should return 400).
func IsUnknownFieldError ¶ added in v0.90.0
IsUnknownFieldError checks if an error is an unknown field error (should return 422).
func IsValidationError ¶ added in v0.18.0
IsValidationError checks if an error is a validation error (should return 422).
func ParamAs ¶ added in v0.10.0
ParamAs extracts and converts a path parameter to type T. Returns an error if the parameter is missing or conversion fails. Supported types: string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool
func ParamAsOrDefault ¶ added in v0.10.0
ParamAsOrDefault extracts and converts a path parameter to type T, returning a default value if the parameter is missing or conversion fails.
func ParamOrDefault ¶ added in v0.10.0
ParamOrDefault is a convenience function that calls Params.ParamOrDefault
func QueryParam ¶ added in v0.11.0
QueryParam is a convenience function that calls Query.QueryParam
func QueryParamAs ¶ added in v0.11.0
QueryParamAs extracts and converts a query parameter to type T. Returns an error if conversion fails. For missing parameters, returns the zero value and no error (use pointer types for optional params). Supported types: string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool
func QueryParamAsOrDefault ¶ added in v0.11.0
QueryParamAsOrDefault extracts and converts a query parameter to type T, returning a default value if the parameter is missing or conversion fails.
func QueryParamOrDefault ¶ added in v0.11.0
QueryParamOrDefault is a convenience function that calls Query.QueryParamOrDefault
func RenderAndValidate ¶ added in v0.18.0
func RenderAndValidate(w http.ResponseWriter, status int, data any) error
RenderAndValidate renders JSON response after validating the data. This catches server-side bugs like missing required fields before sending responses.
If validation fails, it returns a 500 Internal Server Error (server bug).
Example:
func handler(w http.ResponseWriter, r *http.Request) error {
user := User{ID: "...", Name: "John"}
return zh.RenderAndValidate(w, http.StatusOK, user)
}
Types ¶
type Binder ¶
type Binder interface {
// JSON decodes JSON request body into the destination struct.
// It uses json.NewDecoder with DisallowUnknownFields enabled
// for safer JSON parsing that rejects unknown fields.
JSON(r io.Reader, dst any) error
// Form parses form data from the request body (application/x-www-form-urlencoded)
// and binds it to the destination struct using `form` tags.
// It also parses the query string and includes those values.
Form(r *http.Request, dst any) error
// MultipartForm parses multipart/form-data from the request,
// including file uploads, and binds values to the destination struct.
// The maxMemory parameter controls how much of the form data is stored in memory
// before being written to temp files (similar to http.Request.ParseMultipartForm).
// File uploads are bound to fields of type FileHeader or []FileHeader.
MultipartForm(r *http.Request, dst any, maxMemory int64) error
// Query binds query parameters from the request URL to a destination struct.
// Uses `query` struct tags for field mapping. Fields without tags are mapped
// using snake_case conversion of the field name.
// Returns an error if binding fails due to type mismatch.
Query(r *http.Request, dst any) error
}
Binder handles request binding and parsing for various content types. It provides methods to decode request data into Go structs.
type Config ¶ added in v0.58.0
type Config struct {
// Addr is the address for the HTTP server to listen on.
// Default: "localhost:8080"
Addr string
// Server is the HTTP server instance for plain (non-TLS) traffic.
// Default: preconfigured server listening on "localhost:8080"
Server *http.Server
// Listener allows specifying a custom net.Listener for HTTP traffic (optional).
// Default: nil (system default listener will be created)
Listener net.Listener
// TLS holds the configuration for the HTTPS server.
TLS TLSConfig
// Lifecycle holds the server startup and shutdown hook configuration.
Lifecycle LifecycleConfig
// Logger is the logger instance used by the server and middlewares.
// Default: nil (a default logger will be created if nil)
Logger log.Logger
// DisableDefaultMiddlewares disables all built-in default middlewares when true.
// Default: false (default middlewares are enabled)
DisableDefaultMiddlewares bool
// DefaultMiddlewares is a custom list of middlewares to use. If nil, uses the built-in default middleware list.
// Default: nil (means use built-in defaults)
DefaultMiddlewares []MiddlewareFunc
// Recover holds the configuration for the panic recovery middleware.
Recover recover.Config
// RequestBodySize holds the configuration for the request body size limiting middleware.
RequestBodySize requestbodysize.Config
// RequestID holds the configuration for the request ID generation middleware.
RequestID requestid.Config
// RequestLogger holds the configuration for the HTTP request logging middleware.
RequestLogger requestlogger.Config
// SecurityHeaders holds the configuration for the security headers middleware.
SecurityHeaders securityheaders.Config
// Metrics holds the configuration for the metrics middleware.
Metrics metrics.Config
// Tracer holds the configuration for the tracing middleware.
// Default: DefaultTracerConfig
Tracer tracer.Config
// Validator is an optional struct validator for validating request data.
// Users can inject their own implementation (e.g., github.com/go-playground/validator/v10).
// The validator must implement the Validator interface.
// If nil, the default built-in validator will be used.
// Default: nil
Validator Validator
// Extensions holds optional protocol and feature extensions.
Extensions ExtensionsConfig
}
Config holds server and middleware configuration options for zerohttp.
type ExtensionsConfig ¶ added in v0.58.0
type ExtensionsConfig struct {
// AutocertManager is an optional autocert manager for automatic certificate management (AutoTLS).
// Users can inject their own implementation (e.g., golang.org/x/crypto/acme/autocert.Manager)
// by implementing the AutocertManager interface.
// Default: nil (AutoTLS not enabled unless set)
AutocertManager autocert.Manager
// HTTP3Server is an optional HTTP/3 server instance for handling HTTP/3 traffic over QUIC.
// Users can inject their own HTTP/3 implementation (e.g., quic-go/http3).
// The server must implement the HTTP3Server interface.
// Default: nil (HTTP/3 not enabled unless set)
HTTP3Server http3.Server
// SSEProvider is an optional handler for Server-Sent Events connections.
// Users can set their own provider (e.g., wrapping a custom SSE library).
// If nil, SSE is not available but users can still handle SSE manually in their handlers.
// Default: nil
SSEProvider sse.Provider
// WebSocketUpgrader is an optional handler for WebSocket upgrades.
// Users can set their own upgrader (e.g., wrapping gorilla/websocket).
// If nil, WebSocket is not available but users can still handle
// upgrades manually in their handlers.
WebSocketUpgrader websocket.Upgrader
// WebTransportServer is an optional WebTransport server for handling WebTransport sessions.
// Users can inject their own implementation (e.g., quic-go/webtransport-go).
// The server must implement the WebTransportServer interface.
// If nil, WebTransport support will not be enabled.
// The server will be started automatically when ListenAndServeTLS or Start is called.
// Default: nil
WebTransportServer webtransport.Server
}
type FileHeader ¶ added in v0.9.0
type FileHeader = bind.FileHeader
FileHeader represents an uploaded file in a multipart form. It provides access to the file's metadata and content. This is an alias to internal/bind.FileHeader.
type HandlerFunc ¶
type HandlerFunc func(w http.ResponseWriter, r *http.Request) error
HandlerFunc is a handler function that returns an error. It implements http.Handler, allowing it to be used anywhere a standard HTTP handler is expected.
Errors are automatically converted to appropriate HTTP responses:
- Validation errors return 422 Unprocessable Entity with field details
- Unknown fields return 422 Unprocessable Entity
- Binding errors return 400 Bad Request
- Request too large returns 413 Payload Too Large
- ProblemDetail errors return their specified status code
- All other errors return 500 Internal Server Error
Example:
app.GET("/users/{id}", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
id := zh.Param(r, "id")
user, err := db.GetUser(id)
if err != nil {
return err // Returns 500
}
if user == nil {
return zh.NewProblemDetail(http.StatusNotFound, "User not found").Render(w)
}
return zh.Render.JSON(w, http.StatusOK, user)
}))
func (HandlerFunc) ServeHTTP ¶
func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler interface. It handles all errors directly; no panic propagation is used.
type LifecycleConfig ¶ added in v0.58.0
type LifecycleConfig struct {
// PreStartupHooks are hooks that execute sequentially before any startup hooks.
// These run before the server begins initialization.
// Default: nil
PreStartupHooks []StartupHookConfig
// StartupHooks are hooks that execute sequentially before the server starts
// accepting connections. If any startup hook returns an error, the server
// will not start.
// Default: nil
StartupHooks []StartupHookConfig
// PostStartupHooks are hooks that execute sequentially after the server has
// started accepting connections.
// Default: nil
PostStartupHooks []StartupHookConfig
// PreShutdownHooks are hooks that execute sequentially before server shutdown begins.
// These run before any servers start shutting down.
// Default: nil
PreShutdownHooks []ShutdownHookConfig
// ShutdownHooks are hooks that execute concurrently with server shutdown.
// These run alongside the HTTP/HTTPS/HTTP3 server shutdown.
// Default: nil
ShutdownHooks []ShutdownHookConfig
// PostShutdownHooks are hooks that execute sequentially after all servers are shut down.
// These run after all servers have completed shutdown.
// Default: nil
PostShutdownHooks []ShutdownHookConfig
}
type M ¶
M is a convenience type for map[string]any, useful for quick JSON responses.
return zh.Render.JSON(w, http.StatusOK, zh.M{
"message": "Hello, World!",
"count": 42,
})
type MiddlewareFunc ¶ added in v0.79.0
HandlerFunc is a handler function that returns an error. It implements http.Handler, allowing it to be used anywhere a standard HTTP handler is expected.
Errors are automatically converted to appropriate HTTP responses:
- Validation errors return 422 Unprocessable Entity with field details
- Unknown fields return 422 Unprocessable Entity
- Binding errors return 400 Bad Request
- Request too large returns 413 Payload Too Large
- ProblemDetail errors return their specified status code
- All other errors return 500 Internal Server Error
Example:
app.GET("/users/{id}", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
id := zh.Param(r, "id")
user, err := db.GetUser(id)
if err != nil {
return err // Returns 500
}
if user == nil {
return zh.NewProblemDetail(http.StatusNotFound, "User not found").Render(w)
}
return zh.Render.JSON(w, http.StatusOK, user)
}))
func DefaultMiddlewares ¶ added in v0.58.0
func DefaultMiddlewares(cfg Config, logger log.Logger) []MiddlewareFunc
DefaultMiddlewares returns the default set of middlewares with the provided configuration. The returned middlewares are applied in the following order:
- RequestID: Assigns a unique request ID to each request
- Recover: Recovers from panics and logs errors
- RequestBodySize: Limits the maximum request body size
- SecurityHeaders: Adds security-related HTTP headers
- RequestLogger: Logs HTTP requests and responses
type ParamExtractor ¶ added in v0.10.0
type ParamExtractor interface {
// Param gets a path parameter by name as a string.
// Returns empty string if parameter is not found.
Param(r *http.Request, name string) string
// ParamOrDefault gets a path parameter with a fallback default value.
ParamOrDefault(r *http.Request, name, defaultVal string) string
}
ParamExtractor defines the interface for path parameter extraction
type ParamType ¶ added in v0.10.0
type ParamType interface {
~string | ~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64 |
~bool
}
ParamType is a type constraint for supported path parameter types. Supported types: string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool
type ProblemDetail ¶
ProblemDetail is an alias to problem.Detail. It represents an RFC 9457 Problem Details response, a standardized format for returning error details from HTTP APIs.
Example usage:
return zh.NewProblemDetail(http.StatusNotFound, "User not found").Render(w)
Or return validation errors:
return zh.Validate.Struct(&req) // Returns 422 with field errors
func NewProblemDetail ¶
func NewProblemDetail(statusCode int, detail string) *ProblemDetail
NewProblemDetail creates a new ProblemDetail with the given status code and detail message. This is a convenience wrapper around problem.NewDetail.
func NewValidationProblemDetail ¶
func NewValidationProblemDetail[T any](detail string, errors []T) *ProblemDetail
NewValidationProblemDetail creates a problem detail for validation errors (HTTP 422). This is a convenience wrapper around problem.NewValidationDetail.
type QueryExtractor ¶ added in v0.11.0
type QueryExtractor interface {
// QueryParam gets a query parameter by name as a string.
// Returns empty string if parameter is not found.
QueryParam(r *http.Request, name string) string
// QueryParamOrDefault gets a query parameter with a fallback default value.
QueryParamOrDefault(r *http.Request, name, defaultVal string) string
}
QueryExtractor defines the interface for query parameter extraction
type Renderer ¶
type Renderer interface {
// JSON writes a JSON response with the given status code and data
JSON(w http.ResponseWriter, statusCode int, data any) error
// Text writes a plain text response with the given status code and data
Text(w http.ResponseWriter, statusCode int, data string) error
// HTML writes an HTML response with the given status code and data
HTML(w http.ResponseWriter, statusCode int, data string) error
// Template renders an HTML template with proper Content-Type header
Template(w http.ResponseWriter, code int, tmpl *template.Template, name string, data any) error
// Blob writes a binary response with the given status code, content type, and data
Blob(w http.ResponseWriter, statusCode int, contentType string, data []byte) error
// Stream writes a streaming response with the given status code and content type,
// copying data from the provided reader to the response writer
Stream(w http.ResponseWriter, statusCode int, contentType string, reader io.Reader) error
// File serves a file as the response, automatically setting appropriate headers
File(w http.ResponseWriter, r *http.Request, filename string) error
// NoContent writes a 204 No Content response with no body
NoContent(w http.ResponseWriter) error
// NotModified writes a 304 Not Modified response for conditional requests
NotModified(w http.ResponseWriter) error
// Redirect performs an HTTP redirect with the specified status code and location
Redirect(w http.ResponseWriter, r *http.Request, url string, code int) error
// ProblemDetail writes an RFC 9457 Problem Details response
ProblemDetail(w http.ResponseWriter, problem *ProblemDetail) error
}
Renderer handles response rendering for various content types
var Render Renderer = &defaultRenderer{}
Render is the default Renderer instance used by the package. Use it to write HTTP responses in various formats:
// JSON response zh.Render.JSON(w, http.StatusOK, user) // Plain text zh.Render.Text(w, http.StatusOK, "Hello") // File download zh.Render.File(w, r, "/path/to/document.pdf")
For convenience, use the R alias.
type Router ¶
type Router interface {
// DELETE registers a handler for HTTP DELETE requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
DELETE(path string, h http.Handler, mw ...MiddlewareFunc)
// GET registers a handler for HTTP GET requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
GET(path string, h http.Handler, mw ...MiddlewareFunc)
// HEAD registers a handler for HTTP HEAD requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
HEAD(path string, h http.Handler, mw ...MiddlewareFunc)
// OPTIONS registers a handler for HTTP OPTIONS requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
OPTIONS(path string, h http.Handler, mw ...MiddlewareFunc)
// PATCH registers a handler for HTTP PATCH requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
PATCH(path string, h http.Handler, mw ...MiddlewareFunc)
// POST registers a handler for HTTP POST requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
POST(path string, h http.Handler, mw ...MiddlewareFunc)
// PUT registers a handler for HTTP PUT requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
PUT(path string, h http.Handler, mw ...MiddlewareFunc)
// CONNECT registers a handler for HTTP CONNECT requests to the specified path.
// Additional middleware can be provided that will be applied only to this route.
// CONNECT is typically used for WebSocket and WebTransport upgrades.
CONNECT(path string, h http.Handler, mw ...MiddlewareFunc)
// Use adds middleware to the router's global middleware chain.
// Middleware is applied to all routes registered after this call.
Use(mw ...MiddlewareFunc)
// Group creates a new router scope that inherits the current middleware chain.
// This allows for organizing routes and applying middleware to specific groups.
Group(fn func(Router))
// NotFound sets a custom handler for 404 Not Found responses.
// If not set, a default handler that returns a problem detail response is used.
NotFound(h http.Handler)
// MethodNotAllowed sets a custom handler for 405 Method Not Allowed responses.
// If not set, a default handler that returns a problem detail response is used.
MethodNotAllowed(h http.Handler)
// Files serves static files from embedded FS at the specified prefix.
// The prefix is stripped from URLs before looking up files in the embedFS.
Files(prefix string, embedFS embed.FS, dir string)
// FilesDir serves static files from a directory at the specified prefix.
// The prefix is stripped from URLs before looking up files in the directory.
FilesDir(prefix, dir string)
// Static serves a static web application from embedded FS with configurable fallback behavior.
// If fallback is true, falls back to index.html for non-existent files (SPA behavior).
// If fallback is false, uses the custom NotFound handler for missing files.
// Requests matching apiPrefix patterns return 404 regardless.
Static(embedFS embed.FS, distDir string, fallback bool, apiPrefix ...string)
// StaticDir serves a static web application from a directory with configurable fallback behavior.
// If fallback is true, falls back to index.html for non-existent files (SPA behavior).
// If fallback is false, uses the custom NotFound handler for missing files.
// Requests matching apiPrefix patterns return 404 regardless.
StaticDir(dir string, fallback bool, apiPrefix ...string)
// ServeMux returns the underlying http.ServeMux for advanced usage or integration.
ServeMux() *http.ServeMux
// ServeHTTP implements the http.Handler interface, making the router compatible
// with Go's standard HTTP server and middleware ecosystem.
ServeHTTP(w http.ResponseWriter, req *http.Request)
// Logger returns the logger instance used by the router for logging
// requests, errors, and other router-specific events.
Logger() log.Logger
// SetLogger configures the logger instance that the router should use
// for logging operations. This allows for custom logger configuration.
SetLogger(logger log.Logger)
// Config returns the current configuration used by the router.
// This configuration controls various aspects of router behavior
// including middleware settings and error response handling.
Config() Config
// SetConfig updates the router's configuration. This affects how
// the router handles various behaviors including middleware settings
// and error response processing.
//
// Note: Changing the configuration affects both regular routes
// and 404/405 error responses.
SetConfig(config Config)
}
Router interface defines the contract for HTTP routing operations. It provides methods for registering HTTP handlers for specific HTTP methods, applying middleware, creating route groups, and customizing error handlers.
func NewRouter ¶
func NewRouter(mw ...MiddlewareFunc) Router
NewRouter creates a new router instance with optional global middleware. The middleware provided here will be applied to all routes registered on this router.
Example:
router := NewRouter(loggingMiddleware, authMiddleware)
type Server ¶
type Server struct {
// Router provides HTTP routing functionality including method-specific
// route registration, middleware support, and request handling.
Router
// contains filtered or unexported fields
}
Server represents a zerohttp server instance that wraps Go's standard HTTP server with additional functionality including middleware support, TLS configuration, automatic certificate management, and structured logging.
The Server embeds a Router interface, providing direct access to HTTP routing methods (GET, POST, PUT, DELETE, etc.) and middleware management.
func New ¶
New creates and configures a new Server instance with the provided It initializes the server with sensible defaults that can be overridden using the provided
The server includes:
- HTTP and HTTPS support
- Middleware integration
- Structured logging
- Automatic metrics collection (enabled by default)
- Request binding and validation
Example - Basic usage with defaults:
app := zh.New()
app.GET("/", handler)
log.Fatal(app.Start())
Example - With custom configuration:
app := zh.New(Config{
Addr: ":8080",
Server: &http.Server{
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
},
Logger: myLogger,
Metrics: metrics.Config{
Enabled: config.Bool(false), // Disable metrics
},
})
Example - Customizing only specific server fields (keeps other defaults):
srv := zh.DefaultHTTPServer()
srv.ReadTimeout = 30 * time.Second
app := zh.New(Config{
Addr: ":8080",
Server: srv,
})
Example - With pluggable validator:
app := zh.New(Config{
Validator: myCustomValidator,
})
func (*Server) Close ¶
Close immediately closes all server listeners, terminating any active connections. Unlike Shutdown, this method does not wait for connections to finish gracefully. It closes both HTTP and HTTPS listeners concurrently.
This method is thread-safe and can be called multiple times safely. Returns the last error encountered while closing listeners, or nil if successful.
func (*Server) ListenAndServe ¶
ListenAndServe starts the HTTP server and begins accepting connections. It creates a listener if one is not already configured and serves HTTP traffic on the configured address. If the server is not configured, this method logs a debug message and returns nil without error.
This method blocks until the server encounters an error or is shut down. Returns any error encountered while starting or running the server.
func (*Server) ListenAndServeHTTP3 ¶ added in v0.6.0
ListenAndServeHTTP3 starts the HTTP/3 server with the specified certificate files. HTTP/3 requires TLS and uses the provided certificate and key files for encryption. If the HTTP/3 server is not configured, this method logs a debug message and returns nil without error.
Parameters:
- certFile: Path to the TLS certificate file in PEM format
- keyFile: Path to the TLS private key file in PEM format
This method blocks until the server encounters an error or is shut down. Returns any error encountered while starting or running the HTTP/3 server.
func (*Server) ListenAndServeTLS ¶
ListenAndServeTLS starts the HTTPS server with the specified certificate files. It creates a TLS listener if one is not already configured and serves HTTPS traffic using the provided certificate and key files. If the TLS server is not configured, this method logs a debug message and returns nil without error.
Parameters:
- certFile: Path to the TLS certificate file in PEM format
- keyFile: Path to the TLS private key file in PEM format
This method blocks until the server encounters an error or is shut down. Returns any error encountered while starting or running the TLS server.
func (*Server) ListenerAddr ¶
ListenerAddr returns the network address that the HTTP server is listening on. If a listener is configured, it returns the listener's actual address. If no listener is configured but a server is configured, it returns the server's configured address. If neither is configured, it returns an empty string.
This method is thread-safe and can be called concurrently. The returned address includes both host and port (e.g., "127.0.0.1:8080").
func (*Server) ListenerTLSAddr ¶
ListenerTLSAddr returns the network address that the HTTPS server is listening on. If a TLS listener is configured, it returns the listener's actual address. If no TLS listener is configured but a TLS server is configured, it returns the server's configured address. If neither is configured, it returns an empty string.
This method is thread-safe and can be called concurrently. The returned address includes both host and port (e.g., "127.0.0.1:8443").
func (*Server) Logger ¶
Logger returns the structured logger instance used by the server. This logger is used for recording HTTP requests, errors, server lifecycle events, and can be used by application code for consistent logging.
The returned logger implements the log.Logger interface and provides structured logging capabilities with fields and different log levels.
func (*Server) Metrics ¶ added in v0.23.0
Metrics returns the metrics registry for collecting custom metrics. Returns nil if metrics are not enabled.
Use this to create custom metrics in your handlers or middleware:
requests := app.Metrics().Counter("my_requests_total", "status")
requests.WithLabelValues("200").Inc()
func (*Server) MetricsAddr ¶ added in v0.24.0
MetricsAddr returns the network address that the metrics server is listening on. If a listener is configured, it returns the listener's actual address. If no listener is configured but a metrics server is configured, it returns the server's configured address. If no metrics server is configured, it returns an empty string.
This method is thread-safe and can be called concurrently.
func (*Server) RegisterPostShutdownHook ¶ added in v0.14.0
func (s *Server) RegisterPostShutdownHook(name string, hook ShutdownHook)
RegisterPostShutdownHook registers a hook to run after servers have shut down. Post-shutdown hooks execute sequentially in registration order. Errors from post-shutdown hooks are logged but do not affect shutdown.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, shutdown will hang.
Example:
app.RegisterPostShutdownHook("cleanup", func(ctx context.Context) error {
return os.RemoveAll("/tmp/app-*")
})
func (*Server) RegisterPostStartupHook ¶ added in v0.36.0
func (s *Server) RegisterPostStartupHook(name string, hook StartupHook)
RegisterPostStartupHook registers a hook to run after servers have started accepting connections. Post-startup hooks execute sequentially in registration order. Errors from post-startup hooks are logged but do not stop the server.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, startup will hang.
Example:
app.RegisterPostStartupHook("announce-ready", func(ctx context.Context) error {
return notifyServiceDiscovery()
})
func (*Server) RegisterPreShutdownHook ¶ added in v0.14.0
func (s *Server) RegisterPreShutdownHook(name string, hook ShutdownHook)
RegisterPreShutdownHook registers a hook to run before server shutdown begins. Pre-shutdown hooks execute sequentially in registration order, before servers stop. Errors from pre-shutdown hooks are logged but do not stop shutdown.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, shutdown will hang.
Example:
app.RegisterPreShutdownHook("health", func(ctx context.Context) error {
health.SetUnhealthy()
return nil
})
func (*Server) RegisterPreStartupHook ¶ added in v0.36.0
func (s *Server) RegisterPreStartupHook(name string, hook StartupHook)
RegisterPreStartupHook registers a hook to run before servers start and before startup hooks. Pre-startup hooks execute sequentially in registration order. If any pre-startup hook returns an error, the server will not start.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, startup will hang.
Example:
app.RegisterPreStartupHook("validate-config", func(ctx context.Context) error {
return validateConfig()
})
func (*Server) RegisterShutdownHook ¶ added in v0.14.0
func (s *Server) RegisterShutdownHook(name string, hook ShutdownHook)
RegisterShutdownHook registers a hook to run concurrently with server shutdown. Shutdown hooks execute concurrently alongside server shutdown. Errors from shutdown hooks are logged but do not stop shutdown.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, shutdown will hang.
Example:
app.RegisterShutdownHook("close-db", func(ctx context.Context) error {
return db.Close()
})
func (*Server) RegisterStartupHook ¶ added in v0.35.0
func (s *Server) RegisterStartupHook(name string, hook StartupHook)
RegisterStartupHook registers a hook to run concurrently with servers starting up. Startup hooks execute sequentially in registration order, after PreStartupHooks. If any startup hook returns an error, the server will not start.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, startup will hang.
Example:
app.RegisterStartupHook("migrations", func(ctx context.Context) error {
return goose.Up(db.DB, "migrations")
})
func (*Server) SSEProvider ¶ added in v0.16.0
SSEProvider returns the configured SSE provider (if any). Returns nil if no SSE provider has been configured.
func (*Server) SetHTTP3Server ¶ added in v0.6.0
SetHTTP3Server sets the HTTP/3 server instance. This can be used to inject an HTTP/3 implementation (e.g., quic-go/http3) after creating the server.
The HTTP/3 server will be started automatically when ListenAndServeTLS or StartTLS is called. You don't need to call ListenAndServeTLS on the HTTP/3 server yourself.
Parameters:
- server: An HTTP/3 server instance implementing the HTTP3Server interface
func (*Server) SetSSEProvider ¶ added in v0.16.0
SetSSEProvider sets the SSE provider instance. This can be used to inject an SSE implementation after creating the server.
Users can implement their own SSE provider or use the built-in stdlib provider:
app := zerohttp.New()
app.SetSSEProvider(zh.NewDefaultProvider())
app.GET("/events", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
provider := app.SSEProvider()
sse, err := provider.New(w, r)
if err != nil {
return err
}
defer sse.Close()
// ... stream events ...
}))
Parameters:
- provider: An SSE provider instance implementing the SSEProvider interface
func (*Server) SetValidator ¶ added in v0.18.0
SetValidator sets the struct validator instance. This can be used to inject a custom validation implementation (e.g., go-playground/validator/v10) after creating the server. If nil, the default built-in validator will be used.
Example:
import "github.com/go-playground/validator/v10"
app := zerohttp.New()
app.SetValidator(&myValidator{v: validator.New()})
Parameters:
- validator: A validator instance implementing the Validator interface
func (*Server) SetWebSocketUpgrader ¶ added in v0.15.0
SetWebSocketUpgrader sets the WebSocket upgrader instance. This can be used to inject a WebSocket implementation (e.g., gorilla/websocket, nhooyr/websocket) after creating the server.
The WebSocket upgrader provides the Upgrade method for handling WebSocket connections. Users bring their own WebSocket library and implement the WebSocketUpgrader interface, or use a thin wrapper around their preferred library.
Example with gorilla/websocket:
import "github.com/gorilla/websocket"
upgrader := &websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
app := zerohttp.New()
app.SetWebSocketUpgrader(&myUpgrader{upgrader})
app.GET("/ws", zh.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
ws, err := app.WebSocketUpgrader().Upgrade(w, r)
if err != nil {
return err
}
defer ws.Close()
// ... handle connection ...
}))
Parameters:
- upgrader: A WebSocket upgrader instance implementing the config.WebSocketUpgrader interface
func (*Server) SetWebTransportServer ¶ added in v0.7.0
func (s *Server) SetWebTransportServer(server webtransport.Server)
SetWebTransportServer sets the WebTransport server instance. This can be used to inject a WebTransport implementation (e.g., quic-go/webtransport-go) after creating the server.
The WebTransport server will be started automatically when ListenAndServeTLS or Start is called. You don't need to call ListenAndServeTLS on the WebTransport server yourself.
Parameters:
- server: A WebTransport server instance implementing the config.WebTransportServer interface
func (*Server) Shutdown ¶
Shutdown gracefully shuts down both HTTP and HTTPS servers without interrupting any active connections. It waits for active connections to finish or for the provided context to be cancelled.
Parameters:
- ctx: Context that controls the shutdown timeout. If the context is cancelled before shutdown completes, the servers will be forcefully closed.
The shutdown process runs concurrently for both servers. If any server encounters an error during shutdown, that error is returned. Shutdown hooks are executed during the shutdown process:
- Pre-shutdown hooks run sequentially before server shutdown begins
- Shutdown hooks run concurrently with server shutdown
- Post-shutdown hooks run sequentially after all servers are shut down
Returns the first error encountered during shutdown, or nil if successful.
func (*Server) Start ¶
Start begins serving HTTP, HTTPS, and metrics traffic concurrently. It starts all configured servers (HTTP, HTTPS, metrics, HTTP/3, WebTransport) in separate goroutines and blocks until all servers exit.
For HTTPS, the server will start if:
- TLS server is configured AND
- Either certificates are loaded in TLS config OR certificate files are specified
Start blocks until all servers exit. If any server encounters an unexpected error (i.e. not ErrServerClosed), that error is returned immediately. Returns nil when all servers shut down cleanly (e.g. via Shutdown()).
func (*Server) StartAutoTLS ¶
StartAutoTLS starts the server with automatic TLS certificate management using Let's Encrypt. It starts both HTTP (for ACME challenges) and HTTPS servers. The HTTP server redirects to HTTPS and handles ACME challenges.
Users must configure the AutocertManager with their desired host policy before calling this method. For example, using golang.org/x/crypto/acme/autocert:
mgr := &autocert.Manager{
Cache: autocert.DirCache("/var/cache/certs"),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.com"),
}
srv := zerohttp.New(WithAutocertManager(mgr))
srv.StartAutoTLS()
The HTTP server handles:
- ACME challenge requests from Let's Encrypt
- Redirects all other HTTP traffic to HTTPS
Returns an error if the autocert manager is not configured or if any server fails to start.
func (*Server) StartHTTP3 ¶ added in v0.6.0
StartHTTP3 starts only the HTTP/3 server with the specified certificate files. This is a convenience method for starting just HTTP/3 without HTTP or HTTPS. If the HTTP/3 server is not configured, this method returns nil without error.
Parameters:
- certFile: Path to the TLS certificate file in PEM format
- keyFile: Path to the TLS private key file in PEM format
This is equivalent to calling ListenAndServeHTTP3 directly. Returns any error encountered while starting or running the HTTP/3 server.
func (*Server) StartTLS ¶
StartTLS is a convenience method that starts only the HTTPS server with the specified certificate files. If the TLS server is not configured, this method returns nil without error.
Parameters:
- certFile: Path to the TLS certificate file in PEM format
- keyFile: Path to the TLS private key file in PEM format
This is equivalent to calling ListenAndServeTLS directly. Returns any error encountered while starting or running the TLS server.
func (*Server) Validator ¶ added in v0.18.0
Validator returns the configured struct validator (if any). Returns nil if no custom validator has been configured - in this case, the default built-in validator (zh.V) should be used.
func (*Server) WebSocketUpgrader ¶ added in v0.15.0
WebSocketUpgrader returns the configured WebSocket upgrader (if any). Returns nil if no WebSocket upgrader has been configured.
type ShutdownHook ¶ added in v0.58.0
ShutdownHook is a function called during server shutdown. The context passed to the hook will be cancelled when the shutdown timeout is reached or if the parent context is cancelled.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, shutdown will hang.
type ShutdownHookConfig ¶ added in v0.58.0
type ShutdownHookConfig struct {
Name string
Hook ShutdownHook
}
ShutdownHookConfig configures a shutdown hook.
type StartupHook ¶ added in v0.58.0
StartupHook is a function called before the server starts accepting connections. The context passed to the hook has a deadline based on any configured timeout.
Startup hooks execute sequentially in registration order. If any startup hook returns an error, the server will not start.
Hooks must respect context cancellation by checking ctx.Done(). If a hook blocks without respecting the context, startup will hang.
Example:
app.RegisterStartupHook("migrations", func(ctx context.Context) error {
return goose.Up(db.DB, "migrations")
})
type StartupHookConfig ¶ added in v0.58.0
type StartupHookConfig struct {
Name string
Hook StartupHook
}
StartupHookConfig configures a startup hook.
type TLSConfig ¶ added in v0.58.0
type TLSConfig struct {
// Addr is the address for the HTTPS server to listen on.
// Default: "localhost:8443"
Addr string
// Server is the HTTPS server instance for encrypted traffic.
// Default: preconfigured server listening on "localhost:8443"
Server *http.Server
// Listener allows specifying a custom net.Listener for HTTPS traffic (optional).
// Default: nil (system default listener will be created)
Listener net.Listener
// CertFile is the file path to the TLS certificate (PEM) when serving HTTPS.
// Default: "" (no certificate loaded unless specified)
CertFile string
// KeyFile is the file path to the TLS private key (PEM) when serving HTTPS.
// Default: "" (no key loaded unless specified)
KeyFile string
// RedirectHTTP enables automatic HTTP to HTTPS redirects when both HTTP and
// HTTPS servers are running. When enabled, all HTTP traffic is redirected
// to HTTPS with a 301 Moved Permanently status.
// Default: true (for security, redirects to HTTPS by default)
RedirectHTTP bool
}
type TemplateManager ¶ added in v0.3.0
type TemplateManager struct {
// contains filtered or unexported fields
}
TemplateManager implements TemplateRenderer using html/template
func (*TemplateManager) Render ¶ added in v0.3.0
func (tm *TemplateManager) Render(w http.ResponseWriter, code int, name string, data any) error
Render renders the specified template with the given data and status code
type TemplateRenderer ¶ added in v0.3.0
type TemplateRenderer interface {
Render(w http.ResponseWriter, code int, name string, data any) error
}
TemplateRenderer defines the interface for rendering HTML templates
func NewTemplateManager ¶ added in v0.3.0
func NewTemplateManager(templatesFS embed.FS, pattern string) TemplateRenderer
NewTemplateManager creates a new TemplateManager with parsed templates from the embedded filesystem
type ValidationError ¶
type ValidationError = problem.ValidationError
ValidationError is an alias to problem.ValidationError. It represents a single validation error with optional field location information.
type Validator ¶ added in v0.18.0
type Validator interface {
// Struct validates a struct using `validate` struct tags.
// It returns an error containing all validation failures, or nil if valid.
Struct(dst any) error
// Register adds a custom validation function with the given name.
// The name can be used in struct tags like `validate:"customName"`.
Register(name string, fn func(reflect.Value, string) error)
}
Validator is the interface for struct validation. Users can implement this interface to provide their own validation logic (e.g., wrapping github.com/go-playground/validator/v10).
Example with go-playground/validator:
import "github.com/go-playground/validator/v10"
type myValidator struct {
v *validator.Validate
}
func (m *myValidator) Struct(dst any) error {
return m.v.Struct(dst)
}
func (m *myValidator) Register(name string, fn func(reflect.Value, string) error) {
// Custom registration or no-op
}
app := zerohttp.New(zh.ConfigValidator: &myValidator{v: validator.New()}})
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
core/binding_form
command
|
|
|
core/binding_param
command
|
|
|
core/binding_query
command
|
|
|
core/crud
command
|
|
|
core/custom_error_handlers
command
|
|
|
core/file_server
command
|
|
|
core/file_upload
command
|
|
|
core/graceful
command
|
|
|
core/hello_world
command
|
|
|
core/hsts
command
|
|
|
core/lifecycle
command
|
|
|
core/logger
command
|
|
|
core/problem_detail
command
|
|
|
core/rendering
command
|
|
|
core/request_tracing
command
|
|
|
core/route_groups
command
|
|
|
core/static_spa
command
|
|
|
core/static_website
command
|
|
|
core/template
command
|
|
|
core/template_renderer
command
|
|
|
core/testing
command
|
|
|
core/tls
command
|
|
|
core/validation_basic
command
|
|
|
core/validation_custom
command
|
|
|
core/validation_nested
command
|
|
|
healthcheck
command
|
|
|
metrics
command
|
|
|
middleware/basic_auth
command
|
|
|
middleware/cache
command
|
|
|
middleware/circuitbreaker
command
|
|
|
middleware/compress
command
|
|
|
middleware/contentcharset
command
|
|
|
middleware/contentencoding
command
|
|
|
middleware/contenttype
command
|
|
|
middleware/cors
command
|
|
|
middleware/csrf
command
|
|
|
middleware/custom
command
|
|
|
middleware/etag
command
|
|
|
middleware/hmacauth
command
|
|
|
middleware/hmacauth/client
command
|
|
|
middleware/host
command
|
|
|
middleware/idempotency
command
|
|
|
middleware/jwtauth
command
|
|
|
middleware/jwtauth_cookie
command
|
|
|
middleware/jwtauth_refresh
command
|
|
|
middleware/mediatype
command
|
|
|
middleware/nocache
command
|
|
|
middleware/ratelimit
command
|
|
|
middleware/realip
command
|
|
|
middleware/recover
command
|
|
|
middleware/requestbodysize
command
|
|
|
middleware/requestid
command
|
|
|
middleware/requestlogger
command
|
|
|
middleware/reverseproxy
command
|
|
|
middleware/securityheaders
command
|
|
|
middleware/securityheaders_nonce
command
|
|
|
middleware/setheader
command
|
|
|
middleware/timeout
command
|
|
|
middleware/tracer
command
|
|
|
middleware/trailingslash
command
|
|
|
middleware/value
command
|
|
|
pagination
command
|
|
|
pprof
command
|
|
|
sse
command
|
|
|
Package extensions provides optional interfaces for extending zerohttp functionality.
|
Package extensions provides optional interfaces for extending zerohttp functionality. |
|
autocert
Package autocert provides automatic TLS certificate management via Let's Encrypt.
|
Package autocert provides automatic TLS certificate management via Let's Encrypt. |
|
http3
Package http3 provides HTTP/3 support for zerohttp.
|
Package http3 provides HTTP/3 support for zerohttp. |
|
websocket
Package websocket provides WebSocket support for zerohttp.
|
Package websocket provides WebSocket support for zerohttp. |
|
webtransport
Package webtransport provides WebTransport support for zerohttp.
|
Package webtransport provides WebTransport support for zerohttp. |
|
Package healthcheck provides [Kubernetes]-style health probe endpoints.
|
Package healthcheck provides [Kubernetes]-style health probe endpoints. |
|
Package httpx provides HTTP header names, content types, and other constants for use throughout the framework.
|
Package httpx provides HTTP header names, content types, and other constants for use throughout the framework. |
|
internal
|
|
|
mwutil
Package mwutil provides shared utilities for middleware implementations.
|
Package mwutil provides shared utilities for middleware implementations. |
|
Package log provides structured logging interfaces for zerohttp.
|
Package log provides structured logging interfaces for zerohttp. |
|
Package metrics provides [Prometheus]-compatible metrics collection with zero external dependencies.
|
Package metrics provides [Prometheus]-compatible metrics collection with zero external dependencies. |
|
Package middleware provides HTTP middleware for zerohttp.
|
Package middleware provides HTTP middleware for zerohttp. |
|
basicauth
Package basicauth provides HTTP Basic Authentication middleware.
|
Package basicauth provides HTTP Basic Authentication middleware. |
|
cache
Package cache provides HTTP caching middleware with ETag and conditional request support.
|
Package cache provides HTTP caching middleware with ETag and conditional request support. |
|
circuitbreaker
Package circuitbreaker provides circuit breaker middleware for fault tolerance.
|
Package circuitbreaker provides circuit breaker middleware for fault tolerance. |
|
compress
Package compress provides response compression middleware.
|
Package compress provides response compression middleware. |
|
contentcharset
Package contentcharset provides Content-Type charset validation middleware.
|
Package contentcharset provides Content-Type charset validation middleware. |
|
contentencoding
Package contentencoding provides Content-Encoding validation middleware.
|
Package contentencoding provides Content-Encoding validation middleware. |
|
contenttype
Package contenttype provides Content-Type validation middleware.
|
Package contenttype provides Content-Type validation middleware. |
|
cors
Package cors provides Cross-Origin Resource Sharing middleware.
|
Package cors provides Cross-Origin Resource Sharing middleware. |
|
csrf
Package csrf provides Cross-Site Request Forgery protection middleware.
|
Package csrf provides Cross-Site Request Forgery protection middleware. |
|
etag
Package etag provides ETag generation and validation middleware.
|
Package etag provides ETag generation and validation middleware. |
|
hmacauth
Package hmacauth provides HMAC request signing authentication.
|
Package hmacauth provides HMAC request signing authentication. |
|
host
Package host provides host header validation middleware.
|
Package host provides host header validation middleware. |
|
idempotency
Package idempotency provides idempotent request handling middleware.
|
Package idempotency provides idempotent request handling middleware. |
|
jwtauth
Package jwtauth provides JWT authentication middleware.
|
Package jwtauth provides JWT authentication middleware. |
|
mediatype
Package mediatype provides media type negotiation and validation middleware.
|
Package mediatype provides media type negotiation and validation middleware. |
|
nocache
Package nocache provides cache-busting middleware.
|
Package nocache provides cache-busting middleware. |
|
ratelimit
Package ratelimit provides rate limiting middleware.
|
Package ratelimit provides rate limiting middleware. |
|
realip
Package realip provides client IP extraction middleware.
|
Package realip provides client IP extraction middleware. |
|
recover
Package recover provides panic recovery middleware.
|
Package recover provides panic recovery middleware. |
|
requestbodysize
Package requestbodysize provides request body size limiting middleware.
|
Package requestbodysize provides request body size limiting middleware. |
|
requestid
Package requestid provides request ID generation middleware.
|
Package requestid provides request ID generation middleware. |
|
requestlogger
Package requestlogger provides HTTP request/response logging middleware.
|
Package requestlogger provides HTTP request/response logging middleware. |
|
reverseproxy
Package reverseproxy provides reverse proxy middleware.
|
Package reverseproxy provides reverse proxy middleware. |
|
securityheaders
Package securityheaders provides security header middleware.
|
Package securityheaders provides security header middleware. |
|
setheader
Package setheader provides custom response header middleware.
|
Package setheader provides custom response header middleware. |
|
timeout
Package timeout provides request timeout middleware.
|
Package timeout provides request timeout middleware. |
|
tracer
Package tracer provides distributed tracing middleware.
|
Package tracer provides distributed tracing middleware. |
|
trailingslash
Package trailingslash provides trailing slash normalization middleware.
|
Package trailingslash provides trailing slash normalization middleware. |
|
value
Package value provides context value injection middleware.
|
Package value provides context value injection middleware. |
|
Package pagination provides utilities for handling pagination in HTTP APIs.
|
Package pagination provides utilities for handling pagination in HTTP APIs. |
|
Package pprof provides Go runtime profiling endpoints.
|
Package pprof provides Go runtime profiling endpoints. |
|
Package sse provides Server-Sent Events (SSE) support for real-time server-to-client streaming using Go's standard library.
|
Package sse provides Server-Sent Events (SSE) support for real-time server-to-client streaming using Go's standard library. |
|
Package storage provides a shared storage interface for middleware backends.
|
Package storage provides a shared storage interface for middleware backends. |
|
Package trace provides interfaces for distributed tracing.
|
Package trace provides interfaces for distributed tracing. |
|
Package validator provides struct tag-based validation with no external dependencies.
|
Package validator provides struct tag-based validation with no external dependencies. |
|
Package zhtest provides testing utilities for zerohttp applications.
|
Package zhtest provides testing utilities for zerohttp applications. |