HTTPower (HTTPower v0.16.0)
View SourceA production-ready HTTP client library for Elixir that adds reliability patterns and enterprise features on top of existing HTTP clients through an adapter system.
HTTPower supports multiple HTTP clients via adapters — Finch (high-performance, default), Req (batteries-included), and Tesla (bring-your-own-config) — while providing production reliability features that work consistently across all of them:
- Adapter pattern: Choose between Finch, Req, or Tesla HTTP clients
- Middleware pipeline: Rate limiting, circuit breaker, and request deduplication
- Smart retries: Exponential backoff with jitter and Retry-After header support
- PCI-compliant logging: Automatic sanitization of sensitive data with structured metadata
- Telemetry integration: Comprehensive observability for all operations
- Configuration profiles: Pre-built profiles for payment processing, high-volume APIs, and microservices
- Clean error handling: Never raises exceptions, always returns
{:ok, response}or{:error, reason} - Test utilities: Adapter-agnostic test helpers via
HTTPower.Test
Basic Usage
# Simple GET request
HTTPower.get("https://api.example.com/users")
# POST with data
HTTPower.post("https://api.example.com/users",
body: "name=John&email=john@example.com",
headers: %{"Content-Type" => "application/x-www-form-urlencoded"}
)
# With configuration options
HTTPower.get("https://api.example.com/slow-endpoint",
timeout: 30,
max_retries: 5,
retry_safe: true
)Test Mode
HTTPower can block real HTTP requests during testing while allowing mocked requests:
# In test configuration
Application.put_env(:httpower, :test_mode, true)
# This will be blocked
HTTPower.get("https://real-api.com") # {:error, %HTTPower.Error{reason: :network_blocked}}
# But this will work with Req.Test
HTTPower.get("https://api.com", plug: {Req.Test, MyApp})Configuration Options
timeout- Request timeout in seconds (default: 60)max_retries- Maximum retry attempts (default: 3)retry_safe- Enable retries for connection resets (default: false)ssl_verify- Enable SSL verification (default: true)proxy- Proxy configuration (default: :system)headers- Request headers map
Return Values
All HTTP methods return either:
{:ok, %HTTPower.Response{}}on success{:error, %HTTPower.Error{}}on failure
HTTPower never raises exceptions for network errors, ensuring your application stays stable even when external services fail.
Configured Clients
You can create pre-configured client instances for reuse:
# Create a configured client
client = HTTPower.new(
base_url: "https://api.example.com",
headers: %{"Authorization" => "Bearer token"},
timeout: 30,
max_retries: 5
)
# Use the client for multiple requests
HTTPower.get(client, "/users")
HTTPower.post(client, "/users", body: %{name: "John"})This is especially useful for API clients, different environments, or service-specific configuration.
Summary
Functions
Makes an HTTP DELETE request.
Makes an HTTP GET request.
Makes an HTTP HEAD request.
Creates a new HTTPower client with pre-configured options.
Makes an HTTP OPTIONS request.
Makes an HTTP PATCH request.
Makes an HTTP POST request.
Makes an HTTP PUT request.
Checks if HTTPower is currently in test mode.
Types
Functions
@spec delete( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec delete(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP DELETE request.
Accepts either a URL string or a configured client as the first argument.
Options
See module documentation for available options.
Examples
# With URL string
HTTPower.delete("https://api.example.com/users/1")
# With configured client
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.delete(client, "/users/1")
@spec delete(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec get( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec get(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP GET request.
Accepts either a URL string or a configured client as the first argument.
Options
See module documentation for available options.
Examples
# With URL string
HTTPower.get("https://api.example.com/users")
HTTPower.get("https://api.example.com/users", headers: %{"Authorization" => "Bearer token"})
# With configured client
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.get(client, "/users")
@spec get(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec head( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec head(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP HEAD request.
Accepts either a URL string or a configured client as the first argument.
Examples
HTTPower.head("https://api.example.com/users")
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.head(client, "/users")
@spec head(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Creates a new HTTPower client with pre-configured options.
Options
base_url- Base URL to prepend to all requestsprofile- Pre-configured profile (:payment_processing,:high_volume_api,:microservices_mesh)- All other options are the same as individual request options (see module documentation)
When using a profile, profile settings are merged with explicit options. Explicit options always take precedence over profile defaults.
Examples
# Simple client with base URL
client = HTTPower.new(base_url: "https://api.example.com")
# Client with authentication and timeouts
client = HTTPower.new(
base_url: "https://api.example.com",
headers: %{"Authorization" => "Bearer token"},
timeout: 30,
max_retries: 5,
retry_safe: true
)
# Use a profile for optimal settings
client = HTTPower.new(
base_url: "https://payment-gateway.com",
profile: :payment_processing
)
# Profile with overrides
client = HTTPower.new(
base_url: "https://api.example.com",
profile: :high_volume_api,
rate_limit: [requests: 2000] # Override profile's rate limit
)
@spec options( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec options(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP OPTIONS request.
Accepts either a URL string or a configured client as the first argument.
Examples
HTTPower.options("https://api.example.com/users")
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.options(client, "/users")
@spec options(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec patch( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec patch(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP PATCH request.
Accepts either a URL string or a configured client as the first argument.
Examples
HTTPower.patch("https://api.example.com/users/1", body: "name=Jane")
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.patch(client, "/users/1", body: %{name: "Jane"})
@spec patch(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec post( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec post(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP POST request.
Accepts either a URL string or a configured client as the first argument.
Options
See module documentation for available options. Additionally supports:
body- Request body (string or form data)
Examples
# With URL string
HTTPower.post("https://api.example.com/users", body: "name=John")
HTTPower.post("https://api.example.com/users",
body: Jason.encode!(%{name: "John"}),
headers: %{"Content-Type" => "application/json"}
)
# With configured client
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.post(client, "/users", body: %{name: "John"})
@spec post(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec put( String.t(), keyword() ) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec put(client(), String.t()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
Makes an HTTP PUT request.
Accepts either a URL string or a configured client as the first argument.
Options
See module documentation for available options. Additionally supports:
body- Request body (string or form data)
Examples
# With URL string
HTTPower.put("https://api.example.com/users/1", body: "name=John")
# With configured client
client = HTTPower.new(base_url: "https://api.example.com")
HTTPower.put(client, "/users/1", body: %{name: "John"})
@spec put(client(), String.t(), keyword()) :: {:ok, HTTPower.Response.t()} | {:error, HTTPower.Error.t()}
@spec test_mode?() :: boolean()
Checks if HTTPower is currently in test mode.
In test mode, real HTTP requests are blocked unless they include a :plug option
for mocking with Req.Test.
Examples
Application.put_env(:httpower, :test_mode, true)
HTTPower.test_mode?() # true
Application.put_env(:httpower, :test_mode, false)
HTTPower.test_mode?() # false