Fist 👊

A declarative, type-safe router for the Mist web server in Gleam, inspired by Axum.

Features

Installation

Add fist to your gleam.toml:

[dependencies]
fist = { path = "../fist" } # Or from Hex when available

Quick Start

1. Define your handlers

With fist, you can return standard Response types using built-in helpers.

import gleam/dict.{type Dict}
import gleam/http/request.{type Request}
import gleam/result
import fist

fn hello_handler(_req: Request(body), params: Dict(String, String)) {
  let name = dict.get(params, "name") |> result.unwrap("stranger")
  fist.ok("Hello, " <> name <> "!")
}

2. Create and transform the router

You can write your business logic using simple Response(String) and then transform it for your web server (like Mist) at the end.

import fist

pub fn main() {
  fist.new()
  |> fist.get("/hello/:name", to: hello_handler)
  |> fist.get("/json", to: fn(_, _) { fist.json("{\"status\": \"ok\"}") })
  // Transform all Response(String) to Response(mist.ResponseData)
  |> fist.map(fist.render_mist)
  |> fist.start(port: 8080)
}

Advanced: Custom Return Types (ADTs)

Because fist is generic over the handler’s output, you can use your own Algebraic Data Types and map them.

pub type MyAnswer {
  Success(String)
  UserFound(User)
  Error(String)
}

fn my_handler(_, _) {
  Success("Operation completed")
}

pub fn start() {
  fist.new()
  |> fist.get("/", to: my_handler)
  |> fist.map(fn(answer) {
    case answer {
      Success(msg) -> fist.ok(msg)
      UserFound(user) -> fist.json(user_to_json(user))
      Error(err) -> fist.text("Error: " <> err) // Adicione .set_status(400) se necessário
    }
  })
  |> fist.map(fist.render_mist)
  |> fist.start(8080)
}

Integration with Mist

The fist.start function provides a convenient way to run your router with Mist. It expects a router where handlers return Response(mist.ResponseData).

import mist
import fist

pub fn main() {
  fist.new()
  |> fist.get("/", to: fn(_req, _params) {
    fist.ok("Hello from Mist!")
  })
  |> fist.map(fist.render_mist)
  |> fist.start(port: 8080)
}
✨ Search Document