webServerHTTP is a simple educational HTTP server written in C++ using Windows API (WinSock2).
The main goal of this project is to practice network programming, understand the basics of the HTTP protocol,
and learn how to build and structure a server application in C++.
It is not a production-ready server, but rather a training project for: Understanding socket programming in Windows Handling multiple client connections Serving static web content (HTML files) Building projects with CMake
TCP listener (TcpListener) + non-blocking sockets Basic WebServer with request parsing Serving files from wwwroot/ GET / POST / DELETE Content-Length body reading CMake project structure
Algorithm: 1 class (ServerConfig) + the parser class (ConfigParser)
- listen – define host:port the server listens on
- server_name – domain names for virtual host routing
- root – base directory for serving static files
- index – default file served for directories
- error_page – map HTTP status codes to custom HTML pages
- client_max_body_size – limit the size of request bodies
- allowed_methods – allowed HTTP methods (GET, POST, DELETE)
- autoindex – enable/disable directory listing
- upload_store – directory where uploaded files are saved
- root (per location) – override root for this specific route
- index (per location) – override index for this route
- cgi_extension – file extensions triggering CGI execution
- cgi_path – path to the CGI interpreter (php-cgi, python3, etc.)
- Multiple server blocks
- Default server behavior
- Support nested blocks
- Support multiple location blocks
- Ignore whitespace and newlines
- Detect invalid syntax
- Host
- User-Agent
- Content-Length
- Content-Type
- Accept-Charset
- Authorization
- Date
- Server
- Location
- Retry-After
- WWW-Authenticate
- Accept-Language
- Allow
- Content-Language
- Content-Location
- Last-Modified
- Referer
- Transfer-Encoding
- 404 Not Found
- 403 Forbidden
- 500 Internal Server Error
- Non-blocking sockets using fcntl(O_NONBLOCK)
- Single select() loop for ALL FDs
- No read/write without select
- Handle partial reads
- Handle partial writes
- State-machine per client (READ → PROCESS → WRITE)
- Graceful client disconnect
- Parse request line (METHOD URI VERSION)
- Parse headers (strict RFC)
- Validate Host
- Normalize URL (remove ../, duplicate slashes)
- Detect body type
- Handle Content-Length body
- Handle chunked transfer encoding
- Support incomplete request reads
- Create status line (HTTP/1.1
) - Send required headers
- Serve static files (non-blocking)
- Directory handling
- [ ] index file
- [ ] autoindex (HTML generation) - Correct error response fallback
- Chunked responses (when body size unknown)
- Keep-alive connections (optional but recommended)
- Select correct server block based on Host header
- Select correct location based on URI
- Apply location-level root/index/allow rules
- Return 405 for disallowed methods
- Return 404 for missing files
- Return 403 for forbidden paths
- Fork ONLY for CGI
- Set all CGI meta-variables, including:
- [ ] REQUEST_METHOD
- [ ] SCRIPT_NAME
- [ ] PATH_INFO
- [ ] PATH_TRANSLATED
- [ ] QUERY_STRING
- [ ] CONTENT_LENGTH
- [ ] CONTENT_TYPE
- [ ] SERVER_PROTOCOL
- [ ] SERVER_NAME
- [ ] SERVER_PORT
- [ ] GATEWAY_INTERFACE
- [ ] REMOTE_ADDR
- Send request body to CGI stdin
- Read CGI stdout until EOF
- Respect CGI headers (Status, Content-Type, etc.)
- Support php-cgi
- Correct working directory (chdir to file’s directory)
- No memory leaks (valgrind clean)
- No crashes even under stress
- No hanging requests
- FD cleanup for every client
- Survive multiple parallel clients