[enter]prize
prize is a Go package that provides a type-safe, generic HTTP handler with built-in middleware support. Built on top of github.com/4thPlanet/dispatch, it wires together session management, request logging, error handling, and content encoding into a single composable handler — so you can focus on your application logic rather than plumbing.
Features
- Generic, type-safe request data — bind strongly-typed request context (
T) to each incoming request via a user-supplied factory function
- Typed Handlers — Generic
TypedHandler[S, T] for type-safe request handling with session and custom data support
- Session Management — pluggable
SessionStore; defaults to an in-memory session store
- Request Logging — Apache-style access logging with configurable format directives
- Error Handling — centralized, swappable error handler with panic recovery and stack trace logging
- Content Encoding — support for gzip, deflate, and custom encoders with Content-Type negotiation
- Middleware chaining — attach custom middleware that runs after the built-in layers
- WebSocket support — indirect, via the
gobwas/ws dependency pulled in through dispatch
Requirements
Go 1.26.1 or later
Installation
go get github.com/4thPlanet/prize
Quick Start
package main
import (
"fmt"
"net/http"
"github.com/4thPlanet/prize"
"github.com/4thPlanet/prize/middleware"
)
// Define your session type. Must implement middleware.Session interface (Id() string)
type MySession struct {
UserID string
}
func (s MySession) Id() string { return s.UserID }
// Define your per-request data type.
type RequestData struct {
Name string
}
func main() {
// Create a typed handler.
// The argument extracts typed data from the request.
handler := prize.NewTypedHandler[MySession](
func(r *http.Request) RequestData {
return RequestData{Name: r.URL.Query().Get("name")}
},
)
// Register routes - HandlerData gives access to Session and RequestData
handler.HandleFunc("GET /hello", func(w http.ResponseWriter, hd *prize.HandlerData[MySession, RequestData]) {
fmt.Fprintf(w, "Hello, %s!", hd.Data.Name)
})
// Register custom middleware (logging, error handling, sessions, and content encoding
// are automatically prepended).
handler.UseMiddleware(/* your custom middleware here */)
http.ListenAndServe(":8080", handler)
}
A more detailed example — including session usage, content negotiation, and authentication — is available in examples/basic.
API Reference
TypedHandler[S, T]
The central type. S must satisfy middleware.Session; T is your arbitrary per-request data struct.
type TypedHandler[S middleware.Session, T any] struct { ... }
NewTypedHandler
func NewTypedHandler[S middleware.Session, T any](
fn func(*http.Request) T,
) *TypedHandler[S, T]
Creates a new handler. fn builds the typed request data from the incoming *http.Request.
UseLog
func (mux *TypedHandler[S, T]) UseLog(format string, l io.Writer)
Override the log format string and output destination. The default format is Apache Combined Log Format (%h %l %u %t "%r" %s %b\n); the default writer is log.Default().Writer().
UseErrorHandler
func (mux *TypedHandler[S, T]) UseErrorHandler(
handler middleware.ErrorHandler[*HandlerData[S, T]],
ctn *dispatch.ContentTypeNegotiator,
)
Swap in a custom error handler and content-type negotiator.
UseContentEncoders
func (mux *TypedHandler[S, T]) UseContentEncoders(encs ...middleware.ContentEncoder)
Register one or more response content encoders (e.g. gzip).
UseSessionStore
func (mux *TypedHandler[S, T]) UseSessionStore(store middleware.SessionStore[S])
Replace the default in-memory session store.
UseMiddleware
func (mux *TypedHandler[S, T]) UseMiddleware(mws ...dispatch.Middleware[*HandlerData[S, T]])
Attach custom middleware. The following built-in middleware layers are automatically prepended in order:
- Logger — logs each request
- Error handler — catches and formats errors
- Session — loads/saves the session for each request
- Content encoding — applies response encoders
HandlerData[S, T]
The context object passed to every route handler. Provides access to the raw request, the typed data, and the loaded session.
type HandlerData[S middleware.Session, T any] struct {
Data T
// contains unexported fields
}
// HandlerData[S, T] implements dispatch.RequestAdapter
func (d *HandlerData[S, T]) Request() *http.Request
// HandlerData[S, T] implements middleware.SessionAdapter
func (d *HandlerData[S, T]) GetSession() S
func (d *HandlerData[S, T]) SetSession(session S)
// HandlerData[S, T] implements middleware.DispatchEncoder
func (d *HandlerData[S, T]) Encoder() *middleware.EncodingData
// HandlerData[S, T] implements middleware.DispatchLogger
func (d *HandlerData[S, T]) Log() *middleware.LoggerData
Middleware
Logger
Apache-style access logging with support for standard directives:
%h - Remote host
%l - Remote logname
%u - Remote user
%t - Time
%r - Request line
%s - Status code
%b - Response size
%D - Request duration (microseconds)
%T - Request duration (seconds)
%{format}t - Custom time format
%{Header}i / %{Header}o - Request/response headers
%m - Request method
%U - Request URL path
%q - Query string
%p - Local port
%H - Request protocol
- And more...
Error Handling
Catches panics and returns configurable error responses with stack trace logging. Supports content type negotiation for error responses.
Session
Generic session management with:
Session interface for custom session types (requires Id() string)
DefaultSessionStore for in-memory session storage
- Cookie-based session tracking
- Configurable session lifecycle
Content Encoding
Content encoding support:
gzip and deflate compression
- Custom encoder support via
ContentEncoder interface
- Automatic
Accept-Encoding negotiation
Running the Example
go run examples/basic/main.go
The example server starts on localhost:8080 with:
GET / - List users (supports HTML, JSON, CSV content negotiation)
POST / - Add a new user (requires Basic Authentication)
GET /panic - Test panic recovery middleware
Building & Testing
# Build
go build ./...
# Run tests
go test ./...
# Run tests with verbose output
go test -v ./...
Dependencies
| Module |
Purpose |
github.com/4thPlanet/dispatch |
Typed HTTP routing and middleware chaining |
github.com/gobwas/ws |
WebSocket support (indirect) |
golang.org/x/sys |
System-level support (indirect) |
License
BSD 3-Clause License. See LICENSE for details.