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:


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

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/hello

Install

Add to rebar.config:

{deps, [wade]}.