glen

🏕️ A peaceful web framework that targets JS.

Other packages you will need:

Types

A request handler.

Examples

fn my_serve(port: Int, handler: glen.Handler) -> Nil {
  io.println("Starting server...")
  glen.serve(port, handler)
}
pub type Handler =
  fn(Request) -> Promise(Response)

A JavaScript request handler.

pub type JsHandler =
  fn(JsRequest) -> Promise(JsResponse)

A standard JavaScript ReadableStream.

pub type JsReadableStream =
  conversation.JsReadableStream

A standard JavaScript Request.

pub type JsRequest =
  conversation.JsRequest

A standard JavaScript Response.

pub type JsResponse =
  conversation.JsResponse

An incoming request.

pub type Request =
  HttpRequest(RequestBody)

An incoming request’s body.

pub type RequestBody =
  conversation.RequestBody

An outgoing response.

pub type Response =
  HttpResponse(ResponseBody)

An outgoing response’s body.

pub type ResponseBody {
  Text(String)
  File(path: String)
  Bits(BitArray)
  Empty
  Websocket(ws.WebsocketBody)
}

Constructors

  • Text(String)

    A text body.

  • File(path: String)

    A file body. The file will be streamed and not read into memory, so it is okay to send files of any size. If the file cannot be accessed, an empty response with a 500 status code (internal server error) will be returned.

  • Bits(BitArray)

    A BitArray body.

  • Empty

    An empty body, equivalent to Bits(<<>>).

  • Websocket(ws.WebsocketBody)

    A websocket response body.

Constants

pub const path_segments: fn(Request(RequestBody)) -> List(String) = request.path_segments

Return the non-empty segments of a request path.

ℹ️ This function is re-exported from gleam_http.

Examples

case glen.path_segments(req) {
  [] -> index_page()
  ["about"] -> about_page()
  ["greet", name] -> greet_page(name)
  _ -> not_found_page()
}
pub const set_body: fn(Response(ResponseBody), ResponseBody) ->
  Response(ResponseBody) = response.set_body

Set the body of a response.

ℹ️ This function is re-exported from gleam_http.

pub const set_header: fn(Response(ResponseBody), String, String) ->
  Response(ResponseBody) = response.set_header

Set the header with the given value under the given header key.

If the response already has that key, it is replaced.

ℹ️ This function is re-exported from gleam_http.

Functions

pub fn bit_array_body(
  res: Response(ResponseBody),
  bits: BitArray,
) -> Response(ResponseBody)

Set the body of a response to a BitArray.

pub fn convert_request(req: JsRequest) -> Request(RequestBody)

Convert a JavaScript request into a Glen request.

pub fn convert_response(
  res: Response(ResponseBody),
) -> JsResponse

Convert a Glen response into a JavaScript response.

pub fn escape_html(string: String) -> String

Escape a string so it can be included inside of HTML safely. You should run this function on all user input being included in HTML to prevent possible XSS attacks.

pub fn file(path: String, status: Int) -> Response(ResponseBody)

Create a response with a file stream as the body. The content-type header will be automatically set based on the file’s extension.

pub fn file_body(
  res: Response(ResponseBody),
  path: String,
) -> Response(ResponseBody)

Set the body of a response to a file stream. The content-type header will be automatically set based on the file’s extension.

