async-http-capture 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1daaf4df163cc364474c3fa2317fc470599b93291f172612534c251de4213f7d
4
+ data.tar.gz: eeb94b760ea184040e56a2d334e9eb655864f4275d3e9397ae99f19ca3f237c5
5
+ SHA512:
6
+ metadata.gz: aec6884a20a7bf778d2a420927893c0bb24cbf988554b6a1c23fa8336abe332c37037663060e84e04acf0fdc365d1fa38196d934bcda1e824dabcdf5276c3ab9
7
+ data.tar.gz: b3cdf504d73f9ec34dea3e0faf4db09f813c616fc800b1922149e27687a5c02716b06d051e1a0d2626bb203a814c7cc4f4bc2c917e842357354b9b36ccc11993
@@ -0,0 +1,186 @@
1
+ # Getting Started
2
+
3
+ This guide explains how to get started with `async-http-capture`, a Ruby gem for recording and replaying HTTP requests using Protocol::HTTP.
4
+
5
+ ## Installation
6
+
7
+ Add the gem to your project:
8
+
9
+ ~~~ bash
10
+ $ bundle add async-http-capture
11
+ ~~~
12
+
13
+ ## Core Concepts
14
+
15
+ `async-http-capture` has several core concepts:
16
+
17
+ - A {ruby Async::HTTP::Capture::Middleware} which captures HTTP requests and responses as they pass through your application.
18
+ - An {ruby Async::HTTP::Capture::Interaction} which represents a single HTTP request/response pair with lazy Protocol::HTTP object construction.
19
+ - A {ruby Async::HTTP::Capture::Cassette} which is a collection of interactions that can be loaded from and saved to JSON files.
20
+ - A {ruby Async::HTTP::Capture::CassetteStore} which provides content-addressed storage, saving each interaction to a separate file named by its content hash.
21
+ - A {ruby Async::HTTP::Capture::ConsoleStore} which logs interactions to the console for debugging purposes.
22
+
23
+ ## Usage
24
+
25
+ The basic workflow involves:
26
+
27
+ 1. **Recording**: Capture HTTP interactions using middleware
28
+ 2. **Storage**: Save interactions using pluggable store backends
29
+ 3. **Replay**: Load and replay recorded interactions
30
+
31
+ ### Basic Recording
32
+
33
+ Here's how to record HTTP interactions to files:
34
+
35
+ ~~~ ruby
36
+ require "async/http/capture"
37
+
38
+ # Create a store that saves to content-addressed files:
39
+ store = Async::HTTP::Capture::CassetteStore.new("interactions")
40
+
41
+ # Create your application
42
+ app = ->(request) { Protocol::HTTP::Response[200, {}, ["OK"]] }
43
+
44
+ # Wrap it with recording middleware:
45
+ middleware = Async::HTTP::Capture::Middleware.new(app, store: store)
46
+
47
+ # Make requests - they will be automatically recorded:
48
+ request = Protocol::HTTP::Request["GET", "/users"]
49
+ response = middleware.call(request)
50
+ # This creates a file like interactions/a1b2c3d4e5f67890.json
51
+ ~~~
52
+
53
+ ### Recording with Console Output
54
+
55
+ For debugging, you can log interactions to the console:
56
+
57
+ ~~~ ruby
58
+ # Create a console store for debugging:
59
+ console_store = Async::HTTP::Capture::ConsoleStore.new
60
+ middleware = Async::HTTP::Capture::Middleware.new(app, store: console_store)
61
+
62
+ # This will log interactions to console:
63
+ middleware.call(request)
64
+ # Output: "Recorded: GET /users"
65
+ ~~~
66
+
67
+ ### Loading and Replaying Interactions
68
+
69
+ ~~~ ruby
70
+ # Load recorded interactions:
71
+ cassette = Async::HTTP::Capture::Cassette.load("interactions")
72
+
73
+ # Replay them against your application:
74
+ cassette.each do |interaction|
75
+ request = interaction.request # Lazy Protocol::HTTP::Request construction
76
+ response = app.call(request) # Send to your app
77
+ puts "#{request.method} #{request.path} -> #{response.status}"
78
+ end
79
+ ~~~
80
+
81
+ ## Recording HTTP Requests and Responses
82
+
83
+ By default, only requests are recorded. To capture responses as well:
84
+
85
+ ~~~ ruby
86
+ middleware = Async::HTTP::Capture::Middleware.new(
87
+ app,
88
+ store: store,
89
+ record_response: true
90
+ )
91
+
92
+ response = middleware.call(request)
93
+ # Both request and response are now recorded
94
+ ~~~
95
+
96
+ ## Content-Addressed Storage
97
+
98
+ Each interaction is saved to a file named by its content hash, providing several benefits:
99
+
100
+ ~~~
101
+ interactions/
102
+ ├── a1b2c3d4e5f67890.json # GET /users
103
+ ├── f67890a1b2c3d4e5.json # POST /orders
104
+ └── 1234567890abcdef.json # GET /health
105
+ ~~~
106
+
107
+ Benefits:
108
+ - **Automatic de-duplication**: Identical interactions → same filename
109
+ - **Parallel-safe**: Multiple processes can write without conflicts
110
+ - **Content integrity**: Hash verifies file contents
111
+ - **Git-friendly**: Stable filenames for version control
112
+
113
+ ## Application Warmup
114
+
115
+ A common use case is warming up your application with recorded traffic:
116
+
117
+ ~~~ ruby
118
+ require "async/http/capture"
119
+
120
+ # Step 1: Record requests during development/testing
121
+ endpoint = Async::HTTP::Endpoint.parse("https://api.example.com")
122
+ store = Async::HTTP::Capture::CassetteStore.new("warmup_interactions")
123
+
124
+ recording_middleware = Async::HTTP::Capture::Middleware.new(
125
+ nil,
126
+ store: store
127
+ )
128
+
129
+ client = Async::HTTP::Client.new(endpoint, middleware: [recording_middleware])
130
+
131
+ # Make the requests you want to record
132
+ Async do
133
+ client.get("/health")
134
+ client.get("/api/popular-items")
135
+ client.post("/api/user-sessions", {user_id: 123})
136
+ end
137
+
138
+ # Step 2: Use recorded interactions to warm up your application
139
+ cassette = Async::HTTP::Capture::Cassette.load("warmup_interactions")
140
+ app = MyApplication.new
141
+
142
+ puts "Warming up with #{cassette.interactions.size} recorded interactions..."
143
+ cassette.each do |interaction|
144
+ request = interaction.request
145
+ begin
146
+ app_response = app.call(request)
147
+ puts "Warmed up #{request.method} #{request.path} -> #{app_response.status}"
148
+ rescue => error
149
+ puts "Warning: #{request.method} #{request.path} -> #{error.message}"
150
+ end
151
+ end
152
+
153
+ puts "Warmup complete!"
154
+ ~~~
155
+
156
+ ## Custom Storage Backends
157
+
158
+ You can create custom storage backends by implementing the {ruby Async::HTTP::Capture::Store} interface:
159
+
160
+ ~~~ ruby
161
+ class MyCustomStore
162
+ include Async::HTTP::Capture::Store
163
+
164
+ def call(interaction)
165
+ # Handle the interaction as needed
166
+ # e.g., send to a database, external service, etc.
167
+ puts "Custom handling: #{interaction.request.method} #{interaction.request.path}"
168
+ end
169
+ end
170
+
171
+ # Use your custom store
172
+ custom_store = MyCustomStore.new
173
+ middleware = Async::HTTP::Capture::Middleware.new(app, store: custom_store)
174
+ ~~~
175
+
176
+ ## Key Features
177
+
178
+ - **Pure Protocol::HTTP**: Works directly with Protocol::HTTP objects, no lossy conversions
179
+ - **Content-Addressed Storage**: Each interaction saved as separate JSON file with content hash
180
+ - **Parallel-Safe**: Multiple processes can record simultaneously without conflicts
181
+ - **Flexible Stores**: Pluggable storage backends (files, console logging, etc.)
182
+ - **Complete Headers**: Full round-trip serialization including `fields` and `tail`
183
+ - **Error Handling**: Captures network errors and connection issues
184
+ - **Lazy Construction**: Protocol::HTTP objects are constructed on-demand for memory efficiency
185
+
186
+ This makes `async-http-capture` ideal for testing, debugging, application warmup, and HTTP traffic analysis scenarios.
@@ -0,0 +1,12 @@
1
+ # Automatically generated context index for Utopia::Project guides.
2
+ # Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3
+ ---
4
+ description: A HTTP request and response capture.
5
+ metadata:
6
+ documentation_uri: https://socketry.github.io/async-http-capture/
7
+ source_code_uri: https://github.com/socketry/async-http-capture.git
8
+ files:
9
+ - path: getting-started.md
10
+ title: Getting Started
11
+ description: This guide explains how to get started with `async-http-capture`, a
12
+ Ruby gem for recording and replaying HTTP requests using Protocol::HTTP.