HTTP request recording and replay system for API testing
npx @tessl/cli install tessl/npm-replay@2.4.00
# Replay
1
2
Replay is a comprehensive HTTP request recording and replay system designed for API testing. It allows developers to capture HTTP responses during initial test runs and replay them in subsequent runs without making actual network requests, creating deterministic, fast-running test suites.
3
4
## Package Information
5
6
- **Package Name**: replay
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install replay`
10
11
## Core Imports
12
13
```javascript
14
const Replay = require('replay');
15
```
16
17
The package exports a single **Replay** instance that provides all functionality.
18
19
## Basic Usage
20
21
```javascript
22
const Replay = require('replay');
23
24
// Set mode to record new responses
25
Replay.mode = 'record';
26
27
// Configure fixtures directory
28
Replay.fixtures = __dirname + '/fixtures';
29
30
// Make HTTP requests - they will be recorded automatically
31
const http = require('http');
32
http.get('http://api.example.com/data', (response) => {
33
// Response will be saved for future replay
34
});
35
36
// Later, in test mode (default)
37
Replay.mode = 'replay'; // Only replay captured responses
38
```
39
40
## Architecture
41
42
Replay is built around several key components:
43
44
- **Mode System**: Four operational modes (replay, record, cheat, bloody) controlling request behavior
45
- **Proxy Chain**: Pluggable request processing pipeline with built-in handlers
46
- **Host Management**: Flexible routing for localhost, pass-through, and dropped hosts
47
- **Catalog System**: Manages fixture storage and retrieval on disk
48
- **Module Patching**: Automatic interception of Node.js HTTP/HTTPS/DNS modules
49
50
## Capabilities
51
52
### Mode Management
53
54
Controls how Replay handles HTTP requests with four distinct operational modes.
55
56
```javascript { .api }
57
// Mode property
58
Replay.mode: string; // 'replay' | 'record' | 'cheat' | 'bloody'
59
```
60
61
[Mode Management](./mode-management.md)
62
63
### Host Configuration
64
65
Flexible host routing system for localhost redirection, pass-through, and connection dropping.
66
67
```javascript { .api }
68
// Host configuration methods
69
Replay.localhost(...hosts: string[]): Replay;
70
Replay.passThrough(...hosts: string[]): Replay;
71
Replay.drop(...hosts: string[]): Replay;
72
Replay.reset(...hosts: string[]): Replay;
73
74
// Host checking methods
75
Replay.isLocalhost(host: string): boolean;
76
Replay.isPassThrough(host: string): boolean;
77
Replay.isDropped(host: string): boolean;
78
```
79
80
[Host Configuration](./host-configuration.md)
81
82
### Fixture Management
83
84
Recording and storage configuration for HTTP response fixtures.
85
86
```javascript { .api }
87
// Fixture configuration
88
Replay.fixtures: string; // Directory path
89
Replay.headers: RegExp[]; // Headers to record/match
90
91
// Catalog access (internal fixture management)
92
Replay.catalog: Catalog;
93
```
94
95
[Fixture Management](./fixture-management.md)
96
97
### Proxy System
98
99
Extensible proxy chain system for custom request processing.
100
101
```javascript { .api }
102
// Proxy chain methods
103
Replay.use(proxy: (request: any, callback: Function) => void): Replay;
104
105
// Built-in proxies
106
Replay.logger(): Function;
107
108
// Chain access (internal proxy chain management)
109
Replay.chain: Chain;
110
```
111
112
[Proxy System](./proxy-system.md)
113
114
## Environment Variables
115
116
```javascript { .api }
117
// Environment variable configuration
118
process.env.REPLAY: 'replay' | 'record' | 'cheat' | 'bloody';
119
process.env.DEBUG: 'replay'; // Enable debug logging
120
```
121
122
## Event Handling
123
124
Replay extends EventEmitter for error handling:
125
126
```javascript { .api }
127
// Event handling
128
Replay.on(event: 'error', listener: (error: Error) => void): Replay;
129
```
130
131
**Usage Examples:**
132
133
```javascript
134
const Replay = require('replay');
135
136
// Handle errors from the replay system
137
Replay.on('error', (error) => {
138
console.error('Replay error:', error.message);
139
140
// Common error types:
141
if (error.code === 'ECONNREFUSED') {
142
console.log('Request blocked - no fixture found and not in record mode');
143
} else if (error.code === 'CORRUPT FIXTURE') {
144
console.log('Fixture file is corrupted or malformed');
145
}
146
});
147
```
148
149
## Error Conditions
150
151
Common error scenarios and their handling:
152
153
```javascript { .api }
154
// Connection refused - no fixture available in replay mode
155
class ReplayConnectionRefusedError extends Error {
156
code: 'ECONNREFUSED';
157
syscall: 'connect';
158
message: 'Connection to {url} refused: not recording and no network access';
159
}
160
161
// Corrupt fixture file
162
class ReplayCorruptFixtureError extends Error {
163
code: 'CORRUPT FIXTURE';
164
syscall: 'connect';
165
message: string;
166
}
167
168
// Unsupported mode
169
class ReplayUnsupportedModeError extends Error {
170
message: 'Unsupported mode \'{mode}\', must be one of bloody, cheat, record, replay.';
171
}
172
```
173
174
## Types
175
176
```javascript { .api }
177
// Operational modes
178
type ReplayMode = 'replay' | 'record' | 'cheat' | 'bloody';
179
180
// Proxy handler function
181
type ProxyHandler = (request: ReplayRequest, callback: (error?: Error, response?: ReplayResponse) => void) => void;
182
183
// Response control function
184
type ResponseControlFunction = (request: ReplayRequest, response: ReplayResponse) => boolean;
185
186
// Host pattern (supports wildcards)
187
type HostPattern = string; // e.g., 'api.example.com', '*.example.com', 'api.*'
188
189
// Request object structure
190
interface ReplayRequest {
191
url: URL;
192
method: string;
193
headers: { [key: string]: string | string[] };
194
body?: Array<[Buffer | string, string]>;
195
trailers?: { [key: string]: string | string[] };
196
}
197
198
// Response object structure
199
interface ReplayResponse {
200
version: string;
201
statusCode: number;
202
statusMessage: string;
203
rawHeaders: string[];
204
headers: { [key: string]: string | string[] };
205
body: Array<[Buffer | string, string]>;
206
trailers?: { [key: string]: string | string[] };
207
rawTrailers?: string[];
208
}
209
210
// Catalog class for fixture management
211
interface Catalog {
212
find(host: string): Matcher[] | null;
213
save(host: string, request: ReplayRequest, response: ReplayResponse, callback: (error?: Error) => void): void;
214
getFixturesDir(): string;
215
setFixturesDir(dir: string): void;
216
}
217
218
// Chain class for proxy management
219
interface Chain {
220
append(handler: ProxyHandler): Chain;
221
prepend(handler: ProxyHandler): Chain;
222
clear(): void;
223
start: ProxyHandler | null;
224
}
225
226
// Matcher class for request/response matching
227
interface Matcher {
228
(request: ReplayRequest): ReplayResponse | null;
229
}
230
```