No release in over 3 years
A HTTP request and response capture.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

>= 0.53.0
~> 0.90
 Project Readme

Async::HTTP::Capture

A Ruby gem for recording and replaying HTTP requests using Protocol::HTTP. Features timestamped storage, parallel-safe recording, and flexible store backends.

Development Status

Features

  • Pure Protocol::HTTP: Works directly with Protocol::HTTP objects, no lossy conversions
  • Timestamped Storage: Each interaction saved as separate JSON file with timestamp
  • Parallel-Safe: Multiple processes can record simultaneously without conflicts
  • Flexible Stores: Pluggable storage backends (files, console logging, etc.)
  • Complete Headers: Full round-trip serialization including fields and tail
  • Error Handling: Captures network errors and connection issues

Usage

Please see the project documentation for more details.

  • Getting Started - This guide explains how to get started with async-http-capture, a Ruby gem for recording and replaying HTTP requests using Protocol::HTTP.

  • Falcon Integration - This guide explains how to integrate async-http-capture with Falcon web server for recording and replaying HTTP interactions.

Basic Recording to Files

require "async/http/capture"

# Create a store that saves to timestamped files:
store = Async::HTTP::Capture::CassetteStore.new("interactions")

# Create middleware:
app = ->(request) { Protocol::HTTP::Response[200, {}, ["OK"]] }
middleware = Async::HTTP::Capture::Middleware.new(app, store: store)

# Record interactions:
request = Protocol::HTTP::Request["GET", "/users"]
response = middleware.call(request)

Recording to Console Log

# Create a console store for debugging:
console_store = Async::HTTP::Capture::ConsoleStore.new
middleware = Async::HTTP::Capture::Middleware.new(app, store: console_store)

# This will log interactions to console:
middleware.call(request)
# Output: "Recorded: GET /users"

Loading and Replaying

# Load recorded interactions:
cassette = Async::HTTP::Capture::Cassette.load("interactions")

# Replay them:
cassette.each do |interaction|
  request = interaction.request  # Lazy construction
  response = app.call(request)   # Send to your app
end

Recording with Responses

# Record both requests and responses:
middleware = Async::HTTP::Capture::Middleware.new(
  app, 
  store: store,
  record_response: true
)

response = middleware.call(request)
# Both request and response are now recorded

Architecture

Middleware -> Store.call(interaction) -> [CassetteStore | ConsoleStore | ...]
  • Middleware: Pure capture logic, creates Interaction objects with Protocol::HTTP data
  • Store Interface: Generic call(interaction) method for pluggable backends
  • Stores: Handle serialization, filtering, persistence, or logging
  • Interaction: Simple data container with lazy Protocol::HTTP object construction

Timestamped Storage

Each interaction is saved to a file named with timestamp, process ID, and object ID:

recordings/
├── 20250821-105406-271633-12345-67890.json  # GET /users
├── 20250821-105006-257022-12346-67891.json  # POST /orders
└── 20250820-101234-567890-12347-67892.json  # GET /health

Benefits:

  • Chronological ordering: Files sorted by timestamp
  • Parallel-safe: Multiple processes can write without conflicts
  • Human-readable: Timestamps are easy to understand

Store Implementations

CassetteStore

Saves interactions to timestamped JSON files in a directory.

ConsoleStore

Logs interactions via the Console gem with different levels based on success/failure.

Custom Stores

Implement the Store interface:

class MyStore
  include Async::HTTP::Capture::Store
  
  def call(interaction)
    # Handle the interaction as needed
  end
end

Testing

bundle exec sus

The gem includes comprehensive tests using the Sus testing framework with 41 tests and 101 assertions.