pub fn get_query(
  req: Request(RequestBody),
) -> List(#(String, String))

Get the query parameters from a request. Parameters are not predictably ordered, so you should not pattern match on them. Instead, use the key_find function from gleam/list to access parameters.

pub fn html(html: String, status: Int) -> Response(ResponseBody)

Create a response with an HTML body.

pub fn html_body(
  res: Response(ResponseBody),
  html: String,
) -> Response(ResponseBody)

Set the body of a response to HTML.

pub fn json(json: String, status: Int) -> Response(ResponseBody)

Create a response with a JSON body.

pub fn json_body(
  res: Response(ResponseBody),
  json: String,
) -> Response(ResponseBody)

Set the body of a response to JSON.

pub fn log(
  req: Request(RequestBody),
  next: fn() -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function for logging requests and responses.

Examples

fn handle_req(req) {
  use <- glen.log(req)
  // ...requests and responses are now logged...
}
pub fn method_not_allowed(
  allowed: List(Method),
) -> Response(ResponseBody)

Create a response with a status of 405 (method not allowed). The allowed header will be set to the given allowed methods.

pub fn read_body_bits(
  req: Request(RequestBody),
) -> Promise(Result(BitArray, ReadError))

Read a request body as a BitArray.

pub fn read_form_body(
  req: Request(RequestBody),
) -> Promise(Result(FormData, ReadError))

Read a request body as FormData.

pub fn read_json_body(
  req: Request(RequestBody),
) -> Promise(Result(Dynamic, ReadError))

Read a request body as JSON.

pub fn read_text_body(
  req: Request(RequestBody),
) -> Promise(Result(String, ReadError))

Read a request body as text.

pub fn redirect(
  url: String,
  status: Int,
) -> Response(ResponseBody)

Redirect the client to a URL with the given status. The status should be in the 3xx range (such as 303: See Other or 307: Temporary Redirect).

pub fn require_bit_array_body(
  req: Request(RequestBody),
  next: fn(BitArray) -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function that reads a request body as a BitArray.

Examples

fn handle_req(req) {
  use bits <- glen.require_bit_array_body(req)

  "Look at all the bits! " <> string.inspect(bits)
  |> glen.html(status.ok)
  |> promise.resolve
}
pub fn require_content_type(
  req: Request(RequestBody),
  required: String,
  next: fn() -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function for requiring the request to have a content-type header with a specific content type. Returns the same as unsupported_media_type if the header is missing or does not meet the requirement.

Examples

fn handle_req(req) {
  use <- glen.require_content_type(req, "text/html")
  // ...the request's content-type must be text/html...
}
pub fn require_form(
  req: Request(RequestBody),
  next: fn(FormData) -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware for requiring the request body to be a form with a content-type of either application/x-www-form-urlencoded or multipart/form-data.

Formdata values are sorted alphabetically so they can be pattern matched on.

Examples

fn handle_req(req) {
  use formdata <- glen.require_form(req)

  case formdata.values {
    [#("name", name)] -> greet(name)
    _ -> glen.response(status.bad_request)
  }
  |> promise.resolve
}
pub fn require_json(
  req: Request(RequestBody),
  next: fn(Dynamic) -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function for requiring the request body to be JSON with a content-type of application/json.

Examples

fn handle_req(req) {
  use json <- glen.require_json(req)

  case my_decoder(json) {
    Ok(decoded) -> decoded.foo |> glen.text(status.ok)
    Error(_) -> glen.response(status.bad_request)
  }
  |> promise.resolve
}
pub fn require_method(
  req: Request(RequestBody),
  method: Method,
  next: fn() -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function for requiring the request to be of a certain HTTP method. Returns the same as method_not_allowed if the method does not meet the requirement.

Examples

fn handle_req(req) {
  use <- glen.require_method(req, http.Get)
  // ...only GET requests are allowed...
}
pub fn require_string_body(
  req: Request(RequestBody),
  next: fn(String) -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function that reads a request body as a string.

Examples

fn handle_req(req) {
  use string_body <- glen.require_string_body(req)

  "You gave me: " <> glen.escape_html(string_body)
  |> glen.html(status.ok)
  |> promise.resolve
}
pub fn rescue_crashes(
  handler: fn() -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware function that rescues any crashes with an empty response and a status of 500 (internal server error).

Gleam code should never crash under normal circumstances, but it’s always good to be prepared.

Examples

fn handle_req(req) {
  use <- glen.rescue_crashes
  // ...crashes are now handled gracefully...
}
pub fn response(status: Int) -> Response(ResponseBody)

Create a response with the given status code and an empty body.

pub fn serve(
  port: Int,
  handler: fn(Request(RequestBody)) ->
    Promise(Response(ResponseBody)),
) -> Nil

Start a server using Deno.serve.

ℹ️ Only works when using the deno runtime. See the readme for more info.

Examples

glen.serve(8000, fn(_req) {
  "Hello, world!"
  |> glen.text(status.ok)
  |> promise.resolve
})
pub fn static(
  req: Request(RequestBody),
  prefix: String,
  directory: String,
  next: fn() -> Promise(Response(ResponseBody)),
) -> Promise(Response(ResponseBody))

Middleware for serving up static files from a directory under a path prefix.

Examples

fn handle_req(req) {
  use <- glen.static(req, "static", "./somedir/static")

  "<img src='/static/image.png'/>" |> glen.html(status.ok) |> promise.resolve
}
pub fn text(text: String, status: Int) -> Response(ResponseBody)

Create a response with a text body.

pub fn text_body(
  res: Response(ResponseBody),
  text: String,
) -> Response(ResponseBody)

Set the body of a response to text.

pub fn unsupported_media_type(
  supported: List(String),
) -> Response(ResponseBody)

Create a response with a status of 415 (unsupported media type). The accept header will be set to the given supported content types.

pub fn websocket(
  req: Request(RequestBody),
  on_open on_open: fn(WebsocketConn(a)) -> b,
  on_close on_close: fn(b) -> Nil,
  on_event on_event: fn(WebsocketConn(a), b, WebsocketMessage(a)) ->
    b,
  with_conn do: fn(WebsocketConn(a)) -> Nil,
) -> Promise(Response(ResponseBody))

Upgrade a request to become a websocket. If the request does not have an upgrade header set to websocket, a response of 426 (upgrade required) will be returned.

  • on_open gets called when a client starts a websocket connection.
  • on_close is called when the connection in closed.
  • on_event gets called when the websocket recieves an event or message.

ℹ️ Websockets are currently only supported when using the deno runtime.

Examples

See this for a more detailed example of websockets.

fn handle_req(req) {
  use _conn <- glen.websocket(
    req,
    on_open: on_open,
    on_close: on_close,
    on_event: on_event,
  )
  Nil
}

fn on_open(conn) {
  // ...
}

fn on_close(state) {
  // ...
}

fn on_event(conn, state, msg) {
  // ...
}
Search Document