Skip to content

OpenFn/weir

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Weir

Hex.pm Docs CI

Streaming HTTP proxy library with O(1) memory body observation for Elixir.

Weir /wɪər/ - A low dam that measures water flow without blocking it.

Features

  • Zero buffering: Stream requests and responses without memory accumulation
  • Body observation: Capture SHA256, size, preview, timing without buffering
  • Plug integration: Use as Plug or call directly from controllers
  • Configurable: Per-request overrides for all settings
  • Observable: Lifecycle callbacks for monitoring and logging

Installation

Add weir to your list of dependencies in mix.exs:

def deps do
  [
    {:weir, "~> 0.1.0"}
  ]
end

Quick Start

  1. Add Finch to your supervision tree:
children = [
  {Finch, name: MyApp.Finch}
]
  1. Configure Weir:
# config/config.exs
config :weir, finch_name: MyApp.Finch
  1. Use in your controller:
def proxy(conn, _params) do
  Weir.proxy(conn, upstream: "https://api.example.com")
end

Or as a Plug in your router:

forward "/api", Weir.ProxyPlug, upstream: "https://api.example.com"

Body Observation

Weir captures observations about request and response bodies without buffering:

conn = Weir.proxy(conn, upstream: "https://api.example.com")

# Access observations from conn.private
req_obs = conn.private[:weir_request_observation]
resp_obs = conn.private[:weir_response_observation]

# Each observation contains:
# - :hash - SHA256 hash of the body
# - :size - Total body size in bytes
# - :preview - First 64KB of the body (UTF-8 safe truncation)
# - :body - Full body (only if under max_payload_size and content-type matches)
# - :duration_us - Processing time in microseconds

Observer Callbacks

Implement Weir.Observer to hook into the proxy lifecycle:

defmodule MyApp.ProxyObserver do
  use Weir.Observer

  @impl true
  def handle_request_started(metadata) do
    Logger.info("Proxying #{metadata.method} #{metadata.upstream_url}")
    :ok
  end

  @impl true
  def handle_response_started(metadata) do
    Logger.info("TTFB: #{metadata.ttfb_ms}ms")
    :ok
  end

  @impl true
  def handle_response_finished(result) do
    Logger.info("Completed: #{result.status} in #{result.duration_us}us")
    # result contains :request_observation and :response_observation
    :ok
  end
end

# Use it:
Weir.proxy(conn,
  upstream: "https://api.example.com",
  observer: MyApp.ProxyObserver
)

Configuration Options

Option Default Description
:finch_name Weir.Finch Name of the Finch pool to use
:receive_timeout 15_000 Response timeout in milliseconds
:max_payload_size 1_048_576 Max body size for full accumulation (1MB)
:persistable_content_types JSON/XML/text Content types eligible for body storage

Override per-request:

Weir.proxy(conn,
  upstream: "https://api.example.com",
  receive_timeout: 60_000,
  max_payload_size: 5_242_880
)

Or set application defaults:

# config/config.exs
config :weir,
  finch_name: MyApp.Finch,
  receive_timeout: 30_000,
  max_payload_size: 5_242_880,
  persistable_content_types: ["application/json", "text/*"]

Documentation

Full documentation: https://hexdocs.pm/weir

License

Apache-2.0

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages