mh2c-go is a manual HTTP/2 client library for debugging servers.
This project is not a high-level HTTP client. It is designed for building, sending, receiving, and inspecting HTTP/2 frames directly, including unusual or intentionally malformed traffic when needed.
The current implementation provides:
- manual frame assembly in the
framepackage - TLS + ALPN
h2connection handling intlsconn - a low-level client in
client - HPACK support via
golang.org/x/net/http2/hpack, wrapped by the localhpackpackage - a manual debugging CLI in
cmd/mh2c
Reusable CLI examples live under examples/, including observe
flows, script files, and a small jsonl consumer.
make build-cli
./bin/mh2c --helpOr install it into your Go bin directory:
go install ./cmd/mh2c
mh2c --helpThe repository-wide build still works as before:
go build ./...go test ./...cmd/mh2c is a manual HTTP/2 debugging client. It prints received frames and
their payload details instead of hiding protocol activity behind a
curl-style response summary.
mh2c request [options]
mh2c ping [options]
mh2c observe [options]
mh2c script run --script-file file.toml [options]
mh2c script describe [--type action_type]
mh2c script template request
mh2c script validate --script-file file.toml
Request:
./bin/mh2c request \
--url https://nghttp2.org/httpbin/headers \
--header 'user-agent:mh2c-go'POST request:
./bin/mh2c request \
--url https://nghttp2.org/httpbin/post \
--method POST \
--header 'content-type: application/json' \
--data '{"message":"hello from mh2c-go"}'PING:
./bin/mh2c ping \
--host nghttp2.org \
--ping-data mh2cpingObserve selected traffic:
./bin/mh2c observe \
--host nghttp2.org \
--frame-filter headers \
--frame-filter data \
--stream-filter 1 \
--save-body ./body.bin \
--save-headers ./headers.txtRun a script:
./bin/mh2c script run --script-file ./examples/request.tomlOther checked-in examples:
./bin/mh2c script run --script-file ./examples/unusual-raw-sequence.toml
./bin/mh2c observe --host nghttp2.org --output jsonl | go run ./examples/jsonl-summaryUse the script helpers to inspect the supported TOML shape before editing a script file:
./bin/mh2c script describe --type headers
./bin/mh2c script template request
./bin/mh2c script validate --script-file ./examples/request.tomlReusable script files live under examples/. A normal request
flow is available in examples/request.toml, and
examples/unusual-raw-sequence.toml shows how to keep raw protocol details
visible.
Command and target options:
make build-clicreates./bin/mh2cfor local usemake installrunsgo install ./cmd/mh2cmh2c request,mh2c ping,mh2c observe, andmh2c script ...are the supported command forms--urloverrides--scheme,--host,--port, and--path--body-file path/to/filereads the request body from a file--body-file -reads the request body from stdin--authorityoverrides the:authoritypseudo-headermh2c observeperforms the HTTP/2 handshake and continues printing received frames untilGOAWAY,--timeout, or--max-recv--max-recv Nlimits the number of received frames in observe mode;0means unlimited
Output controls:
--stream-filter idkeeps stream-specific output focused on one stream while still showing connection-level frames--direction-filter sent|receivedis repeatable and keeps output focused on sent events, received events, or both--frame-filter nameis repeatable and acceptssettings,headers,continuation,data,ping,goaway,window_update,rst_stream,push_promise,priority, andraw--output jsonlemits one JSON line per event instead of the default text output--data-format text|hex|bothcontrols how DATA, PING, and GOAWAY debug payloads are rendered--data-limit Ntruncates displayed payload bytes;0means unlimited--decode-headers=falsedisables HPACK header decoding in CLI output--show-header-block=falsehides HPACK/header block fragments from the output--save-output pathmirrors the displayed CLI output into a file--save-body pathstores the captured response body in request/observe mode--save-headers pathstores decoded response headers in request/observe mode
Script mode:
mh2c script run --script-file file.tomlexecutes a scripted frame sequencemh2c script describe [--type action_type]prints supported script action fieldsmh2c script template requestprints a starter TOML scriptmh2c script validate --script-file file.tomlchecks a script without connecting to a server- script mode does not auto-send connection preface or SETTINGS; include them explicitly when needed
- supported script actions are
preface,sleep,settings,headers,continuation,data,ping,goaway,window_update,rst_stream,priority,push_promise,raw, andreceive sleepusesduration_ms = <int>and prints progress such as>> SLEEP 500ms- the script parser accepts the TOML subset used in the example above:
strings, integers, booleans, string arrays,
[connection], and[[action]]
Manual debugging boundary:
- the default request/script helpers aim to keep common HTTP/2 state in sync so normal debugging stays practical
- this does not turn
mh2c-gointo a high-level client: frames are still explicit and visible in the CLI output - when you want to bypass helper-managed state and send unusual or intentionally invalid bytes, prefer
block_hexorraw - received frames are printed with payload details such as decoded headers, DATA text/hex, SETTINGS entries, and PING payloads
go run ./cmd/mh2c request ...still works for ad-hoc execution without producing a local binary
cmd/mh2c manual HTTP/2 debugging CLI
client/ connection preface, raw I/O, frame send/receive, HPACK helpers
frame/ manual HTTP/2 frame types and binary encoding/decoding
hpack/ HPACK implementation and wrapper helpers
tlsconn/ TLS connection bootstrap with ALPN h2
internal/ internal wire helpers