or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

body-processing.mderror-handling.mdfile-blob.mdheaders.mdhttp-client.mdindex.mdrequest-response.mdutilities.md

body-processing.mddocs/

0

# Body Processing

1

2

Unified interface for reading and processing request/response bodies with support for multiple formats including JSON, text, binary data, form data, and streams.

3

4

## Capabilities

5

6

### Body Interface

7

8

Shared interface implemented by both Request and Response classes for consistent body handling.

9

10

```javascript { .api }

11

/**

12

* Body interface for reading request/response content

13

*/

14

interface Body {

15

readonly body: ReadableStream | null;

16

readonly bodyUsed: boolean;

17

readonly size: number;

18

19

arrayBuffer(): Promise<ArrayBuffer>;

20

blob(): Promise<Blob>;

21

formData(): Promise<FormData>;

22

json(): Promise<any>;

23

text(): Promise<string>;

24

25

/** @deprecated Use arrayBuffer() instead */

26

buffer(): Promise<Buffer>;

27

}

28

```

29

30

**Usage Examples:**

31

32

```javascript

33

import fetch from 'node-fetch';

34

35

const response = await fetch('https://api.github.com/users/octocat');

36

37

// Check if body has been consumed

38

console.log(response.bodyUsed); // false

39

40

// Read as JSON

41

const userData = await response.json();

42

console.log(response.bodyUsed); // true

43

44

// Cannot read again after consumption

45

try {

46

await response.text(); // This will throw an error

47

} catch (error) {

48

console.error('Body already used:', error.message);

49

}

50

```

51

52

### JSON Processing

53

54

Parse response bodies as JSON with automatic error handling for malformed JSON.

55

56

```javascript { .api }

57

/**

58

* Parse body as JSON

59

* @returns Promise resolving to parsed JSON data

60

* @throws SyntaxError if JSON is malformed

61

*/

62

json(): Promise<any>;

63

```

64

65

**Usage Examples:**

66

67

```javascript

68

// API response as JSON

69

const response = await fetch('https://api.github.com/users/octocat');

70

const userData = await response.json();

71

72

console.log(userData.login); // 'octocat'

73

console.log(userData.id); // 583231

74

console.log(userData.name); // 'The Octocat'

75

76

// Handle JSON parsing errors

77

try {

78

const response = await fetch('https://example.com/malformed-json');

79

const data = await response.json();

80

} catch (error) {

81

if (error instanceof SyntaxError) {

82

console.error('Invalid JSON response:', error.message);

83

}

84

}

85

86

// POST request with JSON response

87

const postResponse = await fetch('https://httpbin.org/post', {

88

method: 'POST',

89

headers: { 'Content-Type': 'application/json' },

90

body: JSON.stringify({ name: 'Alice', age: 30 })

91

});

92

const result = await postResponse.json();

93

console.log(result.json); // { name: 'Alice', age: 30 }

94

```

95

96

### Text Processing

97

98

Read response bodies as plain text with automatic UTF-8 decoding.

99

100

```javascript { .api }

101

/**

102

* Read body as text string

103

* @returns Promise resolving to text content

104

*/

105

text(): Promise<string>;

106

```

107

108

**Usage Examples:**

109

110

```javascript

111

// HTML content

112

const response = await fetch('https://example.com');

113

const htmlContent = await response.text();

114

console.log(htmlContent); // '<!DOCTYPE html><html>...'

115

116

// Plain text API

117

const textResponse = await fetch('https://httpbin.org/uuid');

118

const uuid = await textResponse.text();

119

console.log(uuid.trim()); // 'f47ac10b-58cc-4372-a567-0e02b2c3d479'

120

121

// CSV data

122

const csvResponse = await fetch('https://example.com/data.csv');

123

const csvContent = await csvResponse.text();

124

const rows = csvContent.split('\n');

125

console.log('Number of rows:', rows.length);

126

127

// Large text processing

128

const largeTextResponse = await fetch('https://example.com/large-file.txt');

129

const text = await largeTextResponse.text();

130

console.log('File size:', text.length, 'characters');

131

```

132

133

### Binary Data Processing

134

135

Handle binary data as ArrayBuffer for images, files, and other binary content.

136

137

```javascript { .api }

138

/**

139

* Read body as ArrayBuffer

140

* @returns Promise resolving to ArrayBuffer

141

*/

142

arrayBuffer(): Promise<ArrayBuffer>;

143

```

144

145

**Usage Examples:**

146

147

