Skip to content

Response Body Compression #102

Open
Open
@ofekd

Description

To reduce request size, often the body is compressed. A mechanism that supports this is currently missing from Wisp.

I am not quite sure what scope of a solution is a good fit for Wisp. A full flow will be:

  1. Detect compressions supported by the browser using the accept-encoding header
  2. Compress non-binary bodies
  3. Set the content-encoding header to indicate the compression for responses compressed on the fly
  4. Allow setting the header for static files that are pre-compressed

Steps 1 through 3 are fairly straightforward to do on top of wisp:

  let accept_encoding =
    req.headers
    |> list.find_map(fn(header) {
      case header.0 == "accept-encoding" {
        True -> Ok(header.1)
        False -> Error(Nil)
      }
    })
    |> result.unwrap("")
    |> string.split(",")
    |> list.map(string.trim)

  let deflate_accepted = accept_encoding |> list.contains("deflate")

  case res.body, deflate_accepted {
    wisp.Text(body), True ->
      res
      |> wisp.set_header("content-encoding", "deflate")
      |> wisp.set_body(
        body
        |> string_builder.to_string
        |> bit_array.from_string
        |> gzlib.compress
        |> bytes_builder.from_bit_array
        |> wisp.Bytes,
      )
    _, _ -> res
  }

But there's no clear way to achieve step 4

My current work around is to hard-code the file names:

  let res =
    wisp.serve_static(
      req,
      under: "/priv/static",
      from: client_priv_static,
      next: fun,
    )

  let compressed_statics = [ "script.mjs" ]

  case compressed_statics |> list.any(string.contains(req.path, _)) {
    True -> res |> wisp.set_header("content-encoding", "gzip")
    False -> res
  }

But even beyond the hard-coding of file name, this checks every response

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions