Skip to content

OpenFn/weir

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 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