```javascript

148

// Download image as binary data

149

const imageResponse = await fetch('https://github.com/images/error/octocat_happy.gif');

150

const imageBuffer = await imageResponse.arrayBuffer();

151

152

// Save to file (Node.js)

153

import { writeFileSync } from 'fs';

154

writeFileSync('octocat.gif', Buffer.from(imageBuffer));

155

156

// Process binary data

157

const uint8Array = new Uint8Array(imageBuffer);

158

console.log('File size:', uint8Array.length, 'bytes');

159

console.log('First 4 bytes:', Array.from(uint8Array.slice(0, 4)).map(b => b.toString(16)));

160

161

// Download ZIP file

162

const zipResponse = await fetch('https://example.com/archive.zip');

163

const zipBuffer = await zipResponse.arrayBuffer();

164

console.log('ZIP file size:', zipBuffer.byteLength, 'bytes');

165

166

// Handle different binary formats

167

const pdfResponse = await fetch('https://example.com/document.pdf');

168

const pdfBuffer = await pdfResponse.arrayBuffer();

169

// Process PDF data...

170

```

171

172

### Buffer Processing (Deprecated)

173

174

**⚠️ DEPRECATED**: The `buffer()` method is deprecated in favor of `arrayBuffer()`. Use `arrayBuffer()` for new code.

175

176

```javascript { .api }

177

/**

178

* Read body as Buffer (Node.js specific)

179

* @deprecated Use response.arrayBuffer() instead

180

* @returns Promise resolving to Buffer

181

*/

182

buffer(): Promise<Buffer>;

183

```

184

185

**Migration Example:**

186

187

```javascript

188

// OLD - Deprecated approach

189

const response = await fetch('https://example.com/file.pdf');

190

const buffer = await response.buffer(); // ⚠️ Deprecated

191

192

// NEW - Recommended approach

193

const response = await fetch('https://example.com/file.pdf');

194

const arrayBuffer = await response.arrayBuffer();

195

const buffer = Buffer.from(arrayBuffer);

196

197

// Or for Node.js compatibility

198

const response = await fetch('https://example.com/file.pdf');

199

const buffer = Buffer.from(await response.arrayBuffer());

200

```

201

202

**Why migrate from buffer() to arrayBuffer()?**

203

204

- **Web Standards Compliance**: `arrayBuffer()` is part of the standard Fetch API

205

- **Cross-platform Compatibility**: Works in both Node.js and browsers

206

- **Future-proof**: The `buffer()` method will be removed in future versions

207

- **Better Type Safety**: `ArrayBuffer` provides clearer type semantics

208

209

### Blob Processing

210

211

Convert response bodies to Blob objects for file-like operations.

212

213

```javascript { .api }

214

/**

215

* Read body as Blob

216

* @returns Promise resolving to Blob object

217

*/

218

blob(): Promise<Blob>;

219

```

220

221

**Usage Examples:**

222

223

```javascript

224

// Create blob from response

225

const imageResponse = await fetch('https://example.com/image.jpg');

226

const imageBlob = await imageResponse.blob();

227

228

console.log('Blob size:', imageBlob.size);

229

console.log('Blob type:', imageBlob.type); // 'image/jpeg'

230

231

// Convert blob to other formats

232

const arrayBuffer = await imageBlob.arrayBuffer();

233

const text = await imageBlob.text();

234

235

// Create object URL (browser environment)

236

if (typeof URL !== 'undefined') {

237

const objectUrl = URL.createObjectURL(imageBlob);

238

console.log('Object URL:', objectUrl);

239

240

// Don't forget to revoke when done

241

URL.revokeObjectURL(objectUrl);

242

}

243

244

// Stream blob data

245

const stream = imageBlob.stream();

246

const reader = stream.getReader();

247

248

while (true) {

249

const { done, value } = await reader.read();

250

if (done) break;

251

console.log('Chunk size:', value.length);

252

}

253

```

254

255

### Form Data Processing

256

257

Parse multipart/form-data and application/x-www-form-urlencoded content.

258

259

```javascript { .api }

260

/**

261

* Parse body as FormData

262

* @returns Promise resolving to FormData object

263

* @throws Error if content is not form data

264

*/

265

formData(): Promise<FormData>;

266

```

267

268

**Usage Examples:**

269

270

```javascript

271

// Parse multipart form data

272

const formResponse = await fetch('https://httpbin.org/post', {

273

method: 'POST',

274

body: new FormData() // This would be received as form data

275

});

276

277

const formData = await formResponse.formData();

278

279

// Iterate over form fields

280

for (const [name, value] of formData.entries()) {

281

console.log(`${name}: ${value}`);

282

}

283

284

// Get specific field

285

const username = formData.get('username');

286

const avatar = formData.get('avatar'); // Could be a File object

287

288

// Parse URL-encoded form data

289

const urlEncodedResponse = await fetch('https://httpbin.org/post', {

290

method: 'POST',

291

headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

292

body: 'name=Alice&email=alice@example.com'

293

});

294

295

const parsedForm = await urlEncodedResponse.formData();

296

console.log(parsedForm.get('name')); // 'Alice'

297

console.log(parsedForm.get('email')); // 'alice@example.com'

298

```

