0
# Web Standards Implementation
1
2
Complete WHATWG-compliant implementations of fetch, WebSocket, EventSource, and related Web APIs for Node.js environments.
3
4
## Capabilities
5
6
### fetch
7
8
WHATWG fetch API implementation with full Web Standards compliance and performance optimizations.
9
10
```javascript { .api }
11
/**
12
* WHATWG fetch API implementation
13
* @param input - URL or Request object
14
* @param init - Request initialization options
15
* @returns Promise resolving to Response
16
*/
17
function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
18
19
type RequestInfo = string | URL | Request;
20
21
interface RequestInit {
22
method?: string;
23
headers?: HeadersInit;
24
body?: BodyInit;
25
mode?: RequestMode;
26
credentials?: RequestCredentials;
27
cache?: RequestCache;
28
redirect?: RequestRedirect;
29
referrer?: string;
30
referrerPolicy?: ReferrerPolicy;
31
integrity?: string;
32
keepalive?: boolean;
33
signal?: AbortSignal;
34
window?: null;
35
duplex?: RequestDuplex;
36
}
37
38
type RequestMode = 'cors' | 'no-cors' | 'same-origin' | 'navigate';
39
type RequestCredentials = 'omit' | 'same-origin' | 'include';
40
type RequestCache = 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached';
41
type RequestRedirect = 'follow' | 'error' | 'manual';
42
type RequestDuplex = 'half';
43
```
44
45
**Usage Examples:**
46
47
```javascript
48
import { fetch } from 'undici';
49
50
// Simple GET request
51
const response = await fetch('https://api.example.com/users');
52
const users = await response.json();
53
54
// POST request with JSON
55
const createResponse = await fetch('https://api.example.com/users', {
56
method: 'POST',
57
headers: {
58
'Content-Type': 'application/json'
59
},
60
body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' })
61
});
62
63
// Request with abort signal
64
const controller = new AbortController();
65
setTimeout(() => controller.abort(), 5000);
66
67
try {
68
const response = await fetch('https://slow-api.example.com/data', {
69
signal: controller.signal
70
});
71
const data = await response.json();
72
} catch (error) {
73
if (error.name === 'AbortError') {
74
console.log('Request was aborted');
75
}
76
}
77
78
// Custom request options
79
const response = await fetch('https://api.example.com/data', {
80
method: 'GET',
81
mode: 'cors',
82
credentials: 'include',
83
cache: 'no-cache',
84
redirect: 'follow'
85
});
86
```
87
88
### Request
89
90
WHATWG Request API implementation for representing HTTP requests.
91
92
```javascript { .api }
93
/**
94
* Represents an HTTP request
95
*/
96
class Request {
97
constructor(input: RequestInfo, init?: RequestInit);
98
99
readonly method: string;
100
readonly url: string;
101
readonly headers: Headers;
102
readonly body: ReadableStream | null;
103
readonly bodyUsed: boolean;
104
readonly mode: RequestMode;
105
readonly credentials: RequestCredentials;
106
readonly cache: RequestCache;
107
readonly redirect: RequestRedirect;
108
readonly referrer: string;
109
readonly referrerPolicy: ReferrerPolicy;
110
readonly integrity: string;
111
readonly keepalive: boolean;
112
readonly signal: AbortSignal;
113
readonly duplex: RequestDuplex;
114
115
clone(): Request;
116
arrayBuffer(): Promise<ArrayBuffer>;
117
blob(): Promise<Blob>;
118
bytes(): Promise<Uint8Array>;
119
formData(): Promise<FormData>;
120
json(): Promise<any>;
121
text(): Promise<string>;
122
}
123
```
124
125
**Usage Examples:**
126
127
```javascript
128
import { Request, fetch } from 'undici';
129
130
// Create reusable request
131
const baseRequest = new Request('https://api.example.com/users', {
132
method: 'GET',
133
headers: { 'Authorization': 'Bearer token123' }
134
});
135
136
// Clone and modify requests
137
const userRequest = baseRequest.clone();
138
const postsRequest = new Request('https://api.example.com/posts', baseRequest);
139
140
// Use with fetch
141
const response = await fetch(userRequest);
142
const users = await response.json();
143
```
144
145
### Response
146
147
WHATWG Response API implementation for representing HTTP responses.
148
149
```javascript { .api }
150
/**
151
* Represents an HTTP response
152
*/
153
class Response {
154
constructor(body?: BodyInit, init?: ResponseInit);
155
156
readonly status: number;
157
readonly statusText: string;
158
readonly ok: boolean;
159
readonly redirected: boolean;
160
readonly type: ResponseType;
161
readonly url: string;
162
readonly headers: Headers;
163
readonly body: ReadableStream | null;
164
readonly bodyUsed: boolean;
165
166
static error(): Response;
167
static json(data: any, init?: ResponseInit): Response;
168
static redirect(url: string | URL, status?: number): Response;
169
170
clone(): Response;
171
arrayBuffer(): Promise<ArrayBuffer>;
172
blob(): Promise<Blob>;
173
bytes(): Promise<Uint8Array>;
174
formData(): Promise<FormData>;
175
json(): Promise<any>;
176
text(): Promise<string>;
177
}
178
179
interface ResponseInit {
180
status?: number;
181
statusText?: string;
182
headers?: HeadersInit;
183
}
184
185
type ResponseType = 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect';
186
```
187
188
**Usage Examples:**
189
190
```javascript
191
import { Response } from 'undici';
192
193
// Create custom responses
194
const jsonResponse = Response.json({ message: 'Hello World' });
195
const redirectResponse = Response.redirect('https://example.com/new-url', 302);
196
const errorResponse = Response.error();
197
198
// Process response data
199
const response = await fetch('https://api.example.com/data');
200
201
if (response.ok) {
202
const contentType = response.headers.get('content-type');
203
204
if (contentType?.includes('application/json')) {
205
const data = await response.json();
206
console.log(data);
207
} else {
208
const text = await response.text();
209
console.log(text);
210
}
211
} else {
212
console.error(`Request failed: ${response.status} ${response.statusText}`);
213
}
214
```
215
216
### WebSocket
217
218
WHATWG WebSocket API implementation for real-time bidirectional communication.
219
220
```javascript { .api }
221
/**
222
* WebSocket client implementation
223
*/
224
class WebSocket extends EventTarget {
225
constructor(url: string | URL, protocols?: string | string[], options?: WebSocketInit);
226
227
static readonly CONNECTING: 0;
228
static readonly OPEN: 1;
229
static readonly CLOSING: 2;
230
static readonly CLOSED: 3;
231
232
readonly url: string;
233
readonly readyState: number;
234
readonly extensions: string;
235
readonly protocol: string;
236
binaryType: BinaryType;
237
238
send(data: string | ArrayBuffer | ArrayBufferView | Blob): void;
239
close(code?: number, reason?: string): void;
240
241
// Event handlers
242
onopen: ((event: Event) => void) | null;
243
onmessage: ((event: MessageEvent) => void) | null;
244
onerror: ((event: ErrorEvent) => void) | null;
245
onclose: ((event: CloseEvent) => void) | null;
246
}
247
248
interface WebSocketInit {
249
protocols?: string[];
250
headers?: HeadersInit;
251
followRedirects?: boolean;
252
maxRedirects?: number;
253
maxPayload?: number;
254
skipUTF8Validation?: boolean;
255
dispatcher?: Dispatcher;
256
}
257
258
type BinaryType = 'blob' | 'arraybuffer';
259
```
260
261
**Usage Examples:**
262
263
```javascript
264
import { WebSocket } from 'undici';
265
266
// Basic WebSocket connection
267
const ws = new WebSocket('wss://echo.websocket.org');
268
269
ws.onopen = (event) => {
270
console.log('WebSocket connected');
271
ws.send('Hello Server!');
272
};
273
274
ws.onmessage = (event) => {
275
console.log('Received:', event.data);
276
};
277
278
ws.onerror = (event) => {
279
console.error('WebSocket error:', event);
280
};
281
282
ws.onclose = (event) => {
283
console.log(`WebSocket closed: ${event.code} ${event.reason}`);
284
};
285
286
// WebSocket with protocols and headers
287
const authWs = new WebSocket('wss://api.example.com/socket', ['chat', 'v1'], {
288
headers: {
289
'Authorization': 'Bearer token123'
290
},
291
maxPayload: 64 * 1024 // 64KB
292
});
293
294
// Send different data types
295
authWs.send('text message');
296
authWs.send(new ArrayBuffer(8));
297
authWs.send(new Uint8Array([1, 2, 3, 4]));
298
299
// Close with custom code and reason
300
authWs.close(1000, 'Normal closure');
301
```
302
303
### WebSocket Events
304
305
WebSocket event classes for handling connection lifecycle.
306
307
```javascript { .api }
308
/**
309
* WebSocket close event
310
*/
311
class CloseEvent extends Event {
312
constructor(type: string, eventInitDict?: CloseEventInit);
313
314
readonly code: number;
315
readonly reason: string;
316
readonly wasClean: boolean;
317
}
318
319
interface CloseEventInit extends EventInit {
320
code?: number;
321
reason?: string;
322
wasClean?: boolean;
323
}
324
325
/**
326
* WebSocket error event
327
*/
328
class ErrorEvent extends Event {
329
constructor(type: string, eventInitDict?: ErrorEventInit);
330
331
readonly message: string;
332
readonly error: any;
333
}
334
335
interface ErrorEventInit extends EventInit {
336
message?: string;
337
error?: any;
338
}
339
340
/**
341
* WebSocket message event
342
*/
343
class MessageEvent extends Event {
344
constructor(type: string, eventInitDict?: MessageEventInit);
345
346
readonly data: any;
347
readonly origin: string;
348
readonly lastEventId: string;
349
readonly source: any;
350
readonly ports: MessagePort[];
351
}
352
353
interface MessageEventInit extends EventInit {
354
data?: any;
355
origin?: string;
356
lastEventId?: string;
357
source?: any;
358
ports?: MessagePort[];
359
}
360
```
361
362
### WebSocket Utilities
363
364
```javascript { .api }
365
/**
366
* Send a ping frame to a WebSocket
367
* @param ws - WebSocket instance
368
* @param data - Optional ping data
369
* @returns Promise resolving when pong is received
370
*/
371
function ping(ws: WebSocket, data?: Buffer): Promise<void>;
372
```
373
374
**Usage Examples:**
375
376
```javascript
377
import { WebSocket, ping } from 'undici';
378
379
const ws = new WebSocket('wss://example.com/socket');
380
381
ws.onopen = async () => {
382
// Send ping and wait for pong
383
try {
384
await ping(ws, Buffer.from('ping-data'));
385
console.log('Ping successful');
386
} catch (error) {
387
console.error('Ping failed:', error);
388
}
389
};
390
```
391
392
### WebSocket Streams
393
394
Streaming WebSocket implementation providing a simpler streams-based API.
395
396
```javascript { .api }
397
/**
398
* Streaming WebSocket implementation
399
*/
400
class WebSocketStream {
401
constructor(url: string | URL, options?: WebSocketStreamInit);
402
403
readonly url: string;
404
readonly connection: Promise<WebSocketConnection>;
405
406
close(closeInfo?: WebSocketCloseInfo): void;
407
}
408
409
interface WebSocketStreamInit {
410
protocols?: string[];
411
signal?: AbortSignal;
412
}
413
414
interface WebSocketConnection {
415
readonly readable: ReadableStream;
416
readonly writable: WritableStream;
417
readonly extensions: string;
418
readonly protocol: string;
419
}
420
421
interface WebSocketCloseInfo {
422
code?: number;
423
reason?: string;
424
}
425
```
426
427
### WebSocket Errors
428
429
Specialized error types for WebSocket operations.
430
431
```javascript { .api }
432
/**
433
* WebSocket-specific error class
434
*/
435
class WebSocketError extends Error {
436
constructor(message: string, init?: WebSocketErrorInit);
437
438
readonly closeCode?: number;
439
readonly reason?: string;
440
}
441
442
interface WebSocketErrorInit {
443
closeCode?: number;
444
reason?: string;
445
}
446
```
447
448
**Usage Examples:**
449
450
```javascript
451
import { WebSocketStream, WebSocketError } from 'undici';
452
453
// Create a streaming WebSocket connection
454
const wsStream = new WebSocketStream('wss://api.example.com/stream');
455
456
try {
457
const connection = await wsStream.connection;
458
459
// Use readable stream
460
const reader = connection.readable.getReader();
461
while (true) {
462
const { value, done } = await reader.read();
463
if (done) break;
464
console.log('Received:', value);
465
}
466
467
// Use writable stream
468
const writer = connection.writable.getWriter();
469
await writer.write('Hello Stream!');
470
await writer.close();
471
472
} catch (error) {
473
if (error instanceof WebSocketError) {
474
console.error(`WebSocket error: ${error.message}, code: ${error.closeCode}`);
475
}
476
}
477
```
478
479
### EventSource
480
481
WHATWG EventSource API implementation for server-sent events.
482
483
```javascript { .api }
484
/**
485
* Server-sent events client
486
*/
487
class EventSource extends EventTarget {
488
constructor(url: string | URL, eventSourceInitDict?: EventSourceInit);
489
490
static readonly CONNECTING: 0;
491
static readonly OPEN: 1;
492
static readonly CLOSED: 2;
493
494
readonly url: string;
495
readonly readyState: number;
496
readonly withCredentials: boolean;
497
498
close(): void;
499
500
// Event handlers
501
onopen: ((event: Event) => void) | null;
502
onmessage: ((event: MessageEvent) => void) | null;
503
onerror: ((event: Event) => void) | null;
504
}
505
506
interface EventSourceInit {
507
withCredentials?: boolean;
508
headers?: HeadersInit;
509
dispatcher?: Dispatcher;
510
}
511
```
512
513
**Usage Examples:**
514
515
```javascript
516
import { EventSource } from 'undici';
517
518
// Basic EventSource connection
519
const eventSource = new EventSource('https://api.example.com/events');
520
521
eventSource.onopen = () => {
522
console.log('EventSource connected');
523
};
524
525
eventSource.onmessage = (event) => {
526
console.log('Received event:', JSON.parse(event.data));
527
};
528
529
eventSource.onerror = (event) => {
530
console.error('EventSource error:', event);
531
};
532
533
// EventSource with credentials and custom headers
534
const authEventSource = new EventSource('https://api.example.com/private-events', {
535
withCredentials: true,
536
headers: {
537
'Authorization': 'Bearer token123'
538
}
539
});
540
541
// Listen for custom event types
542
authEventSource.addEventListener('user-update', (event) => {
543
const userData = JSON.parse(event.data);
544
console.log('User updated:', userData);
545
});
546
547
// Close connection
548
setTimeout(() => {
549
eventSource.close();
550
}, 30000);
551
```
552
553
## Types
554
555
### Body and Header Types
556
557
```javascript { .api }
558
type BodyInit =
559
| ArrayBuffer
560
| AsyncIterable<Uint8Array>
561
| Blob
562
| FormData
563
| Iterable<Uint8Array>
564
| NodeJS.ArrayBufferView
565
| URLSearchParams
566
| null
567
| string;
568
569
type HeadersInit =
570
| Headers
571
| Record<string, string | ReadonlyArray<string>>
572
| Iterable<readonly [string, string]>;
573
574
type ReferrerPolicy =
575
| ''
576
| 'no-referrer'
577
| 'no-referrer-when-downgrade'
578
| 'same-origin'
579
| 'origin'
580
| 'strict-origin'
581
| 'origin-when-cross-origin'
582
| 'strict-origin-when-cross-origin'
583
| 'unsafe-url';
584
```