A RFC-compliant Go implementation of an HTTP/1.1 server using raw TCP sockets, without relying on Go's net/http package. This project demonstrates low-level HTTP protocol handling, including request parsing, header processing, response writing, and advanced features like chunked transfer encoding and trailers.
- Custom HTTP Request Parser: Parses HTTP/1.1 request lines, headers, and bodies from TCP connections, supporting Content-Length for bodies.
- Header Management: Validates and processes HTTP headers per RFC 7230, with case-insensitive keys and comma-separated values.
- Response Writer: Generates HTTP responses with status lines, headers, and bodies. Supports chunked encoding for streaming responses and trailers (e.g., SHA256 hash and content length).
- Simple Routing: Handles specific paths like
/video(serves a static MP4 file) and/httpbin/*(proxies requests to httpbin.org with chunked responses). - TCP Server: Non-blocking server with connection timeouts and graceful shutdown.
- Utilities: Includes a TCP listener for testing request parsing and a UDP sender (for unrelated testing or demo purposes).
httpfromtcp/
├── cmd/
│ ├── httpserver/ # Main HTTP server binary
│ │ └── main.go # Entry point: starts server on port 42069
│ ├── tcplistener/ # Simple TCP listener to parse and print requests
│ │ └── main.go
│ └── udpsender/ # UDP client to send stdin data to localhost:42069
│ └── main.go
├── internal/
│ ├── headers/ # HTTP header parsing and validation
│ │ ├── headers.go
│ │ ├── types.go
│ │ ├── utils.go
│ │ └── headers_test.go
│ ├── request/ # HTTP request parsing logic
│ │ ├── constants.go
│ │ ├── parsing.go
│ │ ├── request.go
│ │ ├── request_test.go
│ │ ├── types.go
│ │ └── utils.go
│ ├── response/ # HTTP response writing (status, headers, body, chunked)
│ │ └── response.go
│ └── server/ # Core TCP server implementation
│ └── server.go
├── .github/workflows/ci.yml # GitHub Actions CI
├── .gitignore
├── .pre-commit-config.yaml
├── go.mod # Go modules (Go 1.24.6, testify for testing)
├── go.sum
├── README.md
└── messages.txt # (Unused or placeholder file)
- Go 1.24.6 or later
go mod tidy
go build ./cmd/httpserver./httpserverThe server listens on localhost:42069. It supports graceful shutdown via SIGINT/SIGTERM.
Build and run the TCP listener:
go build ./cmd/tcplistener
./tcplistenerConnect via telnet localhost 42069 or curl to send requests and see parsed output.
go build ./cmd/udpsender
./udpsenderType input to send UDP packets to 127.0.0.1:42069.
- GET /video: Serves
assets/vim.mp4with Content-Typevideo/mp4and Connection: close. - GET /httpbin/*: Proxies to
https://httpbin.org(e.g.,/httpbin/ipfetches IP info). Uses chunked transfer encoding, streams response body, and adds trailers with SHA256 hash (X-Content-SHA256) and length (X-Content-Length). - Other paths: Returns 400 Bad Request or 404-like response.
Example curl:
curl http://localhost:42069/video # Streams video
curl http://localhost:42069/httpbin/user-agent # Proxied response with trailers- State Machine: Parses in phases (Pending → Headers → Body → Done).
- RequestLine: Extracts Method, Request-Target, HTTP-Version (only 1.1 supported).
- Headers: Integrated from
internal/headers. - Body: Accumulates based on Content-Length header.
- Handles partial reads with buffering.
- Validation: Ensures no space before colon, valid ASCII characters (32-126, no colon in keys).
- Parsing: Splits lines, trims spaces, lowercases keys, appends comma-separated values.
- Methods:
Parsefor incremental parsing,Get/Setfor access.
- Serve(port, handler): Starts TCP listener on
localhost:port, accepts connections in goroutines. - Handler: Function signature
func(*response.Writer, *request.Request). - Timeouts: 30-second deadline per connection.
- State: Tracks Open/Closed.
- Writer State Machine: Ensures order (Status → Headers → Body/Trailers).
- Status Codes: 200 OK, 400 Bad Request, 500 Internal Server Error.
- Chunked Encoding:
WriteChunkfor streaming,WriteChunkedBodyDonefor termination,WriteTrailersfor metadata. - Defaults: Helpers for Content-Length, Connection: close, text/plain.
- Unit tests in
internal/headers/headers_test.goandinternal/request/request_test.gousingtestify. - Run with:
go test ./internal/... - CI via GitHub Actions (
ci.yml) for linting and testing.
- Only HTTP/1.1 supported; no HTTP/1.0 or 2+.
- No HTTPS/TLS.
- Proxy limited to httpbin.org paths.
- Body parsing assumes Content-Length; no Transfer-Encoding: chunked for requests.
- UDP sender may be for separate testing.
Fork, make changes, and submit a PR. Ensure tests pass and follow Go conventions.
(Placeholder: Add your license here, e.g., MIT).