0
# Utilities
1
2
Helper functions and utilities for HTTP operations, header manipulation, content processing, and various supporting functionality for Undici operations.
3
4
## Capabilities
5
6
### Header Utilities
7
8
Functions for parsing and manipulating HTTP headers.
9
10
```typescript { .api }
11
namespace util {
12
/**
13
* Parse raw headers array into headers object
14
* @param headers - Raw headers array [name, value, name, value, ...]
15
* @param obj - Optional object to assign parsed values to
16
* @returns Parsed headers object
17
*/
18
function parseHeaders(
19
headers: (Buffer | string | (Buffer | string)[])[],
20
obj?: Record<string, string | string[]>
21
): Record<string, string | string[]>;
22
23
/**
24
* Convert header name to proper string format and lowercase it
25
* @param value - Header name buffer or string
26
* @returns Header name as lowercase string
27
*/
28
function headerNameToString(value: string | Buffer): string;
29
}
30
31
/**
32
* Convert header value to proper string format
33
* @param value - Header value buffer or string
34
* @returns Header value as string
35
*/
36
function headerValueToString(value: string | Buffer): string;
37
38
/**
39
* Check if header name is valid
40
* @param name - Header name to validate
41
* @returns True if valid header name
42
*/
43
function isValidHeaderName(name: string): boolean;
44
45
/**
46
* Check if header value is valid
47
* @param value - Header value to validate
48
* @returns True if valid header value
49
*/
50
function isValidHeaderValue(value: string): boolean;
51
```
52
53
**Usage Examples:**
54
55
```typescript
56
import { util } from "undici-types";
57
58
// Parse raw headers from HTTP response
59
const rawHeaders = [
60
"content-type", "application/json",
61
"content-length", "1024",
62
"set-cookie", "session=abc123",
63
"set-cookie", "theme=dark",
64
"cache-control", "no-cache"
65
];
66
67
const parsed = util.parseHeaders(rawHeaders);
68
console.log(parsed);
69
// {
70
// "content-type": "application/json",
71
// "content-length": "1024",
72
// "set-cookie": ["session=abc123", "theme=dark"],
73
// "cache-control": "no-cache"
74
// }
75
76
// Convert header names/values from buffers
77
const headerName = util.headerNameToString(Buffer.from("Content-Type"));
78
const headerValue = headerValueToString(Buffer.from("application/json"));
79
80
// Validate header components
81
console.log(isValidHeaderName("Content-Type")); // true
82
console.log(isValidHeaderName("Content\nType")); // false - contains newline
83
84
console.log(isValidHeaderValue("application/json")); // true
85
console.log(isValidHeaderValue("value\r\n")); // false - contains CRLF
86
87
// Safe header construction
88
function setHeader(headers: Record<string, string>, name: string, value: string) {
89
if (!isValidHeaderName(name)) {
90
throw new Error(`Invalid header name: ${name}`);
91
}
92
93
if (!isValidHeaderValue(value)) {
94
throw new Error(`Invalid header value for ${name}: ${value}`);
95
}
96
97
headers[name.toLowerCase()] = value;
98
}
99
```
100
101
### Content-Type Utilities
102
103
MIME type parsing and manipulation utilities.
104
105
```typescript { .api }
106
/**
107
* Parse MIME type string into structured format
108
* @param input - MIME type string to parse
109
* @returns Parsed MIME type object or 'failure' if invalid
110
*/
111
function parseMIMEType(input: string): MIMEType | 'failure';
112
113
/**
114
* Serialize MIME type object back to string
115
* @param mimeType - MIME type object to serialize
116
* @returns MIME type string
117
*/
118
function serializeAMimeType(mimeType: MIMEType): string;
119
120
interface MIMEType {
121
type: string;
122
subtype: string;
123
parameters: Map<string, string>;
124
essence: string;
125
}
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
import { parseMIMEType, serializeAMimeType } from "undici-types";
132
133
// Parse Content-Type header
134
const contentType = "application/json; charset=utf-8; boundary=something";
135
const parsed = parseMIMEType(contentType);
136
137
if (parsed !== 'failure') {
138
console.log(parsed.type); // "application"
139
console.log(parsed.subtype); // "json"
140
console.log(parsed.essence); // "application/json"
141
console.log(parsed.parameters.get("charset")); // "utf-8"
142
console.log(parsed.parameters.get("boundary")); // "something"
143
}
144
145
// Create MIME type programmatically
146
const mimeType: MIMEType = {
147
type: "text",
148
subtype: "html",
149
essence: "text/html",
150
parameters: new Map([
151
["charset", "utf-8"],
152
["boundary", "----WebKitFormBoundary7MA4YWxkTrZu0gW"]
153
])
154
};
155
156
const serialized = serializeAMimeType(mimeType);
157
console.log(serialized); // "text/html; charset=utf-8; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
158
159
// Content type validation helper
160
function isJsonContentType(contentTypeHeader: string): boolean {
161
const parsed = parseMIMEType(contentTypeHeader);
162
return parsed !== 'failure' && parsed.essence === "application/json";
163
}
164
165
// Usage in request handling
166
const response = await fetch("/api/data");
167
const contentType = response.headers.get("content-type");
168
169
if (contentType && isJsonContentType(contentType)) {
170
const data = await response.json();
171
console.log("JSON data:", data);
172
} else {
173
const text = await response.text();
174
console.log("Text data:", text);
175
}
176
```
177
178
### Cookie Utilities
179
180
Cookie parsing and serialization functions.
181
182
```typescript { .api }
183
/**
184
* Parse cookie header string into cookie objects
185
* @param header - Cookie header string
186
* @returns Array of parsed cookie objects
187
*/
188
function parseCookies(header: string): Cookie[];
189
190
/**
191
* Serialize cookie object into Set-Cookie header string
192
* @param cookie - Cookie object to serialize
193
* @returns Set-Cookie header string
194
*/
195
function serializeCookie(cookie: Cookie): string;
196
197
interface Cookie {
198
name: string;
199
value: string;
200
expires?: Date;
201
maxAge?: number;
202
domain?: string;
203
path?: string;
204
secure?: boolean;
205
httpOnly?: boolean;
206
sameSite?: "Strict" | "Lax" | "None";
207
}
208
```
209
210
**Usage Examples:**
211
212
```typescript
213
import { parseCookies, serializeCookie } from "undici-types";
214
215
// Parse Cookie header from request
216
const cookieHeader = "session=abc123; theme=dark; lang=en-US";
217
const cookies = parseCookies(cookieHeader);
218
219
cookies.forEach(cookie => {
220
console.log(`${cookie.name}: ${cookie.value}`);
221
});
222
// session: abc123
223
// theme: dark
224
// lang: en-US
225
226
// Create and serialize cookies
227
const sessionCookie: Cookie = {
228
name: "session",
229
value: "xyz789",
230
expires: new Date(Date.now() + 86400000), // 24 hours
231
path: "/",
232
secure: true,
233
httpOnly: true,
234
sameSite: "Strict"
235
};
236
237
const cookieString = serializeCookie(sessionCookie);
238
console.log(cookieString);
239
// "session=xyz789; Expires=...; Path=/; Secure; HttpOnly; SameSite=Strict"
240
241
// Cookie management helper
242
class CookieManager {
243
private cookies = new Map<string, Cookie>();
244
245
setCookie(cookie: Cookie) {
246
this.cookies.set(cookie.name, cookie);
247
}
248
249
getCookie(name: string): Cookie | undefined {
250
return this.cookies.get(name);
251
}
252
253
getSetCookieHeaders(): string[] {
254
return Array.from(this.cookies.values()).map(serializeCookie);
255
}
256
257
parseCookieHeader(header: string) {
258
const cookies = parseCookies(header);
259
cookies.forEach(cookie => this.cookies.set(cookie.name, cookie));
260
}
261
}
262
263
// Usage
264
const manager = new CookieManager();
265
manager.setCookie({
266
name: "auth_token",
267
value: "bearer_token_here",
268
maxAge: 3600,
269
secure: true,
270
httpOnly: true
271
});
272
273
const headers = manager.getSetCookieHeaders();
274
// Use headers in response
275
```
276
277
### URL and Query Utilities
278
279
URL manipulation and query string processing utilities.
280
281
```typescript { .api }
282
/**
283
* Build query string from parameters object
284
* @param params - Parameters object
285
* @returns Query string
286
*/
287
function buildQueryString(params: Record<string, any>): string;
288
289
/**
290
* Parse query string into parameters object
291
* @param query - Query string to parse
292
* @returns Parameters object
293
*/
294
function parseQueryString(query: string): Record<string, string | string[]>;
295
296
/**
297
* Resolve relative URL against base URL
298
* @param base - Base URL
299
* @param relative - Relative URL
300
* @returns Resolved absolute URL
301
*/
302
function resolveURL(base: string | URL, relative: string): string;
303
304
/**
305
* Normalize URL by removing redundant components
306
* @param url - URL to normalize
307
* @returns Normalized URL
308
*/
309
function normalizeURL(url: string | URL): string;
310
```
311
312
**Usage Examples:**
313
314
```typescript
315
import {
316
buildQueryString,
317
parseQueryString,
318
resolveURL,
319
normalizeURL
320
} from "undici-types";
321
322
// Build query strings
323
const params = {
324
q: "search term",
325
page: 2,
326
filters: ["active", "recent"],
327
sort: "date"
328
};
329
330
const queryString = buildQueryString(params);
331
console.log(queryString); // "q=search%20term&page=2&filters=active&filters=recent&sort=date"
332
333
// Parse query strings
334
const parsed = parseQueryString("q=hello&page=1&tags=js&tags=web");
335
console.log(parsed);
336
// {
337
// q: "hello",
338
// page: "1",
339
// tags: ["js", "web"]
340
// }
341
342
// URL resolution
343
const baseURL = "https://api.example.com/v1/";
344
const resolved = resolveURL(baseURL, "../v2/users");
345
console.log(resolved); // "https://api.example.com/v2/users"
346
347
// URL normalization
348
const normalized = normalizeURL("https://example.com:443/api//users/../posts/./123");
349
console.log(normalized); // "https://example.com/api/posts/123"
350
351
// Request helper with query building
352
async function apiRequest(endpoint: string, params?: Record<string, any>) {
353
let url = `https://api.example.com${endpoint}`;
354
355
if (params) {
356
const queryString = buildQueryString(params);
357
url += `?${queryString}`;
358
}
359
360
return fetch(url);
361
}
362
363
// Usage
364
const response = await apiRequest("/users", {
365
page: 1,
366
limit: 20,
367
active: true
368
});
369
```
370
371
### Stream Utilities
372
373
Utilities for working with Node.js streams and web streams.
374
375
```typescript { .api }
376
/**
377
* Convert Node.js Readable to web ReadableStream
378
* @param nodeStream - Node.js readable stream
379
* @returns Web ReadableStream
380
*/
381
function nodeStreamToWebStream(nodeStream: NodeJS.ReadableStream): ReadableStream<Uint8Array>;
382
383
/**
384
* Convert web ReadableStream to Node.js Readable
385
* @param webStream - Web ReadableStream
386
* @returns Node.js Readable stream
387
*/
388
function webStreamToNodeStream(webStream: ReadableStream<Uint8Array>): NodeJS.ReadableStream;
389
390
/**
391
* Create readable stream from async iterator
392
* @param iterator - Async iterator
393
* @returns Readable stream
394
*/
395
function iteratorToStream<T>(iterator: AsyncIterable<T>): ReadableStream<T>;
396
397
/**
398
* Collect all chunks from a stream into buffer
399
* @param stream - Stream to collect from
400
* @returns Buffer with all data
401
*/
402
function collectStream(stream: NodeJS.ReadableStream): Promise<Buffer>;
403
```
404
405
**Usage Examples:**
406
407
```typescript
408
import {
409
nodeStreamToWebStream,
410
webStreamToNodeStream,
411
iteratorToStream,
412
collectStream
413
} from "undici-types";
414
import { createReadStream, createWriteStream } from "fs";
415
416
// Convert between stream types
417
const fileStream = createReadStream("./data.txt");
418
const webStream = nodeStreamToWebStream(fileStream);
419
420
// Use web stream with fetch
421
const response = await fetch("https://api.example.com/upload", {
422
method: "POST",
423
body: webStream,
424
duplex: "half"
425
});
426
427
// Convert web stream back to Node.js stream
428
const responseWebStream = response.body;
429
if (responseWebStream) {
430
const nodeStream = webStreamToNodeStream(responseWebStream);
431
nodeStream.pipe(createWriteStream("./response.txt"));
432
}
433
434
// Create stream from async generator
435
async function* generateData() {
436
for (let i = 0; i < 1000; i++) {
437
yield new TextEncoder().encode(`data chunk ${i}\n`);
438
await new Promise(resolve => setTimeout(resolve, 10));
439
}
440
}
441
442
const generatedStream = iteratorToStream(generateData());
443
444
// Collect stream data
445
const nodeReadStream = createReadStream("./small-file.txt");
446
const buffer = await collectStream(nodeReadStream);
447
console.log("File contents:", buffer.toString());
448
449
// Stream transformation pipeline
450
const transformedStream = nodeStreamToWebStream(createReadStream("./input.json"))
451
.pipeThrough(new TransformStream({
452
transform(chunk, controller) {
453
// Process each chunk
454
const text = new TextDecoder().decode(chunk);
455
const processed = text.toUpperCase();
456
controller.enqueue(new TextEncoder().encode(processed));
457
}
458
}));
459
460
// Send transformed stream in request
461
await fetch("https://api.example.com/process", {
462
method: "POST",
463
body: transformedStream,
464
duplex: "half"
465
});
466
```
467
468
### Encoding Utilities
469
470
Text and binary encoding/decoding utilities.
471
472
```typescript { .api }
473
/**
474
* Encode string to UTF-8 bytes
475
* @param text - String to encode
476
* @returns UTF-8 byte array
477
*/
478
function encodeUTF8(text: string): Uint8Array;
479
480
/**
481
* Decode UTF-8 bytes to string
482
* @param bytes - UTF-8 byte array
483
* @returns Decoded string
484
*/
485
function decodeUTF8(bytes: Uint8Array): string;
486
487
/**
488
* Encode string to base64
489
* @param text - String to encode
490
* @returns Base64 encoded string
491
*/
492
function encodeBase64(text: string): string;
493
494
/**
495
* Decode base64 string
496
* @param base64 - Base64 string to decode
497
* @returns Decoded string
498
*/
499
function decodeBase64(base64: string): string;
500
501
/**
502
* URL-safe base64 encoding
503
* @param text - String to encode
504
* @returns URL-safe base64 string
505
*/
506
function encodeBase64URL(text: string): string;
507
508
/**
509
* URL-safe base64 decoding
510
* @param base64url - URL-safe base64 string
511
* @returns Decoded string
512
*/
513
function decodeBase64URL(base64url: string): string;
514
```
515
516
**Usage Examples:**
517
518
```typescript
519
import {
520
encodeUTF8,
521
decodeUTF8,
522
encodeBase64,
523
decodeBase64,
524
encodeBase64URL,
525
decodeBase64URL
526
} from "undici-types";
527
528
// UTF-8 encoding/decoding
529
const text = "Hello, δΈη! π";
530
const utf8Bytes = encodeUTF8(text);
531
console.log(utf8Bytes); // Uint8Array with UTF-8 bytes
532
const decoded = decodeUTF8(utf8Bytes);
533
console.log(decoded); // "Hello, δΈη! π"
534
535
// Base64 encoding/decoding
536
const message = "Secret message";
537
const base64 = encodeBase64(message);
538
console.log(base64); // "U2VjcmV0IG1lc3NhZ2U="
539
const original = decodeBase64(base64);
540
console.log(original); // "Secret message"
541
542
// URL-safe base64 (useful for tokens, IDs)
543
const token = "user:1234/session=active";
544
const urlSafeToken = encodeBase64URL(token);
545
console.log(urlSafeToken); // "dXNlcjoxMjM0L3Nlc3Npb249YWN0aXZl" (no +/= chars)
546
const originalToken = decodeBase64URL(urlSafeToken);
547
console.log(originalToken); // "user:1234/session=active"
548
549
// Authorization header helper
550
function createBasicAuth(username: string, password: string): string {
551
const credentials = `${username}:${password}`;
552
const encoded = encodeBase64(credentials);
553
return `Basic ${encoded}`;
554
}
555
556
// JWT token parsing helper (decode payload only, no verification)
557
function parseJWTPayload(token: string): any {
558
const [, payload] = token.split(".");
559
const decoded = decodeBase64URL(payload);
560
return JSON.parse(decoded);
561
}
562
563
// Usage
564
const authHeader = createBasicAuth("user", "pass123");
565
console.log(authHeader); // "Basic dXNlcjpwYXNzMTIz"
566
567
const jwtToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
568
const payload = parseJWTPayload(jwtToken);
569
console.log(payload); // { sub: "1234567890", name: "John Doe", iat: 1516239022 }
570
```
571
572
### Validation Utilities
573
574
Common validation functions for HTTP-related data.
575
576
```typescript { .api }
577
/**
578
* Check if string is valid URL
579
* @param url - String to validate
580
* @returns True if valid URL
581
*/
582
function isValidURL(url: string): boolean;
583
584
/**
585
* Check if string is valid HTTP method
586
* @param method - String to validate
587
* @returns True if valid HTTP method
588
*/
589
function isValidHTTPMethod(method: string): boolean;
590
591
/**
592
* Check if number is valid HTTP status code
593
* @param status - Number to validate
594
* @returns True if valid status code
595
*/
596
function isValidStatusCode(status: number): boolean;
597
598
/**
599
* Check if string contains only ASCII characters
600
* @param text - String to validate
601
* @returns True if ASCII only
602
*/
603
function isASCII(text: string): boolean;
604
605
/**
606
* Sanitize header value by removing invalid characters
607
* @param value - Header value to sanitize
608
* @returns Sanitized header value
609
*/
610
function sanitizeHeaderValue(value: string): string;
611
```
612
613
**Usage Examples:**
614
615
```typescript
616
import {
617
isValidURL,
618
isValidHTTPMethod,
619
isValidStatusCode,
620
isASCII,
621
sanitizeHeaderValue
622
} from "undici-types";
623
624
// URL validation
625
console.log(isValidURL("https://example.com")); // true
626
console.log(isValidURL("not-a-url")); // false
627
console.log(isValidURL("ftp://files.example.com")); // true
628
629
// HTTP method validation
630
console.log(isValidHTTPMethod("GET")); // true
631
console.log(isValidHTTPMethod("PATCH")); // true
632
console.log(isValidHTTPMethod("INVALID")); // false
633
634
// Status code validation
635
console.log(isValidStatusCode(200)); // true
636
console.log(isValidStatusCode(404)); // true
637
console.log(isValidStatusCode(999)); // false
638
639
// ASCII validation
640
console.log(isASCII("Hello World")); // true
641
console.log(isASCII("Hello δΈη")); // false
642
643
// Header sanitization
644
const unsafeValue = "value\r\nInjected-Header: malicious";
645
const safeValue = sanitizeHeaderValue(unsafeValue);
646
console.log(safeValue); // "value Injected-Header: malicious" (CRLF removed)
647
648
// Request builder with validation
649
function buildRequest(url: string, method: string, headers: Record<string, string>) {
650
if (!isValidURL(url)) {
651
throw new Error(`Invalid URL: ${url}`);
652
}
653
654
if (!isValidHTTPMethod(method)) {
655
throw new Error(`Invalid HTTP method: ${method}`);
656
}
657
658
// Sanitize all header values
659
const sanitizedHeaders: Record<string, string> = {};
660
for (const [name, value] of Object.entries(headers)) {
661
if (!isValidHeaderName(name)) {
662
throw new Error(`Invalid header name: ${name}`);
663
}
664
sanitizedHeaders[name] = sanitizeHeaderValue(value);
665
}
666
667
return {
668
url,
669
method: method.toUpperCase(),
670
headers: sanitizedHeaders
671
};
672
}
673
674
// Usage
675
const request = buildRequest("https://api.example.com/users", "post", {
676
"Content-Type": "application/json",
677
"User-Agent": "MyApp/1.0\r\nX-Injected: hack" // Will be sanitized
678
});
679
```