Build a Minimal Local HTTP/1.1 Server (No Frameworks)
Context
You are asked to implement a minimal HTTP/1.1 server from scratch using only the standard library (no web frameworks). The server should run locally, be configurable, and handle concurrency and shutdown cleanly. Include unit tests and clear run instructions.
Requirements
-
Configuration
-
Listen on a configurable host and port.
-
Serve static files from a configurable root directory.
-
Protocol and Methods
-
Parse HTTP/1.1 requests: request line, headers, and optional body.
-
Support methods: GET and POST.
-
Return appropriate errors: 400 (Bad Request), 404 (Not Found), 405 (Method Not Allowed).
-
Routing
-
GET /health → returns 200 OK with body "OK".
-
POST /echo → returns the request body verbatim, with Content-Type preserved if present.
-
Static files: for any other GET path, serve files from the configured root directory.
-
Use correct Content-Type for common file extensions.
-
Protect against path traversal attacks (e.g., ".." segments).
-
Concurrency and Reliability
-
Handle multiple concurrent connections.
-
Per-connection request timeout.
-
Graceful shutdown (e.g., on SIGINT/SIGTERM): stop accepting new connections and allow in-flight requests to finish.
-
Observability
-
Structured per-request logging (e.g., JSON lines) including: timestamp, remote address, method, path, status, duration, bytes in/out, and user agent.
-
Testing and Docs
-
Include unit tests that verify the core behaviors.
-
Provide clear run instructions for local development.
Constraints
-
Use only the language standard library. No web frameworks (e.g., Flask, Express, Spring), no third-party libraries.
-
Keep the implementation minimal but robust enough for the above requirements.