plume

Package Version Downloads Hex Docs Test License

Sensible HTTP security headers for Gleam web servers, inspired by helmet.

Built on gleam_http, so it works with wisp, mist, or any other compatible server (examples below).

Install

gleam add plume@1

Usage

As use middleware:

import gleam/http/response.{type Response}
import plume

pub fn handler() -> Response(String) {
  use <- plume.middleware(plume.default())
  response.new(200)
}

Or directly on a response:

import gleam/http/response.{type Response}
import plume

pub fn handler() -> Response(String) {
  response.new(200) |> plume.set_headers(plume.default())
}

plume.default() ships a starter CSP, nosniff, SameOrigin frame options, HSTS for one year including subdomains, and other widely-recommended values. Override with record-update syntax — Some(value) to set the header, None to leave it unset — or start from plume.new() to opt in header-by-header:

import gleam/option.{None, Some}
import plume
import plume/frame_options

pub fn config() -> plume.Config {
  plume.Config(
    ..plume.default(),
    frame_options: Some(frame_options.Deny),
    referrer_policy: None,
  )
}

Each header lives in its own submodule (e.g. plume/content_security_policy, plume/strict_transport_security) with typed variants for every directive. Further documentation can be found at https://hexdocs.pm/plume.

Integrations

With Wisp

import plume
import wisp.{type Request, type Response}

pub fn handle_request(_req: Request) -> Response {
  use <- plume.middleware(plume.default())
  wisp.ok()
}

With Mist

import gleam/bytes_tree
import gleam/erlang/process
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
import mist.{type Connection, type ResponseData}
import plume

pub fn handle_request(_req: Request(Connection)) -> Response(ResponseData) {
  use <- plume.middleware(plume.default())
  response.new(200)
  |> response.set_body(mist.Bytes(bytes_tree.from_string("Hello!")))
}

pub fn main() {
  let assert Ok(_) =
    handle_request
    |> mist.new
    |> mist.port(8000)
    |> mist.start

  process.sleep_forever()
}

Development

gleam build  # Compile the project
gleam test   # Run the tests
Search Document