messua/mout
Instantiating and building Outgoing responses.
Types
The response type used throughout this library.
Outgoing is a Result type, which takes advantage of the “early
return on error” behavior1 of use sugar. The Error(Failure)
variant is turned into an actual HTTP response before being spit
back out into the world.
(This example contains some hypothetical functions and types that we do not define, but the general idea should be clear from context.)
// This wrapper around our database module's `check_auth()` function
// is designed to work with `result.try()`.
fn check_auth(
db_handle: DatabaseHandle,
auth_header: String,
) -> Result(User, Failure) {
case dbase.get_user_from_auth(auth_header) {
Ok(user) -> Ok(user)
Error(dbase.UserNotFound) -> fail.error(fail.Unauthorized) |> Error()
Error(_) -> fail.error(fail.InternalServerError) |> Error()
}
}
fn handle(in: Incoming(DatabaseHandle)) -> Outgoing {
// If the request doesn't have an "authorization" header, this returns a
// 400: Bad Request response with a body noting the required header.
use auth_header <- handle.require_header(in, "authorization")
// If, for some reason, we can't get our hands on the server state, this
// returns a 500: Internal Server Error response.
use db_handle <- handle.require_state(in)
// If `check_auth()` fails, we return the `Error(Failure)` response
// it gives us, otherwise we have our authenticated `User`.
use user <- result.try(check_auth(db_handle, auth_header))
// If we can't decode request data from the body (because it's invalid
// or missing), we return a 400: Bad Request response.
use request_data <- handle.require_json_body(
in,
1024 * 1024,
request_data_decoder(),
)
// If our actual processing of the request fails, we return a
// 500: Internal Server Error response here, otherwise we have
// the data for our response.
use result_data <- result.try(
dbase.do_business_logic(db_handle, user, request_data)
|> result.replace_error(fail.new()),
)
let result_json = result_data_to_json(result_data)
// And we return our response data in a 200: Ok response.
mout.ok()
|> mout.with_json_body(result_json)
}
pub type Outgoing =
Result(response.Response(mist.ResponseData), fail.Failure)
Values
pub fn fail() -> Result(
response.Response(mist.ResponseData),
fail.Failure,
)
A new Outgoing response that will translate to an otherwise-empty
500: Internal Server Error response.
pub fn from_response(
resp: response.Response(mist.ResponseData),
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Easily turn your hand-tweaked response.Response into an Outgoing.
pub fn into_response(
out: Result(response.Response(mist.ResponseData), fail.Failure),
) -> response.Response(mist.ResponseData)
Convert an Outgoing into a response.Response from the
gleam_http
package.
pub fn ok() -> Result(
response.Response(mist.ResponseData),
fail.Failure,
)
A new Outgoing 200: OK response with no other information.
pub fn raw_response(
status: Int,
) -> response.Response(mist.ResponseData)
Generate a raw response.Response type from the
gleam_http library with
the given status, if you need to manipulate it in a way this library
doesn’t provide.
pub fn serve_dir(
dir: String,
subsegments: List(String),
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Serve a file from dir (or one of its subdirectories) by appending
the list of subsegments to get a path.
This otherwise has the same semantics as serve_file().
serve_file("/home/server/content", ["images", "blue_frog.jpg"])
will return the file at /home/server/content/images/blue_frog.jpg,
or 404 trying.
pub fn serve_file(
path: String,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Return the file at the given path on the server’s local filesystem
as the body of a request.
This will attempt to guess the content-type based on the file extension
(using marceau, and you can always
set it manually), and will return a 404: Not Found if there’s any
problem accessing the given path.
pub fn with_body(
out: Result(response.Response(mist.ResponseData), fail.Failure),
body: BitArray,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Add a body to the response. The “content-length” should get set correctly, but you should set the “content-type” header.
pub fn with_header(
out: Result(response.Response(mist.ResponseData), fail.Failure),
name: String,
value: String,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Add the given header to the Outgoing response.
pub fn with_json_body(
out: Result(response.Response(mist.ResponseData), fail.Failure),
body: json.Json,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Add the given encoded JSON as a body. The “content-length” and
“content-type” (application/json) should get set correctly.
pub fn with_status(
out: Result(response.Response(mist.ResponseData), fail.Failure),
status: Int,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Set the status of the response.
pub fn with_string_body(
out: Result(response.Response(mist.ResponseData), fail.Failure),
body: String,
) -> Result(response.Response(mist.ResponseData), fail.Failure)
Add a body to the response. The “content-length” and “content-type”
(text/plain) should get set correctly.