messua/minc
Messua Incoming.
The Incoming(state) type represents an incoming request bundled
with a handle to the server’s state object.
fn handle(inc: Incoming(Int)) -> Outgoing {
let cur_count = minc.alter_state(inc, fn(n) { n + 1 })
let body =
["Your request is #", int.to_string(cur_count), ".\n"]
|> string.concat()
mout.ok()
|> mout.with_string_body(body)
}
fn main() {
messua.default()
|> messua.with_state(1)
|> messua.start(handle)
}
$ curl http://localhost:8080
Your request is #1.
$ curl http://localhost:8080
Your request is #2.
Types
Values
pub fn get_state(inc: Incoming(state)) -> Result(state, Nil)
Get a handle to the Incoming’s bundled state.
fn handle_get_state(in: Incoming(String)) -> Outgoing {
let assert Ok(state) = minc.get_state(in)
io.println(state)
mout.ok()
}
pub fn main() {
messua.default()
|> messua.with_state("Blue, feathery frog wings.")
|> messua.start(handle_get_state)
}
// Prints "Blue, feathery frog wings." on every request.
pub fn get_then_update_state(
inc: Incoming(state),
with: fn(state) -> state,
) -> Result(state, Nil)
Update the server state with the supplied function, but return the
value it had prior to the update.
This operation is “atomic” in the same sense as update_state().
pub fn into_parts(
inc: Incoming(state),
) -> Result(#(request.Request(mist.Connection), state), Nil)
Decompose an Incoming into a Request and a State.
This is equivalent to calling get_state and req.
pub fn replace_req(
new_req: request.Request(mist.Connection),
old_in: Incoming(state),
) -> Incoming(state)
Replace the Incoming Request with a new one.
fn handle(in: Incoming(state)) -> Outgoing {
let inner = minc.req(in)
case check_auth(in) {
Ok(user) ->
minc.req(in)
|> request.set_header("x-uname", user.uname)
|> minc.replace_req(in)
|> handle_authorized()
Error(_) ->
fail.new()
|> fail.with_error(fail.Unauthorized)
|> Error()
}
}
pub fn req(
inc: Incoming(state),
) -> request.Request(mist.Connection)
Get your grubby hands on the underlying incoming Request.
pub fn set_state(
inc: Incoming(state),
new_state: state,
) -> Incoming(state)
Sets the server state.
This is probably not the function you want to use. Note that, for example,
fn handle(in: Incoming(Int)) -> Outgoing {
let state = minc.get_state(in)
minc.set_state(in, state + 1)
// ...
mout.ok()
}
isn’t necessarily an atomic operation. If this handler is handling multiple requests concurrently, these state updates may step on each others’ toes.
You probably want update_state() instead.
pub fn update_state(
inc: Incoming(state),
with: fn(state) -> state,
) -> Nil
Update the server state with the given function.
This will update “atomically”, that is, this read-change-write compound operation is guaranteed to not overlap with any other read-change-write.
pub fn update_then_get_state(
inc: Incoming(state),
with: fn(state) -> state,
) -> Result(state, Nil)
Update the server state with the supplied function, then return
the new value.
This operation is “atomic” in the same sense as update_state().