README.md

# messua

A collection of convenience types and functions that might amount to a
small web framework sitting atop [mist](https://hexdocs.pm/mist/).

[![Package Version](https://img.shields.io/hexpm/v/messua)](https://hex.pm/packages/messua)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/messua/)

_Messua_ is a [genus of spider](https://en.wikipedia.org/wiki/Messua_(spider)),
which apparently was itself named after
[a character from _The Jungle Book_](https://en.wikipedia.org/wiki/List_of_The_Jungle_Book_characters#Messua).
Please do not take this as any sort of endorsement of any orientalist or
colonialist themes that may appear in Kipling's work; I just wanted a
name vaguely related to webs that probably wouldn't already be taken.

## Introduction

When a piece of technology focuses on a particular solution or style in
the face of many alternatives, it is in fashion these days to refer to that
piece of technology as being "opinionated", particularly when describing
a programming language, framework, or library. I wouldn't say that Messua
is _opinionated_ so much as I'd say it _sees the point_ of doing things a
certain way, and is willing to give that a go. It is based largely on a
couple of convenient patterns I have found myself using when implementing
backends in Rust and Gleam:

1. A common `Result(Response, Error)` type returned by handlers, for which
   the `Error` variant gets automatically converted to a response.
2. A common `Request` type (injected[^injected] with some server state),
   passed "down" through layers of middleware, with the aforementioned
   `Result` type bubbling back up.
3. Functions that couple this `Result` type with Gleam's `use` sugar to
   mimic early returns of `Error` variants that then get handled with a
   minimum of ceremony, permitting focus on business logic and an
   uncluttered happy path.

[^injected]: I use the term "injected", but really it's more like,
             "bundled with". Under the hood, the `MRequest` is just a
             wrapper that holds the underlying request (the `gleam_http`
             type) and your state.

This library owes a lot to a couple of Rust crates: the
[`axum`](https://docs.rs/axum/latest/axum/) web server, and the
[`tower`](https://docs.rs/tower/latest/tower/index.html) middleware crate,
particularly its
[`Layer`](https://docs.rs/tower/latest/tower/trait.Layer.html) trait.
You might even call this package a sort of cozily-sized Gleam version of
some of the `axum`/`tower` ecosystem.

## Approach

Messua provides a sort of `mist` harness into which it hooks your handler
function (and any `Layer`s you might have on top of it). It provides your
stack with an `MRequest` and expects it to return an `MResponse` (which is
just an alias for a `Result` whose `Ok` variant is a
`gleam/http/response.Response`, and whose `Error` variant is `messua/err.Err`,
which gets turned into an actual HTTP response by the harness). It then
provides you with a slew of convenience functions for extracting parts of
requests, routing, and generating responses.

Messua also provides wrappers around some key things from `mist` and
`gleam_http`; the idea here is that it's easier and more convenient to
import and use a single package, rather than having to mess around in the
guts of three separate packages, wondering which one has the functionality
you want.

## Examples

There is a growing list of examples in the
[examples directory](https://codeberg.org/d2718/messua/src/branch/main/examples);
here's the simplest one:

```gleam
import messua
import messua/ok
import messua/rr.{type MRequest, type MResponse}

fn handler(_req: MRequest(Nil)) -> MResponse {
  ok.ok()
  |> ok.with_text_body("Hello, World!\n")
  |> Ok()
}

pub fn main() {
  messua.default()
  |> messua.with_binding("localhost")
  |> messua.with_http(8080)
  |> messua.start(handler)
}
```

A `gleam run` should be all you need to get the server started; then you can
query it and get a response:

```text
~/ $ curl localhost:8080
Hello, World!
```