A custom HTTP web server built from scratch using Go's raw TCP sockets. This project demonstrates how to create a web server without using any HTTP framework, handling raw socket connections and manually parsing HTTP requests.
- Raw TCP Socket Implementation: Built using Go's
netpackage for direct socket handling - Manual HTTP Parsing: Custom HTTP request parsing without external libraries
- Static File Serving: Serves HTML files from the
publicdirectory - Concurrent Request Handling: Uses goroutines for handling multiple client connections
- Keep-Alive Connections: Supports persistent connections with timeout management
- Error Handling: Custom 404 error pages for missing files
golang/
├── go.mod # Go module definition
├── main.go # Main server entry point
├── server/
│ └── server.go # HTTP request parsing logic
├── public/ # Static web files
│ ├── home.html # Homepage with server status
│ ├── error.html # Error page template
│ ├── contact/
│ │ └── contact.html # Contact page
│ └── parser.go # File serving logic
└── README.md # This file
- Go 1.24.4 or later
- Basic understanding of TCP sockets and HTTP protocol
go run main.goThe server will start and listen on localhost:3000
Open your browser and navigate to:
- Homepage: http://localhost:3000/home.html
- Contact Page: http://localhost:3000/contact/contact.html
| Endpoint | Description | File Served |
|---|---|---|
/home.html |
Homepage with server status | public/home.html |
/contact/contact.html |
Contact page | public/contact/contact.html |
/error.html |
Error page | public/error.html |
| Any other path | 404 Not Found | Custom error message |
- TCP Listener: Creates a TCP listener on port 3000
- Connection Handling: Accepts incoming connections and spawns goroutines
- Request Parsing: Manually parses HTTP requests to extract the requested path
- File Serving: Maps paths to files in the
publicdirectory - Response Generation: Crafts HTTP responses with proper headers
- Sets up TCP listener on
localhost:3000 - Handles incoming connections with goroutines
- Manages connection timeouts (30 seconds)
- Implements keep-alive connections
ParsePathName(): Extracts the requested path from HTTP request- Parses raw HTTP request bytes to find the path between
/andHTTP
ParsePublic(): Maps requested paths to actual files- Handles directory traversal and file serving
- Returns 404 errors for missing files
- Case-insensitive file matching
- Start the server:
go run main.go - Use curl to test endpoints:
# Test homepage
curl http://localhost:3000/home.html
# Test contact page
curl http://localhost:3000/contact/contact.html
# Test 404
curl http://localhost:3000/nonexistent.html- Open http://localhost:3000/home.html in your browser
- The homepage includes a beautiful dashboard showing server status
- Test navigation between different pages
$ go run main.go
Received New User 127.0.0.1:54321$ curl -v http://localhost:3000/home.html
* Connected to localhost (127.0.0.1) port 3000
> GET /home.html HTTP/1.1
> Host: localhost:3000
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Content-Length: 12345
< Connection: keep-alive
< Keep-Alive: timeout=30, max=100- Create HTML file in
public/directory:
<h1>New Page</h1>- Connection Errors: Server continues running if individual connections fail
- File Not Found: Returns custom 404 messages for missing files
- Timeout Handling: Connections timeout after 30 seconds of inactivity
- Directory Traversal: Safely handles requests for non-existent directories
Edit main.go line 37:
conn, err := net.Listen("tcp", "localhost:3000") // Change port here- Create directories in
public/as needed - Add HTML, CSS, JS files
- Access via URL path matching directory structure
Edit main.go line 28 to customize HTTP response headers:
ctx := fmt.Sprintf("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nCustom-Header: value\r\n\r\n%s", len(pageFile), pageFile)This project demonstrates:
- Raw TCP socket programming in Go
- Manual HTTP protocol implementation
- Concurrent programming with goroutines
- File system operations
- Error handling patterns
This project is for educational purposes. Feel free to use and modify as needed.
Happy Coding! 🚀
Built with ❤️ using Go's raw TCP sockets