Skip to content

Commit 141b6f1

Browse files
doc: add esm example for zlib
1 parent 5ba3b54 commit 141b6f1

File tree

1 file changed

+237
-12
lines changed

1 file changed

+237
-12
lines changed

doc/api/zlib.md

Lines changed: 237 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ Gzip, Deflate/Inflate, and Brotli.
1111

1212
To access it:
1313

14-
```js
14+
```mjs
15+
import os from 'node:zlib';
16+
```
17+
18+
```cjs
1519
const zlib = require('node:zlib');
1620
```
1721

@@ -21,13 +25,35 @@ Compressing or decompressing a stream (such as a file) can be accomplished by
2125
piping the source stream through a `zlib` `Transform` stream into a destination
2226
stream:
2327

24-
```js
25-
const { createGzip } = require('node:zlib');
26-
const { pipeline } = require('node:stream');
28+
```mjs
29+
import {
30+
createReadStream,
31+
createWriteStream,
32+
} from 'node:fs';
33+
import process from 'node:process';
34+
import { createGzip } from 'node:zlib';
35+
import { pipeline } from 'node:stream';
36+
37+
const gzip = createGzip();
38+
const source = createReadStream('input.txt');
39+
const destination = createWriteStream('input.txt.gz');
40+
41+
pipeline(source, gzip, destination, (err) => {
42+
if (err) {
43+
console.error('An error occurred:', err);
44+
process.exitCode = 1;
45+
}
46+
});
47+
```
48+
49+
```cjs
2750
const {
2851
createReadStream,
2952
createWriteStream,
3053
} = require('node:fs');
54+
const process = require('node:process');
55+
const { createGzip } = require('node:zlib');
56+
const { pipeline } = require('node:stream');
3157

3258
const gzip = createGzip();
3359
const source = createReadStream('input.txt');
@@ -39,11 +65,41 @@ pipeline(source, gzip, destination, (err) => {
3965
process.exitCode = 1;
4066
}
4167
});
68+
```
4269

43-
// Or, Promisified
70+
Or, using promisified `pipeline`:
4471

45-
const { promisify } = require('node:util');
46-
const pipe = promisify(pipeline);
72+
```mjs
73+
import {
74+
createReadStream,
75+
createWriteStream,
76+
} from 'node:fs';
77+
import process from 'node:process';
78+
import { createGzip } from 'node:zlib';
79+
import { pipeline } from 'node:stream/promises';
80+
81+
async function do_gzip(input, output) {
82+
const gzip = createGzip();
83+
const source = createReadStream(input);
84+
const destination = createWriteStream(output);
85+
await pipe(source, gzip, destination);
86+
}
87+
88+
do_gzip('input.txt', 'input.txt.gz')
89+
.catch((err) => {
90+
console.error('An error occurred:', err);
91+
process.exitCode = 1;
92+
});
93+
```
94+
95+
```cjs
96+
const {
97+
createReadStream,
98+
createWriteStream,
99+
} = require('node:fs');
100+
const process = require('node:process');
101+
const { createGzip } = require('node:zlib');
102+
const { pipeline } = require('node:stream/promises');
47103

48104
async function do_gzip(input, output) {
49105
const gzip = createGzip();
@@ -61,7 +117,43 @@ do_gzip('input.txt', 'input.txt.gz')
61117

62118
It is also possible to compress or decompress data in a single step:
63119

64-
```js
120+
```mjs
121+
import process from 'node:process';
122+
import { Buffer } from 'node:buffer';
123+
import { deflate, unzip } from 'node:zlib';
124+
125+
const input = '.................................';
126+
deflate(input, (err, buffer) => {
127+
if (err) {
128+
console.error('An error occurred:', err);
129+
process.exitCode = 1;
130+
}
131+
console.log(buffer.toString('base64'));
132+
});
133+
134+
const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
135+
unzip(buffer, (err, buffer) => {
136+
if (err) {
137+
console.error('An error occurred:', err);
138+
process.exitCode = 1;
139+
}
140+
console.log(buffer.toString());
141+
});
142+
143+
// Or, Promisified
144+
145+
import { promisify } from 'node:util';
146+
const do_unzip = promisify(unzip);
147+
148+
do_unzip(buffer)
149+
.then((buf) => console.log(buf.toString()))
150+
.catch((err) => {
151+
console.error('An error occurred:', err);
152+
process.exitCode = 1;
153+
});
154+
```
155+
156+
```cjs
65157
const { deflate, unzip } = require('node:zlib');
66158

67159
const input = '.................................';
@@ -104,7 +196,19 @@ limitations in some applications.
104196
Creating and using a large number of zlib objects simultaneously can cause
105197
significant memory fragmentation.
106198

107-
```js
199+
```mjs
200+
import zlib from 'node:zlib';
201+
import { Buffer } from 'node:buffer';
202+
203+
const payload = Buffer.from('This is some data');
204+
205+
// WARNING: DO NOT DO THIS!
206+
for (let i = 0; i < 30000; ++i) {
207+
zlib.deflate(payload, (err, buffer) => {});
208+
}
209+
```
210+
211+
```cjs
108212
const zlib = require('node:zlib');
109213

110214
const payload = Buffer.from('This is some data');
@@ -138,7 +242,47 @@ Using `zlib` encoding can be expensive, and the results ought to be cached.
138242
See [Memory usage tuning][] for more information on the speed/memory/compression
139243
tradeoffs involved in `zlib` usage.
140244

141-
```js
245+
```mjs
246+
// Client request example
247+
import fs from 'node:fs';
248+
import zlib from 'node:zlib';
249+
import http from 'node:http';
250+
import process from 'node:process';
251+
import { pipeline } from 'node:stream';
252+
253+
const request = http.get({ host: 'example.com',
254+
path: '/',
255+
port: 80,
256+
headers: { 'Accept-Encoding': 'br,gzip,deflate' } });
257+
request.on('response', (response) => {
258+
const output = fs.createWriteStream('example.com_index.html');
259+
260+
const onError = (err) => {
261+
if (err) {
262+
console.error('An error occurred:', err);
263+
process.exitCode = 1;
264+
}
265+
};
266+
267+
switch (response.headers['content-encoding']) {
268+
case 'br':
269+
pipeline(response, zlib.createBrotliDecompress(), output, onError);
270+
break;
271+
// Or, just use zlib.createUnzip() to handle both of the following cases:
272+
case 'gzip':
273+
pipeline(response, zlib.createGunzip(), output, onError);
274+
break;
275+
case 'deflate':
276+
pipeline(response, zlib.createInflate(), output, onError);
277+
break;
278+
default:
279+
pipeline(response, output, onError);
280+
break;
281+
}
282+
});
283+
```
284+
285+
```cjs
142286
// Client request example
143287
const zlib = require('node:zlib');
144288
const http = require('node:http');
@@ -177,7 +321,52 @@ request.on('response', (response) => {
177321
});
178322
```
179323

