wisp_roadrunner
Run Wisp apps on Roadrunner, the pure-Erlang HTTP/1.1, HTTP/2, HTTP/3 and WebSocket server, through roadrunner_gleam.
Requirements
Requires OTP 27+ and Gleam 1.19+, with rebar3 installed to build
Roadrunner.
🚧 Status
wisp_roadrunner is in 0.x. The core is functional and covered by tests,
but the API may change between minor versions. Pin an exact version in your
deps if you need stability across upgrades.
Installation
gleam add wisp_roadrunner roadrunner_gleam
Usage
Swap wisp_mist for wisp_roadrunner and start a roadrunner_gleam
listener; the Wisp app stays the same.
import gleam/erlang/process
import roadrunner_gleam
import wisp
import wisp_roadrunner
pub fn main() {
let secret_key_base = wisp.random_string(64)
let assert Ok(_) =
wisp_roadrunner.handler(handle_request, secret_key_base)
|> roadrunner_gleam.new
|> roadrunner_gleam.read_body_on_demand
|> roadrunner_gleam.port(8000)
|> roadrunner_gleam.start
process.sleep_forever()
}
fn handle_request(_request: wisp.Request) -> wisp.Response {
wisp.ok() |> wisp.string_body("hello, roadrunner!")
}
read_body_on_demand lets Wisp read request bodies in pieces, as it asks
for them, so its body size limits hold before a large upload is read. TLS,
HTTP/2, HTTP/3 and the other listener options come from roadrunner_gleam.
What works
- Wisp handlers on HTTP/1.1, HTTP/2 and HTTP/3
- Request bodies read in pieces of Wisp’s
read_chunk_size, with itsmax_body_sizeandmax_files_sizelimits - Forms, multipart uploads, and Wisp’s temporary files deleted after each request
- Text, bytes and file responses, file ranges included, sent by the kernel
- Signed and encrypted cookies, and
serve_static
Sponsors
wisp_roadrunner is open source and maintained on personal time. If you or your company find it useful, consider sponsoring.
I also accept coffees ☕
License
Copyright (c) 2026 William Fank Thomé
wisp_roadrunner is open-source under the Apache 2.0 License on GitHub.
See LICENSE.md for more information.
