messua/err
An error type made to be converted into an error response.
This allows for streamlined handling of error responses.
import messua/err
import messua/errs
import messua/handle
import messua/ok
import messua/rr.{type MRequest, type MResponse}
import my_mod.{type ServerState}
fn update_record(req: MRequest(ServerState)) -> MResponse {
// If there's no Authorization: header, this returns an `Err` that
// becomes a 400 response.
use auth_key <- handle.require_header(req, "authorization")
// If auth fails, we construct an error response ourselves.
use user_id <- result.try(
case rr.state(req) |> my_mod.verify_auth(auth_key) {
my_mod.AuthFailure -> errs.unauthorized() |> Error()
my_mod.AuthSuccess(user_id) -> Ok(user_id)
}
)
// If there's not a properly-formed request body, this returns an
// `Err` that becomes a 400.
use new_record <- handle.require_json_body(req, my_mod.record_decoder)
// If there's an error in our business logic, we return an `Err`
// that becomes a 500, and add the error message to be logged.
use response_data <- result.try(
rr.state(req)
|> my_mod.update_record(user_id, new_record)
|> result.map_error(fn(msg) { errs.error() |> err.log([msg]) })
)
let body = my_mod.encode_response_data(response_data)
ok.ok()
|> ok.with_json_body(body)
|> Ok()
}
Types
The Error
variant of the MResponse type.
It will be converted to an actual gleam/http.Response
once it’s out
of your handler’s hands. You can optionally give it “log message”
(distinct from the body message and not returned with the
response—intended only for a little visibility of server errors) that
will be logged by the log Layer
from the messua/mware
module.
(Alternatively, of course, you can write your own logging Layer
that
uses these.)
pub type Err {
Err(
status: Int,
headers: List(http.Header),
log_msg: Option(StringBuilder),
body_msg: Option(StringBuilder),
)
}
Constructors
-
Err( status: Int, headers: List(http.Header), log_msg: Option(StringBuilder), body_msg: Option(StringBuilder), )
You shouldn’t need to use this constructor yourself; there are plenty of functions for building these more conveniently.
Arguments
-
status
Response status code. This will probably be in the 4xx or 5xx range. Many of the
messua/handle.require_xxx
functions return 400 errors on failure. -
headers
Any additional headers you want to provide; these are not generally required.
-
log_msg
An optional diagnostic message for the server administrator’s benefit.
-
body_msg
An optional message to send as the body of the response.
-
Functions
pub fn log(e: Err, msg: List(String)) -> Err
Add a log message to the given response.
The message is supplied as a list of strings that will get joined with no intervening content.
pub fn new(status: Int) -> Err
Instantiate a new message with the given status code.
See also messua/errs
for some functions to instantiate
these more mnemonically.
pub fn to_response(
e: Err,
logger: fn(StringBuilder) -> Nil,
) -> Response(ResponseData)
This function is used by the handler harness to convert the Err
to a proper Response
before shooting it back down the pipe.
pub fn with_header(e: Err, name: String, value: String) -> Err
Add the given name: value
header to the error response.
pub fn with_message(e: Err, msg: List(String)) -> Err
Add a body message to the given response.
The message is supplied as a list of strings that will get joined
with no intervening content, but will have a \n
suffixed.