Wade
Keep your socks dry.
HTTP client-server for Erlang.
Quick Start (HTTP/1.1)
%% Start server
wade_app:start(8080).
%% Add route
wade:route(get, "/hello/[name]", fun(Req) ->
Name = wade:param(Req, name),
"Hello " ++ Name ++ "!"
end, []).
Visit http://localhost:8080/hello/world
API
One function rules them all:
wade:route(Method, Path, Handler, RequiredParams, RequiredHeaders).Helpers:
wade:param(Req, Key)- URL parameterswade:query(Req, Key)- Query stringwade:body(Req, Key)- POST datawade:method(Req)- HTTP method
Examples
%% Simple route
wade:route(get, "/", fun(_) -> "Hello!" end, []).
%% URL parameters
wade:route(get, "/user/[id]", fun(Req) ->
wade:param(Req, id)
end, []).
%% POST with validation
wade:route(post, "/api", Handler, [name, email]).
%% Any HTTP method
wade:route(any, "/api/[resource]", Handler, []).
%% JSON response
wade:route(get, "/json", fun(_) ->
{200, "{\"ok\": true}", [{"Content-Type", "application/json"}]}
end, []).No XML. No complex routing. No wet socks.
Server-Sent Events (SSE)
Wade includes built-in support for Server-Sent Events (SSE) — a lightweight HTTP streaming protocol for sending real-time event updates from the server to connected clients. SSE enables one-way communication (server → client) over a persistent connection, ideal for live notifications, progress updates, and continuous data streams. With Wade’s simple API, you can register SSE routes and stream custom events in just a few lines of code, without needing complex WebSocket setups.
QUIC / HTTP/3
Wade QUIC is a pure Erlang implementation of QUIC (RFC 9000) and HTTP/3 (RFC 9114).
Features
- QUIC transport (UDP, packet parsing, connection state machine)
- TLS 1.3 handshake and key derivation
- Streams (bidirectional and unidirectional)
- Flow control per-connection and per-stream
- HTTP/3 frame handling (HEADERS, DATA, SETTINGS)
- QPACK static table support
- Unified API with Wade routes (same as HTTP/1.1)
Usage
Start QUIC server
wade:start_quic(8443, #{
certfile => "cert.pem",
keyfile => "key.pem"
}).
wade:route(get, "/hello", fun(Req) ->
wade:reply(Req, 200, <<"Hello HTTP/3!">>)
end, []).Dual mode (HTTP/1.1 + HTTP/3)
{ok, #{http := HTTPPid, quic := QUICPid}} =
wade:start_quic(8080, 8443, #{
certfile => "cert.pem",
keyfile => "key.pem"
}).Routes apply to both protocols.
Testing
# Generate test certificate
openssl req -x509 -newkey rsa:2048 -keyout priv/key.pem -out priv/cert.pem -days 365 -nodes -subj '/CN=localhost'
# Test with curl (HTTP/3)
curl --http3-only -k https://localhost:8443/helloInstall
Add to rebar.config:
{deps, [wade]}.