Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setup a local HTTP/3 test server to toy with

Setup a local HTTP/3 test server to toy with

... and run curl against it.

This is not advice on how to run anything in production. This is for development and experimenting.

Preqreqs

An existing local HTTP/1.1 server that hosts files. Preferably also a few huge ones. You can easily create huge local files like truncate -s=8G 8GB - they are huge but do not occupy that much space on disk since they're just a big hole.

In my Debian setup I just installed apache2. It runs on port 80 and has a document root in /var/www/html. I can get the 8GB file from it with curl localhost/8GB -o dev/null

Build

ngtcp2

Get, build and install quictls:

git clone https://github.com/quictls/openssl.git
cd openssl
./config enable-tls1_3 --prefix=$HOME/build-quictls
make && make install

Get, build and install nghttp3:

git clone https://github.com/ngtcp2/nghttp3.git
cd nghttp3
autoreconf -fi
./configure --prefix=$HOME/build-nghttp3 --enable-lib-only
make && make install

Get, build and install ngtcp2:

git clone https://github.com/ngtcp2/ngtcp2.git
cd ngtcp2
autoreconf -fi
./configure PKG_CONFIG_PATH=$HOME/build-quictls/lib/pkgconfig:$HOME/build-nghttp3/lib/pkgconfig LDFLAGS="-Wl,-rpath,$HOME/build-quictls/lib" --prefix=$HOME/build-ngtcp2 --without-gnutls
make && make install

nghttpx

(You can opt to use Caddy instead, then you can skip this step)

Get, build and install nghttp2:

git clone https://github.com/nghttp2/nghttp2.git
cd nghttp2
autoreconf -fi
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/home/daniel/build-quictls/lib/pkgconfig:/home/daniel/build-nghttp3/lib/pkgconfig:/home/daniel/build-ngtcp2/lib/pkgconfig  LDFLAGS=-L/home/daniel/build-quictls/lib CFLAGS=-I/home/daniel/build-quictls/include ./configure --enable-maintainer-mode --prefix=/home/daniel/build-nghttp2 --disable-shared --enable-app --enable-http3 --without-jemalloc --without-libxml2 --without-systemd
make && make install

curl

Get, build and install curl:

git clone https://github.com/curl/curl.git
cd curl
./buildconf
LIBS="-ldl" LDFLAGS="-Wl,-rpath,$HOME/build-quictls/lib -Wl,-rpath,$HOME/build-curl/lib" ./configure --with-nghttp2=$HOME/build-nghttp2 --prefix=$HOME/build-curl --with-openssl=$HOME/build-quictls --with-ngtcp2=$HOME/build-ngtcp2 --with-nghttp3=$HOME/build-nghttp3
make && make install

(Alternative ways to build curl with HTTP/3 support are documented here)

Run

nghttpx

(You can opt to use Caddy instead, see below)

Run the local h3 server on port 9443, make it proxy all traffic through to HTTP/1 on localhost port 80. For local toying, we can just use the test cert that exists in curl's test dir.

CERT=$CURLSRC/tests/stunnel.pem
$HOME/bin/nghttpx $CERT $CERT --backend=localhost,80 \
  --frontend="localhost,9443;quic"

curl

Get the 8GB file over HTTP/3 using our h3-enabled curl:

$HOME/build-curl/bin/curl --http3 https://localhost:9443/8GB -o /dev/null

HTTP/3 server alternative

Caddy

You can run a HTTP/3 reverse-proxy using Caddy instead of nghttpx. Install caddy, you can even put the single binary in a separate directory if you prefer.

In the same directory you put caddy, create a Caddyfile with the following content to run a HTTP/3 reverse-proxy on port 7443:

{
        auto_https disable_redirects
	servers :7443 {
		protocol {
			experimental_http3
		}
	}
}

localhost:7443 {
	reverse_proxy localhost:80
}

Then run caddy:

./caddy start
@mholt
Copy link

mholt commented Dec 21, 2021

@bagder Ah, good point. Caddy will automatically redirect HTTP (port 80) to the HTTPS port. The easiest way to change these ports globally for the whole server is to use the http_port and https_port global options:

{
	http_port  7080
	https_port 7443
	servers :7443 {
		protocol {
			experimental_http3
		}
	}
}

localhost {
	reverse_proxy localhost:80
}

Another option is to disable automatic HTTPS redirects instead:

{
	auto_https disable_redirects
	servers :7443 {
		protocol {
			experimental_http3
		}
	}
}

localhost:7443 {
	reverse_proxy localhost:80
}

if you only want to listen on an HTTPS port.

@bagder
Copy link
Author

bagder commented Dec 21, 2021

Thanks, I added that into the actual instruction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment