Apache httpd
Posts
-
Digging into Apache httpd's Source 1: How I Read It with AI, and the Map
The first post of a series on reading the httpd source, starting with pictures and a 3-minute hands-on run that show what Apache httpd is, how it works and what it is for. It covers which version is read (trunk, 2.5.1-dev), how to get the same source and build it in Docker (including the places I actually got stuck), a folder map of the roughly 350,000-line codebase, the big road one request travels, and how AI-written notes are re-checked against the source.
-
Digging into Apache httpd's Source 2: Before Reading a Server Written in C — Structs, Function Pointers, Macros
Where does the saying "C structs are more beautiful than C++ or Java objects" come from? Without classes or interfaces, how does httpd plug modules in? We check it against the real source and real runs — memory layout with nothing hidden, interfaces built from function pointers, a void * array indexed by module_index, hook functions stamped out by macros, the MMN check that lets httpd trust a separately compiled .so — and the things C will not do for you.
-
Digging into Apache httpd's Source 3: The Big Picture — Core, APR, MPM, Modules and the Three Big Structs
A map for anyone opening the Apache httpd source for the first time. We look at the layers (operating system, APR, core, MPM, modules), why even the core is a module, how modules compiled into the binary differ from ones loaded with LoadModule, the three structs server_rec, conn_rec and request_rec, the pool hierarchy, and the path a single request takes — all checked against the real source and examples I actually ran.
-
Digging into Apache httpd's Source 4: APR Memory Pools — Managing Memory Without free()
You will hardly find free() in httpd's C code. Instead of handing memory back piece by piece, httpd groups everything with the same lifetime — "one request", "one connection" — into a pool and throws it away in one go. This post looks at APR pool nodes and the allocator, why apr_palloc is just a pointer bump, the order cleanups run in, where httpd creates and destroys its pools, and the two classic mistakes — all checked against the real source and real runs.
-
Digging into Apache httpd's Source 5: main() and Startup — Why the Config Is Read Twice, and Restarts
What happens inside main() when you start httpd, followed through all 914 lines of server/main.c. Why the config file is read twice, how one apachectl graceful makes main()'s loop go round once more, and where a server started as root drops to User — checked against the source and against real log output.
-
Digging into Apache httpd's Source 6: Modules and Hooks — How a Module Plugs into the Server
Nearly every feature of httpd is a module, and a module plugs into the server by attaching functions to fixed points called hooks. Using the source at a pinned commit and three small modules written for this post, we look at the module struct, the two ways a module gets registered (static modules and LoadModule), what the hook macros really expand to, how RUN_FIRST differs from RUN_ALL, and how the call order is decided from order values and the names of other modules.
-
Digging into Apache httpd's Source 7: The Config File and Directives — How One Line of httpd.conf Becomes a C Struct
How does one line you write in httpd.conf end up calling a module's C function and filling in a struct? We follow server/config.c — reading the file into a tree and then walking it, the hash that finds a directive by name, argument styles like TAKE1, FLAG and ITERATE, the bit test behind "not allowed here" and AllowOverride, and when the values in Directory, Location and VirtualHost sections get merged — all checked with a directive we wrote ourselves.
-
Digging into Apache httpd's Source 8: MPMs — How prefork, worker and event Share Out Connections
Follows in the source what the single line LoadModule mpm_event_module in httpd.conf actually changes. How an MPM can be swapped as one module (the mpm hook and ap_mpm_query), prefork that only uses processes, worker that splits the job between a listener thread and a queue, event that takes keep-alive connections off the threads and hands them to epoll, the parent's once-a-second loop that grows and shrinks the children, the shared-memory scoreboard, and where StartServers, MaxRequestWorkers and ThreadsPerChild end up in the code — all checked with ps, mod_status and gdb.
-
Digging into Apache httpd's Source 9: Connections and Reading a Request — From a Socket to a request_rec
Follows one socket handed over by the MPM as it becomes a conn_rec, and then a request_rec once the request line and headers are read — all in the httpd source. Why the core always stands last in the hooks, where the keep-alive loop lives depending on the MPM, how trunk moved request-line reading into a filter, and the two steps that pick a virtual host from the Host header, each checked with an example.
-
Digging into Apache httpd's Source 10: Request Processing — From a URL to a File and a Handler
How does the single line GET /hello.html become a file on disk and a handler that sends it out? We follow the order of the phases in ap_process_request_internal() through the real source. We also look at the three walks that merge Location, Directory and Files settings, mod_dir's subrequest and ErrorDocument's internal redirect, using a module that logs every phase.
-
Digging into Apache httpd's Source 11: Filters and Bucket Brigades — How a Response Flows Out
What shape a response takes inside httpd on its way from the handler to the socket, followed for someone opening the source for the first time. APR-util's buckets and brigades (a ring), PIPE and FILE buckets that change shape when read, filters lining up in six tiers and ap_pass_brigade, chunked encoding and sendfile, and what the core output filter does when the socket is full — all checked with the log of a filter module written for this post.
-
Digging into Apache httpd's Source 12: Handlers and Static Files — How a File Becomes a Response
How the "handler" set by SetHandler and AddHandler differs from the Content-Type, and how the core's default_handler() answers any request nobody else claimed by sending a single file bucket. We also check ETag and 304, Range and 206, the trailing-slash 301 and DirectoryIndex, and which system calls EnableSendfile and EnableMMAP actually change — with curl and strace.
-
Digging into Apache httpd's Source 13: Authentication and Authorization — How a Require Line Is Decided
We follow what AuthType Basic, AuthUserFile, Require valid-user and <RequireAll> in httpd.conf actually do in the source. Why "who are you" (authentication) and "may you come in" (authorization) live in separate modules, providers that are swapped in by name, the Require tree and its GRANTED, DENIED and NEUTRAL results, and the order in request.c that runs the same decision twice — all checked against the real source and example output.
-
Digging into Apache httpd's Source 14: mod_proxy — Reverse Proxy and Load Balancer
We follow one ProxyPass line through the source until the request reaches another server. We see where the URL turns into a "proxy:..." r->filename, how proxy_handler() hands the work to the scheme handler hook, the worker and connection pool that each backend gets, how mod_proxy_http streams the response back through brigades, and how the byrequests balancer alternates between two backends — checked with two backends running in a container.
-
Digging into Apache httpd's Source 15: mod_ssl — Where TLS Plugs In
The httpd core knows nothing about TLS, yet one SSLEngine on line gives you HTTPS. We follow, in the source and with examples, how mod_ssl hooks into startup and every connection, slips OpenSSL into the filter chain with connection filters and home-made BIOs, swaps the virtual host and certificate based on SNI, and hands SSL_* variables to other modules.
-
Digging into Apache httpd's Source 16: Logging — Access Logs, Error Logs, and Wrapping Up the Series
How httpd's two kinds of log are actually written, followed through the source. How one ap_log_rerror() call is filtered by a macro before anything runs, how module_index lets LogLevel differ per module, how ErrorLogFormat and LogFormat strings become arrays of function pointers, exactly when the log_transaction hook fires, and how a piped log program is restarted — all checked with examples, followed by a look back over the 16-part series.