WebServer is the production-oriented HTTP server wrapper exposed by Mux. It wraps http.Server with sensible defaults, graceful shutdown, and TLS helpers.
- Production defaults out of the box: 10 second read timeout, 10 second write timeout, 120 second idle timeout
- Graceful shutdown when the provided context is canceled
- Built-in TLS helpers for explicit cert paths or discovery-based lookup
- A simple blocking
Listenpath and a backgroundStartpath
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/fgrzl/mux"
)
func main() {
router := mux.NewRouter()
if err := router.Configure(func(router *mux.Router) {
router.GET("/", func(c mux.RouteContext) {
c.OK("Hello, World!")
})
}); err != nil {
panic(err)
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
server := mux.NewServer(":8080", router)
if err := server.Listen(ctx); err != nil {
panic(err)
}
}Listen blocks until the server exits or the context is canceled. On cancellation, WebServer performs a graceful shutdown using a 10 second shutdown timeout.
server := mux.NewServer(":8080", router)Constructs a WebServer with production defaults and optional configuration.
- Binds the listener
- Starts serving immediately
- Blocks until shutdown or an unexpected server error
- Gracefully shuts down when
ctxis canceled
Use Listen for your main application server.
Starts serving in the background and returns immediately.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
server := mux.NewServer(":8080", router)
if err := server.Start(ctx); err != nil {
panic(err)
}
// Do other work here.Use Start when your process needs to keep doing work after the HTTP server begins accepting traffic.
Triggers graceful shutdown explicitly.
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Stop(shutdownCtx); err != nil {
panic(err)
}mux.WithReadTimeout(d time.Duration)mux.WithWriteTimeout(d time.Duration)mux.WithIdleTimeout(d time.Duration)
Example:
server := mux.NewServer(":8080", router,
mux.WithReadTimeout(30*time.Second),
mux.WithWriteTimeout(30*time.Second),
mux.WithIdleTimeout(2*time.Minute),
)mux.WithTLS(certFile, keyFile)mux.WithTLSDiscovery(certsDir, certFile, keyFile)
Use explicit TLS paths when you know where the certs live:
server := mux.NewServer(":8443", router,
mux.WithTLS("certs/server.crt", "certs/server.key"),
)Use discovery when the executable may start from different working directories:
server := mux.NewServer(":8443", router,
mux.WithTLSDiscovery("certs", "server.crt", "server.key"),
)WithTLSDiscovery searches upward for a certs directory, up to 10 parent directories.
WebServer pairs naturally with the router's built-in health probe helpers:
router := mux.NewRouter()
if err := router.Configure(func(router *mux.Router) {
router.Healthz()
router.Livez()
router.Readyz()
}); err != nil {
panic(err)
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
server := mux.NewServer(":8080", router)
if err := server.Listen(ctx); err != nil {
panic(err)
}For a full walkthrough, see health-probes.md.
Use WebServer by default. Drop down to raw http.Server only when you need server features that Mux does not surface directly, such as advanced HTTP/2 or transport-level customization beyond the provided timeout and TLS helpers.
Even in that case, the router still implements http.Handler, so it can be used directly:
srv := &http.Server{
Addr: ":8080",
Handler: router,
}The common production pattern in this repository is:
- Create the router with
mux.NewRouter(...) - Register routes inside
router.Configure(...) - Add middleware during startup
- Run the service with
mux.NewServer(...).Listen(ctx)
That keeps route validation explicit and server lifecycle management predictable.