Claude Code 5ab0120597 fix(httpserver): bind port synchronously in OnStart so bind errors propagate
Previously ListenAndServe ran entirely in a goroutine, so a port-in-use
error was only logged and the launcher received nil from OnStart — leaving
the application running without an HTTP server.

Replace with net.Listen (synchronous) + srv.Serve(ln) (goroutine). A bind
failure now returns an error from OnStart, which the launcher treats as
fatal and triggers a clean shutdown immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 00:26:15 +00:00

httpserver

Lifecycle-managed HTTP server built on chi that integrates with the launcher component model.

Features

  • Implements launcher.Component (OnInit / OnStart / OnStop)
  • Embeds chi.Router — full routing API exposed directly on the component
  • Graceful shutdown with configurable timeouts
  • No middleware installed by default — compose your stack with WithMiddleware

Installation

require code.nochebuena.dev/go/httpserver v0.1.0

Usage

srv := httpserver.New(logger, cfg,
    httpserver.WithMiddleware(
        httpmw.Recover(),
        httpmw.CORS([]string{"*"}),
        httpmw.RequestID(uuid.NewString),
        httpmw.RequestLogger(logger),
    ),
)

// Register routes directly on srv — it is a chi.Router.
srv.Get("/health", health.NewHandler(logger, db, cache))

srv.Route("/api/v1", func(r chi.Router) {
    r.Use(httpauth.AuthMiddleware(firebaseClient, nil))
    r.Get("/orders/{id}", httputil.Handle(validator, svc.GetOrder))
})

lc := launcher.New(logger)
lc.Append(db, cache, srv)
if err := lc.Run(); err != nil {
    log.Fatal(err)
}

Config

Field Env var Default Description
Host SERVER_HOST 0.0.0.0 Bind address
Port SERVER_PORT 8080 Listen port
ReadTimeout SERVER_READ_TIMEOUT 5s Max time to read request
WriteTimeout SERVER_WRITE_TIMEOUT 10s Max time to write response
IdleTimeout SERVER_IDLE_TIMEOUT 120s Keep-alive idle timeout

Options

Option Description
WithMiddleware(mw ...func(http.Handler) http.Handler) Applies middleware to the root router during OnInit

Lifecycle

Phase Action
OnInit Applies registered middleware to the router
OnStart Starts net/http.Server in a background goroutine
OnStop Graceful shutdown — waits up to 10s for in-flight requests
Description
Chi-based HTTP server wired into launcher lifecycle.
Readme MIT 55 KiB
2026-03-24 18:53:56 -06:00
Languages
Go 100%