From powering the old-future of AOL and to the new-future of now, fantastically 
done! From myself and I'm sure others too; many kudos to you Gustaf and 
NaviServer!

I also wanted to send praise this way as I've recently started a new job. Today 
where I needed to setup an PXE/KickStart server, after messing with the 
de-facto standard of Apache it failed in revealing hidden files (.treeinfo in 
this case). This too is with (no) help from certain ML-Bots.

Testing Lighttpd ish-worked which is another old favorite of mine also failed 
the task. (I realized after it was missing the mime type)

I threw up NaviServer & Tcl, applied the "hide dotfiles = false" parameter to 
the out-of-box simple configuration file and low & behold the studio now has a 
working kickstart system for Linux powered by NaviServer. It's not much but it 
puts me in the good books and I now I have Tcl available at my paws too. 

Lesson learnt, I should of jumped straight to NaviServer!

All the best,
David F


-----Original Message-----
From: Gustaf <[email protected]>
To: naviserver-devel <[email protected]>
Date: Friday, 12 September 2025 7:10 PM BST
Subject: [naviserver-devel] NaviServer and HTTP/3


Dear all,

you may have noticed that I have been rather quiet over the last weeks. Some 
emails and pull requests are still waiting for feedback from me - the reason is 
that I have been fully absorbed with adding HTTP/3 support to NaviServer.

A week ago, I managed to serve a simple curl GET request over HTTP/3 from 
NaviServer. Today, for the first time, I was able to load the OpenACS start 
page via HTTP/3 — including many parallel streams and a POST request (see 
“Protocol” column).




To give some background on why this effort matters: HTTP/3 is a very different 
animal compared to HTTP/1.x. It is built on top of QUIC, a UDP-based transport 
protocol originally developed by Google and later standardized by the IETF. 
QUIC integrates TLS 1.3, multiplexed bidirectional and unidirectional streams, 
flow control, and loss recovery directly into the transport layer. This avoids 
head-of-line blocking, enables faster connection establishment (including 0-RTT 
resumption), and even allows connections to survive client IP changes (e.g., 
Wi-Fi <-> mobile).

The relevant RFCs were finalized in 2021–2022: 

• RFC 9000: QUIC Transport
• RFC 9001: QUIC + TLS
• RFC 9002: QUIC Loss Detection and Congestion Control
• RFC 9114: HTTP/3
• RFC 9204: QPACK (Header Compression for HTTP/3)

Cloudflare was one of the earliest providers of HTTP/3 starting in 2021. nginx 
added support in 2023, while Apache still lacks native support. All major 
browsers can support HTTP/3 today, though deployment is not yet universal.

Integration into NaviServer

Adding HTTP/3 support required adapting NaviServer’s C-level APIs, because the 
QUIC stack provided by OpenSSL 3.5+ introduces a different threading model 
(e.g., using SSL_poll()). To handle this, NaviServer must allow drivers with 
their own event loop. The new h3 module provides this driver, while still 
reusing the nsssl configuration for ports, certificates, etc. As long as the 
new module is not loaded, existing HTTPS setups will continue to work unchanged.

At the moment, HTTP/3 is implemented as an extra module linked via 
configuration to nsssl. My plan is to include HTTP/3 in NaviServer 5.1, though 
some supporting changes will also land in the 5.0.x series. 

It’s important to note that serving a few requests over HTTP/3 is only the 
first milestone. There will be still a long way to go to reach a similar 
support level as for HTTP/1, including the full range of server features (e.g., 
100-continue, streaming requests) in a stable way. iIt will take some time, 
until the support is production-ready (leaks, no concurrency issues with higher 
load, etc.) Once that is achieved, the next logical step will be HTTP/3 client 
support, which will in turn be required for reverse proxying to upstream HTTP/3 
servers (maybe in 5.2)

Connection Model

In TCP connections over HTTP/1.x and HTTP/2, each client connection is 
identified by: 

      client IP + client port + server IP + server port + protocol

Every new client connection to the listening port creates an ephemeral port on 
the server side for later direct communication.

With HTTP/3 over QUIC, things are different: all requests are directed to the 
same port and these are then multiplexed over a single QUIC connection. This 
means, there is no ephemeral port on the server side, regardless of the number 
of streams. The server simply binds  on startup to a well-known port (usually 
UDP/443) and must handle the multiplexing logic internally. This has strong 
consequences for the integration into NaviServer - including how events are 
managed, how Ns_Socket is interpreted, and how drivers are implemented, etc. 
Furthermore, one needs a bidirectional mapping form between ns_sets and the 
QPAC headers, string based interfaces must be generalized, etc.

QUIC Stream Model

Each QUIC connection can multiplex multiple bidirectional streams for HTTP 
requests/responses, along with several unidirectional control streams for 
session management and header compression:


+-----------------------------------------------------------+
| QUIC Connection                                           |
|                                                           |
| Client-Initiated Unidirectional Streams:                  |
|  ┌──────────────────┐    ┌──────────────────┐             |
|  | Control Stream   |    | QPACK Encoder    |             |
|  └──────────────────┘    └──────────────────┘             |
|                                                           |
| Server-Initiated Unidirectional Streams:                  |
|  ┌──────────────────┐    ┌──────────────────┐             |
|  | Control Stream   |    | QPACK Decoder    |             |
|  └──────────────────┘    └──────────────────┘             |
|                                                           |
| Bidirectional Streams (many in parallel):                 |
|  ┌───────────────────────────────────────────────┐        |
|  | Request/Response Stream #1                    |        |
|  └───────────────────────────────────────────────┘        |
|  ┌───────────────────────────────────────────────┐        |
|  | Request/Response Stream #2                    |        |
|  └───────────────────────────────────────────────┘        |
|  ┌───────────────────────────────────────────────┐        |
|  | Request/Response Stream #N                    |        |
|  └───────────────────────────────────────────────┘        |
+-----------------------------------------------------------+


Each side (client and server) must open its own control stream 
(unidirectional). QPACK requires two unidirectional streams (encoder, decoder). 
Request/response pairs always use bidirectional streams. Streams are 
independent — packet loss in one stream does not block progress in others.

For a recent comparison of HTTP/2 and HTTP/3 in terms of features and 
performance, see:

    https://www.debugbear.com/blog/http3-vs-http2-performance

Best regards,
-gustaf
_______________________________________________
naviserver-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/naviserver-devel


_______________________________________________
naviserver-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/naviserver-devel

Reply via email to