messua/rr
Requests and Responses.
Types
Naturally, a function that accepts an MRequest
and returns an
MResponse
is considered a request Handler
.
pub type Handler(state) =
fn(MRequest(state)) -> MResponse
A Layer
is a Handler
with another “inner” Handler
it can optionally
pass an incoming request through. This inner handler may itself be
another layer; it is possible to form stacks arbitrarily deep this way
(see the Stack
example).
(The inspiration for this particular type is the
tower-layer
Rust
crate.)
Examples
A layer that logs requests to stdout might look like this:
import gleam/int
import gleam/io
import gleam/string_builder
import gleam/http
fn handler(req: MRequest(State)) -> MResponse {
// ...Routing and handling goes here.
}
fn log_layer(req: MRequest(State), next: Handler(State)) -> MResponse {
// Get source, method, path from request.
let source = case info(req) {
Ok(info) -> string_builder.from_strings([
string.inspect(info.ip_address), ":", int.to_string(info.port)
])
Error(_) -> string_builder.from_string("[ source ??? ]")
}
let inner_req = inner(req)
let url = string_builder.from_strings([
string.inspect(inner_req.method),
" ",
string.inspect(inner_req.path)
])
// Call inner handling function, get response.
let mresp = next(req)
// Note response status.
let result_msg = case mresp {
Ok(resp) -> string_builder.from_string(int.to_string(resp.status))
Err(e) -> string_builder.from_string(int.to_string(e.status))
}
// Print a request log entry with the source, method, path fo the
// request and the status code of the associated response.
string_builder.append(source, " ")
|> string_builder.append_builder(url)
|> string_builder.append(" ")
|> string_builder.append(result_msg)
|> string_builder.to_string()
|> io.println()
// Return the response.
mresp
}
messua.default()
|> messua.start(log_layer(_, handler))
pub type Layer(state) =
fn(MRequest(state), Handler(state)) -> MResponse
A request with some user-defined server state.
The type parameter is the type of the state object that gets injected into (or bundled with) each incoming request.
pub opaque type MRequest(state)
Functions
pub fn info(req: MRequest(a)) -> Result(ConnectionInfo, Nil)
Get the underlying connection’s
mist.ConnectionInfo
.
Consider handle.get_client()
or
handle.require_client()
for something
in this namespace that returns equivalent information.
pub fn inner(req: MRequest(a)) -> Request(Connection)
Access the underlying
gleam/http/request.Request
.
pub fn make_mist_handler(
state: a,
handle: fn(MRequest(a)) -> Result(Response(ResponseData), Err),
) -> fn(Request(Connection)) -> Response(ResponseData)
messau.start()
uses this internally. You don’t
need to use it, but Gleam’s visibility rules aren’t granular enough
to hide it fron you.
pub fn stack(
base: fn(MRequest(a)) -> Result(Response(ResponseData), Err),
layers: List(
fn(
MRequest(a),
fn(MRequest(a)) -> Result(Response(ResponseData), Err),
) -> Result(Response(ResponseData), Err),
),
) -> fn(MRequest(a)) -> Result(Response(ResponseData), Err)
Compose a stack of nested Layer
s into a Handler
that can be
passed to messua.start()
.
The front of the list is the “bottom” of the stack; the end of the list is the top.
Examples
See the Stack example in the repository for an expository example.