0
# Mimic Response
1
2
Mimic Response is a Node.js utility that copies HTTP response properties and event handlers from one stream to another, enabling the creation of proxy streams that behave like the original HTTP response stream. It preserves all HTTP-related properties (statusCode, headers, httpVersion, etc.) and forwards abort and close events appropriately.
3
4
## Package Information
5
6
- **Package Name**: mimic-response
7
- **Package Type**: npm
8
- **Language**: JavaScript (ES Module)
9
- **Installation**: `npm install mimic-response`
10
11
## Core Imports
12
13
```javascript
14
import mimicResponse from "mimic-response";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const mimicResponse = require("mimic-response");
21
```
22
23
For TypeScript:
24
25
```typescript
26
import mimicResponse from "mimic-response";
27
import type { IncomingMessage } from "node:http";
28
```
29
30
## Basic Usage
31
32
```javascript
33
import { PassThrough as PassThroughStream } from "node:stream";
34
import mimicResponse from "mimic-response";
35
36
// Get an HTTP response stream from a request
37
const responseStream = getHttpResponseStream();
38
39
// Create a new stream that will mimic the response
40
const myStream = new PassThroughStream({ autoDestroy: false });
41
42
// Copy all HTTP properties and event handlers
43
mimicResponse(responseStream, myStream);
44
45
// Now myStream has all the HTTP response properties
46
console.log(myStream.statusCode); // 200
47
console.log(myStream.headers); // Response headers object
48
console.log(myStream.complete); // Boolean indicating response completion
49
```
50
51
## Capabilities
52
53
### Stream Mimicking
54
55
Copies all HTTP response properties from a source stream to a target stream, making the target stream behave like an HTTP response.
56
57
```javascript { .api }
58
/**
59
* Mimic a Node.js HTTP response stream by copying properties and event handlers
60
* @param fromStream - The HTTP response stream to copy properties from
61
* @param toStream - The target stream to copy properties to (must have autoDestroy: false)
62
* @returns The enhanced toStream with HTTP response properties
63
* @throws Error if toStream has autoDestroy: true
64
*/
65
function mimicResponse<T extends NodeJS.ReadableStream>(
66
fromStream: IncomingMessage,
67
toStream: T
68
): T & IncomingMessage;
69
```
70
71
**Parameters:**
72
- `fromStream` (IncomingMessage): The source HTTP response stream containing properties to copy
73
- `toStream` (NodeJS.ReadableStream): The target stream that will receive the copied properties. Must have `autoDestroy: false`
74
75
**Returns:** The `toStream` parameter enhanced with all HTTP response properties from `fromStream`
76
77
**Throws:** Error with message "The second stream must have the `autoDestroy` option set to `false`" if `toStream._readableState.autoDestroy` is `true`
78
79
**Copied Properties:**
80
The function copies all enumerable properties from the source stream plus these known HTTP response properties:
81
82
```javascript { .api }
83
const knownProperties = [
84
'aborted', // Boolean indicating if request was aborted
85
'complete', // Boolean indicating if response is complete
86
'headers', // Response headers object
87
'httpVersion', // HTTP version string (e.g., "1.1")
88
'httpVersionMinor', // HTTP version minor number
89
'httpVersionMajor', // HTTP version major number
90
'method', // HTTP method string
91
'rawHeaders', // Raw headers array
92
'rawTrailers', // Raw trailers array
93
'setTimeout', // Timeout method function
94
'socket', // Underlying socket object
95
'statusCode', // HTTP status code number
96
'statusMessage', // HTTP status message string
97
'trailers', // Response trailers object
98
'url' // Request URL string
99
];
100
```
101
102
**Event Forwarding:**
103
- **aborted**: When source stream emits 'aborted', destroys target stream and re-emits 'aborted'
104
- **close**: When source stream emits 'close', re-emits 'close' on target stream with proper timing based on response completion
105
106
**Usage Examples:**
107
108
Basic stream proxy:
109
```javascript
110
import { PassThrough as PassThroughStream } from "node:stream";
111
import mimicResponse from "mimic-response";
112
113
const responseStream = getHttpResponseStream();
114
const proxyStream = new PassThroughStream({ autoDestroy: false });
115
116
mimicResponse(responseStream, proxyStream);
117
118
// Access HTTP properties on the proxy stream
119
console.log(proxyStream.statusCode); // Same as responseStream.statusCode
120
console.log(proxyStream.headers); // Same as responseStream.headers
121
```
122
123
Custom stream with manual destroy handling:
124
```javascript
125
import { PassThrough as PassThroughStream } from "node:stream";
126
import mimicResponse from "mimic-response";
127
128
const responseStream = getHttpResponseStream();
129
130
const myStream = new PassThroughStream({
131
autoDestroy: false,
132
destroy(error, callback) {
133
// Manually destroy the source stream
134
responseStream.destroy();
135
callback(error);
136
}
137
});
138
139
mimicResponse(responseStream, myStream);
140
141
// The streams are now linked for destruction
142
myStream.destroy();
143
```
144
145
Stream transformation pipeline:
146
```javascript
147
import { Transform } from "node:stream";
148
import mimicResponse from "mimic-response";
149
150
const responseStream = getHttpResponseStream();
151
152
const transformStream = new Transform({
153
autoDestroy: false,
154
transform(chunk, encoding, callback) {
155
// Transform the data while preserving HTTP properties
156
const transformed = chunk.toString().toUpperCase();
157
callback(null, transformed);
158
}
159
});
160
161
mimicResponse(responseStream, transformStream);
162
163
// Transform stream now has HTTP properties and transforms data
164
responseStream.pipe(transformStream);
165
```
166
167
## Types
168
169
```typescript { .api }
170
interface IncomingMessage extends NodeJS.ReadableStream {
171
aborted: boolean;
172
complete: boolean;
173
headers: { [key: string]: string | string[] | undefined };
174
httpVersion: string;
175
httpVersionMajor: number;
176
httpVersionMinor: number;
177
method?: string;
178
rawHeaders: string[];
179
rawTrailers: string[];
180
setTimeout(msecs: number, callback?: () => void): this;
181
socket: any;
182
statusCode?: number;
183
statusMessage?: string;
184
trailers: { [key: string]: string | undefined };
185
url?: string;
186
}
187
```
188
189
## Error Handling
190
191
The function validates that the target stream is properly configured:
192
193
- **Validation Error**: Throws an Error if `toStream._readableState.autoDestroy` is `true`
194
- **Error Message**: "The second stream must have the `autoDestroy` option set to `false`"
195
196
This validation ensures that the target stream won't be automatically destroyed, which is necessary for proper event forwarding and property access.
197
198
## Important Notes
199
200
1. **AutoDestroy Requirement**: The target stream must have `autoDestroy: false` to prevent automatic cleanup that would interfere with property access and event handling.
201
202
2. **Property Binding**: Function properties from the source stream are bound to maintain the correct `this` context when called on the target stream.
203
204
3. **Non-Overwriting**: Existing properties on the target stream are never overwritten, preserving the target stream's original functionality.
205
206
4. **Manual Destroy Handling**: The `destroy()` method is not automatically proxied. You must manually handle destruction if needed.
207
208
5. **Event Timing**: The 'close' event forwarding handles different timing scenarios based on whether the response is complete and whether the target stream is still readable.