180-
```js
324+
```mjs
325+
// server example
326+
// Running a gzip operation on every request is quite expensive.
327+
// It would be much more efficient to cache the compressed buffer.
328+
import zlib from 'node:zlib';
329+
import http from 'node:http';
330+
import fs from 'node:fs';
331+
import { pipeline } from 'node:stream';
332+
333+
http.createServer((request, response) => {
334+
const raw = fs.createReadStream('index.html');
335+
// Store both a compressed and an uncompressed version of the resource.
336+
response.setHeader('Vary', 'Accept-Encoding');
337+
const acceptEncoding = request.headers['accept-encoding'] || '';
338+
339+
const onError = (err) => {
340+
if (err) {
341+
// If an error occurs, there's not much we can do because
342+
// the server has already sent the 200 response code and
343+
// some amount of data has already been sent to the client.
344+
// The best we can do is terminate the response immediately
345+
// and log the error.
346+
response.end();
347+
console.error('An error occurred:', err);
348+
}
349+
};
350+
351+
// Note: This is not a conformant accept-encoding parser.
352+
// See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
353+
if (/\bdeflate\b/.test(acceptEncoding)) {
354+
response.writeHead(200, { 'Content-Encoding': 'deflate' });
355+
pipeline(raw, zlib.createDeflate(), response, onError);
356+
} else if (/\bgzip\b/.test(acceptEncoding)) {
357+
response.writeHead(200, { 'Content-Encoding': 'gzip' });
358+
pipeline(raw, zlib.createGzip(), response, onError);
359+
} else if (/\bbr\b/.test(acceptEncoding)) {
360+
response.writeHead(200, { 'Content-Encoding': 'br' });
361+
pipeline(raw, zlib.createBrotliCompress(), response, onError);
362+
} else {
363+
response.writeHead(200, {});
364+
pipeline(raw, response, onError);
365+
}
366+
}).listen(1337);
367+
```
368+
369+
```cjs
181370
// server example
182371
// Running a gzip operation on every request is quite expensive.
183372
// It would be much more efficient to cache the compressed buffer.
@@ -315,7 +504,43 @@ quality, but can be useful when data needs to be available as soon as possible.
315504
In the following example, `flush()` is used to write a compressed partial
316505
HTTP response to the client:
317506

318-
```js
507+
```mjs
508+
import zlib from 'node:zlib';
509+
import http from 'node:http';
510+
import { pipeline } from 'node:stream';
511+
512+
http.createServer((request, response) => {
513+
// For the sake of simplicity, the Accept-Encoding checks are omitted.
514+
response.writeHead(200, { 'content-encoding': 'gzip' });
515+
const output = zlib.createGzip();
516+
let i;
517+
518+
pipeline(output, response, (err) => {
519+
if (err) {
520+
// If an error occurs, there's not much we can do because
521+
// the server has already sent the 200 response code and
522+
// some amount of data has already been sent to the client.
523+
// The best we can do is terminate the response immediately
524+
// and log the error.
525+
clearInterval(i);
526+
response.end();
527+
console.error('An error occurred:', err);
528+
}
529+
});
530+
531+
i = setInterval(() => {
532+
output.write(`The current time is ${Date()}\n`, () => {
533+
// The data has been passed to zlib, but the compression algorithm may
534+
// have decided to buffer the data for more efficient compression.
535+
// Calling .flush() will make the data available as soon as the client
536+
// is ready to receive it.
537+
output.flush();
538+
});
539+
}, 1000);
540+
}).listen(1337);
541+
```
542+
543+
```cjs
319544
const zlib = require('node:zlib');
320545
const http = require('node:http');
321546
const { pipeline } = require('node:stream');

0 commit comments

Comments
 (0)