Thanks for the detailed thoughts. I need to ponder them some more, this
seems like a good direction for long-term.
My concern is that waiting for the full design could delay HTTP/3 work.
The mod_http3 project is still young and has a lot of maturing ahead of it.
I propose retargeting PR #699 to the 2.4.x series as an enabling step,
while developing the broader design on 2.5.x. This would let the
community continue to grow, test, and gather feedback on mod_http3 in
parallel.
mod_http3 would adopt an odd/even release strategy. 0.2.0 could target
stable httpd 2.4.x, while 0.3.0-dev targets httpd 2.5.x-dev. When httpd
2.6.x is released, we could then ship mod_http3 0.4.0 as the
corresponding stable release, perhaps ready to be bundled with httpd by
then.
On 2026-08-16 14:28, Graham Leggett via dev wrote:
On 07 Aug 2026, at 15:05, Steffen <[email protected]> wrote:
Developing an HTTP3 module for Apache HTTPD is something that is
desperately needed, noting alternative web servers already offer
HTTP3 support, e.g. NGINX and Caddy.
This is very cool work, happy to help you.
Whilst there's evidence of people actively working towards this, e.g.
https://github.com/machine-moon/mod_http3, it's evidently not
possible with the current 2.4.x code branch. To that end PR#699
https://github.com/apache/httpd/pull/699 has been raised, as a
workaround to allow (some) MPM's to note connections that are not TCP
based.
The following post provides a detailed insight to these issues -
https://codeit.guru/apache-http3-pr-699-mpm-quic-backport-2-4-68
Not had a chance to look at the code yet, but some comments on the
post above.
Brain dump to follow.
"The pull request proposes two optional MPM functions"
Optional functions come with the limitation that only one module can
grab them. Ideally instead of optional functions they should be hooks,
this allows more than one module to be present and do potentially do
work in different ways.
One place where httpd definitely needs a hook is receiving socket
descriptors.
Right now there is code hardcoded in httpd core that is aware of
systemd for example, which can pass a pre-opened socket to httpd. That
really should be a hook that is called when some code in a module has
a socket ready. The core can be pure "open TCP or UDP", while an extra
module can be systemd.
This means systemd can pass UDP sockets to mod_http3 in future and it
just works.
"Every successful call to: ap_mpm_note_extra_connection_added() must
eventually have exactly one matching call to:
ap_mpm_note_extra_connection_removed()"
This is largely impractical, it is pretty much guaranteed that an
error path will be mishandled at some point, which will lead to
instability in the server.
The way httpd handles this is through the use of memory pools
(arenas), each unit of work in httpd has its own pool. When the unit
of work is finished, because it succeeded or failed, doesn't matter,
the memory is cleaned up as a single unit, along with any extra
resources like connection handles etc.
https://apr.apache.org/docs/apr/1.7/group___pool_cleanup.html
Pools are hierarchical, for example a request is created from a
connection. If the request ends for whatever reason, run
apr_pool_destroy(r->pool) will make that request go away. If the
connection dies for whatever reason, run apr_pool_destroy(c->pool) and
the connection, along with any requests currently in progress, will
all go away.
Sometimes you might have a relationship between things that aren't
nested, like an LDAP connection pool. The LDAP connection pool lives
alongside HTTP requests. While the LDAP connection is being used by a
request, a cleanup is registered with the request to return the LDAP
connection to the pool at the end. No matter what happens to the
request, sanity returns to the LDAP connection pool.
What all this means is that you need just one call,
ap_mpm_note_extra_connection_added(), which is passed a pool, and it's
the job of your code to register a cleanup in that pool.
"The MPM owns the process lifecycle, but protocol modules may own
additional connection lifecycles and report them through a defined API."
We have the option to rethink how nghttp3 and httpd mesh with one
another, and given certain limitations inside the core, this is likely
to be necessary.
Thinking out loud, the first hook needed is the hook that allows us to
open TCP or UDP sockets, either natively or from systemd, at or around
make_sock() here
https://github.com/apache/httpd/blob/trunk/server/listen.c#L72
Then each MPM would need a hook to pass UDP packets to. This hook
might use ngtcp2 or openssl to decode the packets, and then pass to a
hook that does nghttp3.
nghttp3 would the make a conn_rec out of nghttp3_conn, and then make a
request_rec out of the callbacks for headers.
The entry point where the request is processed is possibly here at
ap_process_async_request():
https://github.com/apache/httpd/blob/trunk/modules/http/http_request.c#L406
Alternatively, if the above function has too many side effects, run
these three hooks ap_run_quick_handler(),
ap_process_request_internal(), and ap_invoke_handler() one after the
other and process the return code appropriately:
https://github.com/apache/httpd/blob/trunk/modules/http/http_request.c#L447
https://github.com/apache/httpd/blob/trunk/modules/http/http_request.c#L449
https://github.com/apache/httpd/blob/trunk/modules/http/http_request.c#L451
You would need to replace the connection filters with a filter that
injects data into the request, and then allows writing of data from
the request.
The filter would return EAGAIN until all the request is read, and
unlike ap_process_async_request(), you would pass more data in and
keep going until that hook is happy.
Some work might be required to make sure things are properly
re-entrant, but that's doable and reasonable I think.
At the end of ap_invoke_handler() you will have buckets ready to be
written, you can write those buckets to the network and process the
next request. Make sure you limit the number of requests in flight
like this lest you run out of file handles.
We believe it would be really helpful if PR#699 could be approved for
subsequent 2.4.x releases, and equally whether similar functionality
could be added to mpm_winnt, so support for HTTP3 could be developed
for Windows platforms too.
Windows has its own http3 implementation called MsQuic, if the hooks
above are created carefully it should be possible to switch in MsQuic
instead of ngtcp2/nghttp3.
Regards,
Graham
--
--
Cheers,
Tarek
GPG Fingerprint: B9BD295C26A1ED077599810CA284507F96DB79EF