299

300

### Stream Processing

301

302

Access the underlying ReadableStream for streaming data processing.

303

304

```javascript { .api }

305

/**

306

* Access to the underlying ReadableStream

307

*/

308

interface StreamAccess {

309

readonly body: ReadableStream | null;

310

}

311

```

312

313

**Usage Examples:**

314

315

```javascript

316

import { pipeline } from 'stream/promises';

317

import { createWriteStream } from 'fs';

318

319

// Stream large file download

320

const response = await fetch('https://example.com/large-file.zip');

321

322

if (!response.ok) {

323

throw new Error(`HTTP error! status: ${response.status}`);

324

}

325

326

// Pipe response stream to file

327

await pipeline(response.body, createWriteStream('./large-file.zip'));

328

console.log('Download completed');

329

330

// Process streaming JSON data

331

const streamResponse = await fetch('https://httpbin.org/stream/10');

332

333

// Read stream chunk by chunk

334

const reader = streamResponse.body.getReader();

335

const decoder = new TextDecoder();

336

337

while (true) {

338

const { done, value } = await reader.read();

339

340

if (done) break;

341

342

const chunk = decoder.decode(value, { stream: true });

343

console.log('Received chunk:', chunk);

344

}

345

346

// Stream with async iteration (Node.js 10+)

347

const asyncStreamResponse = await fetch('https://httpbin.org/stream/5');

348

349

try {

350

for await (const chunk of asyncStreamResponse.body) {

351

const text = chunk.toString();

352

console.log('Processed chunk:', text);

353

}

354

} catch (error) {

355

console.error('Stream error:', error);

356

}

357

```

358

359

### Body Size and Limits

360

361

Control and monitor body size limits for security and performance.

362

363

```javascript { .api }

364

interface BodyLimits {

365

readonly size: number; // Size limit in bytes (0 = unlimited)

366

}

367

```

368

369

**Usage Examples:**

370

371

```javascript

372

// Set response size limit

373

const response = await fetch('https://example.com/large-file', {

374

size: 1024 * 1024 // Limit to 1MB

375

});

376

377

try {

378

const data = await response.arrayBuffer();

379

console.log('Downloaded:', data.byteLength, 'bytes');

380

} catch (error) {

381

if (error.type === 'max-size') {

382

console.error('Response too large:', error.message);

383

}

384

}

385

386

// Check body size before processing

387

if (response.headers.has('content-length')) {

388

const contentLength = parseInt(response.headers.get('content-length'));

389

if (contentLength > 10 * 1024 * 1024) { // 10MB

390

console.warn('Large response detected:', contentLength, 'bytes');

391

}

392

}

393

```

394

395

### Body Usage Patterns

396

397

Common patterns for handling different types of response bodies.

398

399

```javascript { .api }

400

interface BodyUsagePattern {

401

// Pattern for API responses

402

handleApiResponse<T>(): Promise<T>;

403

404

// Pattern for file downloads

405

handleFileDownload(): Promise<Buffer>;

406

407

// Pattern for streaming data

408

handleStreamingData(): AsyncIterableIterator<Uint8Array>;

409

}

410

```

411

412

**Usage Examples:**

413

414

```javascript

415

// API response handler with error checking

416

async function handleApiResponse(url, options = {}) {

417

const response = await fetch(url, options);

418

419

if (!response.ok) {

420

const errorText = await response.text();

421

throw new Error(`API Error ${response.status}: ${errorText}`);

422

}

423

424

const contentType = response.headers.get('content-type');

425

426

if (contentType?.includes('application/json')) {

427

return await response.json();

428

} else if (contentType?.includes('text/')) {

429

return await response.text();

430

} else {

431

return await response.arrayBuffer();

432

}

433

}

434

435

// File download with progress tracking

436

async function downloadFile(url, onProgress) {

437

const response = await fetch(url);

438

const contentLength = response.headers.get('content-length');

439

const total = contentLength ? parseInt(contentLength) : 0;

440

441

let loaded = 0;

442

const chunks = [];

443

444

const reader = response.body.getReader();

445

446

while (true) {

447

const { done, value } = await reader.read();

448

449

if (done) break;

450

451

chunks.push(value);

452

loaded += value.length;

453

454

if (onProgress && total > 0) {

455

onProgress({ loaded, total, percentage: (loaded / total) * 100 });

456

}

457

}

458

459

return Buffer.concat(chunks);

460

}

461

462

// Usage

463

const fileData = await downloadFile('https://example.com/file.zip', (progress) => {

464

console.log(`Download progress: ${progress.percentage.toFixed(1)}%`);

465

});

466

```