How maemran/webserver works
1. What this repository is
- WebServ is a C++98 HTTP/1.1 server built as a single executable from srcs/main.cpp.
- The architecture is split into clear modules: configuration, network/socket handling, HTTP parsing and response generation, CGI execution, and cookie/session support.
2. Startup and configuration boundary
- On launch, the server reads config_file/config.conf.
- The config subsystem (ConfigLexer, ConfigParser, ConfigValidator, plus HttpConfig, ServerConfig, LocationConfig) turns the text config into structured server/location rules.
- This layer defines the runtime topology: which ports to listen on, which roots to use, allowed methods, redirects, error pages, CGI mappings, and body-size limits.
3. Socket and connection layer
- The socket subsystem (serversocket, connection) owns all POSIX networking concerns: bind/listen/accept, client connection lifecycle, and monitoring multiple file descriptors.
- The README indicates a non-blocking event loop using select() or poll(), so the server is a single-process, multiplexed I/O design rather than a thread-per-client model.
4. Event-driven request ingestion
- Incoming bytes from client sockets are accumulated into a connection object and handed to the HTTP layer.
- This creates the first major runtime boundary: raw TCP stream on one side, parsed HTTP request object on the other.
5. HTTP parsing and request model
- HttpRequest, URI, and the HTTP-related parsing logic convert raw request data into method, target URI, headers, and body.
- This layer is responsible for validating basic HTTP syntax, handling request metadata, and preparing the request for routing and execution.
6. Routing and config matching
- router.cpp connects the parsed request to the active config context.
- It resolves the correct server block and then the most specific location block for the URI.
- From there it enforces per-location rules such as allowed methods, roots, indexes, autoindex, redirects, and body-size limits.
7. Static content serving
- For normal file requests, the server resolves paths against the configured root and serves files from webroot/.
- The repository contains representative static content: HTML pages, CSS, images, blog pages, forms, and custom error pages.
- Directory requests are handled through index resolution and, where enabled, directory listing behavior.
8. CGI execution boundary
- The CGI subsystem (CgiHandler) is the dynamic-content path.
- Requests targeting configured CGI extensions in webroot/cgi-bin/ are executed via an external interpreter such as Python or PHP.
- The server acts as the bridge: it prepares environment variables, passes request data to the child process, reads CGI output, and converts it into an HTTP response.
9. Response construction
- HttpResponse assembles the outbound message: status line, headers, and body.
- It is responsible for producing standards-compliant responses for success cases, redirects, errors, HEAD responses, and CGI output.
- The response path also handles connection metadata and content headers.
10. Error handling and custom pages
- The config and response layers work together to map failures to HTTP status codes and custom HTML pages.
- The repository includes webroot/errors/403.html, 404.html, and 500.html, which are used as configured error documents rather than generic fallback text.
11. Cookie/session support
- cookies/Cookie and cookies/Session suggest a lightweight state-management subsystem.
- This is a supporting boundary, not the core server loop: it likely helps with request/response state, tracking client sessions, or formatting cookie headers.
12. Repository structure mirrors runtime roles
- includes/ contains the public interfaces for each subsystem.
- srcs/ contains the implementation.
- webroot/ is the served content tree, while assets/ contains project documentation imagery rather than runtime assets.
13. Overall data flow
- The runtime flow is: config parse → socket setup → event loop → request parse → route match → static file / CGI / redirect / error handling → response assembly → socket write.
- That is the key diagram to draw: a config-driven, event-loop-based HTTP server with explicit boundaries between networking, HTTP semantics, routing, and CGI execution.
Main entry points: router.hpp Router · HttpResponse.hpp Http response · HttpRequest.hpp Http request · serversocket.hpp Server socket
Components 16
Config
Configuration parsing and runtime server rules
- Config lexer · Tokenizes the config file
includes/Config/ConfigLexer.hpp - Config parser · Builds structured config objects
includes/Config/ConfigParser.hpp - Config validator · Checks config consistency and limits
includes/Config/ConfigValidator.hpp - Server config · HttpConfig, ServerConfig, LocationConfig
includes/Config/HttpConfig.hpp
Network
Socket lifecycle and event-driven client I/O
- Server socket · Bind/listen/accept and multiplexed I/O
includes/Socket/serversocket.hpp - Connection · Per-client socket buffering and lifecycle
includes/Socket/connection.hpp
HTTP
Request parsing, routing, and response generation
- Http request · Parses method, URI, headers, and body
includes/HTTP/HttpRequest.hpp - URI · Normalizes and interprets request targets
includes/HTTP/URI.hpp - Router · Matches request to server and location rules
includes/HTTP/router.hpp - Http response · Assembles status, headers, body, and errors
includes/HTTP/HttpResponse.hpp
CGI
Dynamic execution boundary for external scripts
- Cgi handler · Runs external CGI scripts and reads output
includes/CGI/CgiHandler.hpp
State
Lightweight cookie and session support
Content
Served filesystem tree and custom error pages
- Webroot · Static pages, CGI scripts, and error documents
webroot - Error pages · Configured 403, 404, and 500 responses
webroot/errors
Other components
- Server main · Program startup and orchestration
srcs/main.cpp
Connections 18
- Server main → Config lexer: loads config · Startup reads the config file through the config pipeline
- Config lexer → Config parser: tokens · Lexer output feeds the parser
- Config parser → Config validator: validates · Parsed config is checked for correctness and limits
- Config validator → Server config: builds runtime rules · Validated config becomes server and location topology
- Server main → Server socket: starts listener · Main initializes the multiplexed server socket
- Server socket → Connection: accepts clients · Listener creates and manages per-client connection state
- Connection → Http request: assembles request · Incoming bytes are accumulated into HTTP requests
- Http request → URI: parses target · Request target is normalized and interpreted as a URI
- Http request → Router: dispatches · Parsed request enters routing and config matching
- Server config → Router: routes by rules · Router uses server and location config to select behavior
- Router → Webroot: serves content · Static file requests resolve into the served tree
- Router → Error pages: maps failures · Routing and validation errors select custom error pages
- Router → Cgi handler: executes cgi · Configured CGI targets are handed to the CGI subsystem
- Router → Http response: produces response · Routing outcomes are converted into outbound HTTP responses
- Cgi handler → Http response: cgi output · CGI stdout is wrapped into an HTTP response
- Http response → Server socket: writes back · Response data is sent to the client socket
- Http response → Cookie: sets cookies · Response headers may carry cookie metadata
- Cookie → Session: supports session · Cookie state can back lightweight session tracking