Req.Decompress (req v0.8.0-rc.0)

Copy Markdown View Source

Asks the server to return compressed response.

The response body is decompressed based on the content-encoding response header. This step is off by default; set compressed: true to opt in.

Supported formats:

FormatDecoder
gzip, x-gzip:zlib
br:brotli (if :brotli is installed)
zstd:zstd (requires Erlang/OTP 28+)
otherReturns data as is

This step updates the following headers to reflect the changes:

  • content-encoding is removed
  • content-length is removed

Only enable compression for trusted servers

This step decompresses the whole response body into memory with no size limit, so a small response can expand into many gigabytes. A malicious or compromised server can exploit this to exhaust memory and crash the client (a decompression bomb / denial of service). For this reason compression is off by default; only set compressed: true for endpoints you trust.

Request Options

  • :compressed - if set to true, sets the accept-encoding header with compression algorithms that Req supports and decompresses the response body. Defaults to false.

  • :raw - if set to true, disables response body decompression. Defaults to false.

    Note: setting raw: true also disables response body decoding.

Examples

By default, Req does not ask for a compressed response. Pass compressed: true to request one and have Req decompress the body, so we get back the decompressed content:

iex> response = Req.get!("https://elixir-lang.org", compressed: true)
iex> response.body |> binary_part(0, 15)
"<!DOCTYPE html>"

To inspect the raw compressed bytes the server sent, additionally pass raw: true, which disables decompression. Notice the body now starts with <<31, 139>>, the "magic bytes" for gzip:

iex> response = Req.get!("https://elixir-lang.org", compressed: true, raw: true)
iex> Req.Response.get_header(response, "content-encoding")
["gzip"]
iex> response.body |> binary_part(0, 2)
<<31, 139>>

Zstandard is supported out of the box on Erlang/OTP 28+ (via the built-in :zstd module). Brotli is supported if the optional :brotli package is installed:

Mix.install([
  :req,
  {:brotli, "~> 0.3.0"}
])

response = Req.get!("https://httpbingo.org/anything", compressed: true)
response.body["headers"]["Accept-Encoding"]
#=> ["zstd, br, gzip"]