or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-management.mdcookies.mderror-handling.mdhttp-api.mdhttp-clients.mdindex.mdinterceptors.mdtesting-mocking.mdutilities.mdweb-standards.md

utilities.mddocs/

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

```