H2O

the optimized HTTP/1.x, HTTP/2, HTTP/3 server

Powered by Oktavia

Configure > HTTP/3

HTTP/3 uses QUIC as the transport protocol. A listen directive with a type attribute set to quic instructs the standalone server to bind to a UDP port on which QUIC packets will be sent and received. The binding must have an ssl attribute, as QUIC uses TLS/1.3 as the handshake protocol.

The example below setups a server that listens to both TCP port 443 and UDP port 443 using the same certificate and private key.

First listen directive binds the server to TCP port 443 with specified credentials, marking that directive as an YAML alias called &listen_ssl. Then, it reuses (YAML merge) the first listen directive, adding type: quic to create a UDP port 443 binding for accepting QUIC connections.

Example. Serving HTTP/1,2 and 3 on port 443
listen: &listen_ssl
  port: 443
  ssl:
    certificate-file: /path/to-ssl-certificate-file
    key-file: /path/to/ssl-key-file
listen:
  <<: *listen_ssl
  type: quic

Fine-tuning QUIC Behavior

To fine tune the behavior of QUIC, the quic attribute should be used in place of the type attribute specifying quic. The quic attribute accepts following parameters.

amp-limit
Amount of data that can be sent to the client before the client address is validated; see section 8.1 of RFC 9000. Default is 3.
handshake-timeout-rtt-multiplier
Handshake timeout in the unit of round-trip time. Default is 400.
max-initial-handshake-packets
Maximum number of Initial packets to be sent before the handshake is deemed to have failed. Default is 1,000.
max-streams-bidi
Maximum number of client-initated bi-directional streams. This parameter controls the HTTP request concurrency of a HTTP/3 connection. Default is 100.
max-udp-payload-size
See Section 18.2 of RFC 9000. Default is 1,472.
qpack-encoder-table-capacity
Size of the QPACK encoder table. Default is 4,096.
retry
A boolean flag (OFF or ON) indicating if a Retry packet should be used for validating the client address. Use of Retry packets mitigate denial-of-service attacks at the cost of incurring one additional round-trip for processing the handshake.
sndbuf, rcvbuf
Size of send and receive buffers, in the unit of bytes. Unlike the TCP counterparts that are per-connection, these buffers are associated to the listening port and applies to all the connections bound to that port.

The example below reuses a previous binding but sets the retry parameter to ON.

Example. HTTP/3 endpoint using Retry packets
listen:
  <<: *listen_ssl
  quic:
    retry: ON

Also, properties such as congestion controller and initial congestion window can be tuned using the top-level attribute of listen.

HTTP/3 Directives

Aside from QUIC-level properties, configuration directives listed below are provided for tuning HTTP/3 behavior.

Description:

Maximum duration to retain HTTP/3 connections in half-closed state, in seconds.

When a graceful shutdown of h2o is initiated, h2o at first sends a GOAWAY frame indicating the clients that it is initiating shutdown, then after one second, starts rejecting new HTTP requests (a.k.a. half-closed state).

This directive controls how long h2o should wait for the peer to close the QUIC connection in this half-closed state, before exitting.

If set to zero, this timeout is disabled. h2o will not shut down until all QUIC connections are closed by the clients or times out.

Level:
global
Default:
http3-graceful-shutdown-timeout: 0
Description:

If Generic Segmentation Offload should be used when sending QUIC packets.

Level:
global
Default:
http3-gso: ON
Description:

Idle timeout in the unit of seconds.

Unlike idle timeout of HTTP/1 and HTTP/2, this value should be small because it is faster to re-establish a new connection using 0-RTT than migrating to a different port due to NAT rebinding.

Level:
global
Default:
http3-idle-timeout: 30
Description:

Default window size for HTTP request body.

See http2-input-window-size.

Level:
global
Default:
http3-input-window-size: 16777216