Mini HTTP Server is a small Go playground for building an HTTP service with net/http. It keeps the code compact enough to read locally, but still includes the pieces a real service needs: routing, path parameters, JSON responses, request IDs, request logs, panic recovery, server timeouts, and graceful shutdown.
This project exists to practice HTTP service mechanics in a small Go codebase: registering routes, returning JSON, centralizing error responses, carrying request IDs through logs, recovering safely from pre-response panics, and shutting down cleanly when the process receives an interrupt.
It is meant to be understandable first. The router uses linear matching so the implementation stays easy to follow. The benchmark notes compare that tradeoff against chi, httprouter, and gorilla/mux when you want the measured performance details.
make test
make runIn another terminal, call the health endpoint:
curl -i -H 'X-Request-ID: demo-123' http://127.0.0.1:8080/healthThe server echoes the request ID and returns a compact JSON body:
HTTP/1.1 200 OK
X-Request-Id: demo-123{"status":"ok"}Then try a path parameter:
curl -i http://127.0.0.1:8080/api/v1/hello/Ada{"message":"Hello, Ada!"}And try a JSON request body:
curl -i -X POST http://127.0.0.1:8080/api/v1/echo \
-H 'Content-Type: application/json' \
-d '{"language":"go"}'{"echo":{"language":"go"}}If the JSON is malformed, has trailing tokens, or is too large for the demo endpoint, the server returns the same client-facing error shape:
{"error":"invalid JSON request body"}Each request also writes one log line to stdout:
method=GET path=/health request_id=demo-123 status=200 bytes=16 duration=95µs
For a deeper walkthrough of handlers, route parameters, middleware, error handling, request IDs, logging, panic recovery, and shutdown, read the API guide. For the measured router comparison, read the benchmark notes.
- The demo server is for local exploration. It does not include authentication, authorization, TLS setup, rate limiting, durable storage, or production deployment wiring.
- Route matching is linear. That keeps
pkg/minihttp/router.goeasy to understand, but high-route-count services should use a trie-based router or a mature framework. - Register routes during startup, before serving requests. Route mutation is not designed to run concurrently with request handling.
- Handlers should return errors before writing a response. Once headers or body bytes are committed, the router cannot replace the response with a JSON error.
Recovererconverts panics to JSON500responses only before the response is committed. After a response starts, it re-panics sonet/httpcan close the connection.- Request IDs are accepted as provided. If request IDs are security-sensitive in your environment, validate or replace incoming IDs at the edge.
- The benchmark numbers are direct in-process router dispatch measurements, not TCP, concurrent load-test, or requests-per-second results.