@@ -11,7 +11,11 @@ Gzip, Deflate/Inflate, and Brotli.
11
11
12
12
To access it:
13
13
14
- ``` js
14
+ ``` mjs
15
+ import os from ' node:zlib' ;
16
+ ```
17
+
18
+ ``` cjs
15
19
const zlib = require (' node:zlib' );
16
20
```
17
21
@@ -21,13 +25,35 @@ Compressing or decompressing a stream (such as a file) can be accomplished by
21
25
piping the source stream through a ` zlib ` ` Transform ` stream into a destination
22
26
stream:
23
27
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
27
50
const {
28
51
createReadStream ,
29
52
createWriteStream ,
30
53
} = require (' node:fs' );
54
+ const process = require (' node:process' );
55
+ const { createGzip } = require (' node:zlib' );
56
+ const { pipeline } = require (' node:stream' );
31
57
32
58
const gzip = createGzip ();
33
59
const source = createReadStream (' input.txt' );
@@ -39,17 +65,43 @@ pipeline(source, gzip, destination, (err) => {
39
65
process .exitCode = 1 ;
40
66
}
41
67
});
68
+ ```
42
69
43
- // Or, Promisified
70
+ Or, using the promise ` pipeline ` API:
44
71
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 pipeline (source, gzip, destination);
86
+ }
87
+
88
+ await do_gzip (' input.txt' , ' input.txt.gz' );
89
+ ```
90
+
91
+ ``` cjs
92
+ const {
93
+ createReadStream ,
94
+ createWriteStream ,
95
+ } = require (' node:fs' );
96
+ const process = require (' node:process' );
97
+ const { createGzip } = require (' node:zlib' );
98
+ const { pipeline } = require (' node:stream/promises' );
47
99
48
100
async function do_gzip (input , output ) {
49
101
const gzip = createGzip ();
50
102
const source = createReadStream (input);
51
103
const destination = createWriteStream (output);
52
- await pipe (source, gzip, destination);
104
+ await pipeline (source, gzip, destination);
53
105
}
54
106
55
107
do_gzip (' input.txt' , ' input.txt.gz' )
@@ -61,7 +113,39 @@ do_gzip('input.txt', 'input.txt.gz')
61
113
62
114
It is also possible to compress or decompress data in a single step:
63
115
64
- ``` js
116
+ ``` mjs
117
+ import process from ' node:process' ;
118
+ import { Buffer } from ' node:buffer' ;
119
+ import { deflate , unzip } from ' node:zlib' ;
120
+
121
+ const input = ' .................................' ;
122
+ deflate (input, (err , buffer ) => {
123
+ if (err) {
124
+ console .error (' An error occurred:' , err);
125
+ process .exitCode = 1 ;
126
+ }
127
+ console .log (buffer .toString (' base64' ));
128
+ });
129
+
130
+ const buffer = Buffer .from (' eJzT0yMAAGTvBe8=' , ' base64' );
131
+ unzip (buffer, (err , buffer ) => {
132
+ if (err) {
133
+ console .error (' An error occurred:' , err);
134
+ process .exitCode = 1 ;
135
+ }
136
+ console .log (buffer .toString ());
137
+ });
138
+
139
+ // Or, Promisified
140
+
141
+ import { promisify } from ' node:util' ;
142
+ const do_unzip = promisify (unzip);
143
+
144
+ const unzippedBuffer = await do_unzip (buffer);
145
+ console .log (unzippedBuffer .toString ());
146
+ ```
147
+
148
+ ``` cjs
65
149
const { deflate , unzip } = require (' node:zlib' );
66
150
67
151
const input = ' .................................' ;
@@ -104,7 +188,19 @@ limitations in some applications.
104
188
Creating and using a large number of zlib objects simultaneously can cause
105
189
significant memory fragmentation.
106
190
107
- ``` js
191
+ ``` mjs
192
+ import zlib from ' node:zlib' ;
193
+ import { Buffer } from ' node:buffer' ;
194
+
195
+ const payload = Buffer .from (' This is some data' );
196
+
197
+ // WARNING: DO NOT DO THIS!
198
+ for (let i = 0 ; i < 30000 ; ++ i) {
199
+ zlib .deflate (payload, (err , buffer ) => {});
200
+ }
201
+ ```
202
+
203
+ ``` cjs
108
204
const zlib = require (' node:zlib' );
109
205
110
206
const payload = Buffer .from (' This is some data' );
@@ -138,7 +234,47 @@ Using `zlib` encoding can be expensive, and the results ought to be cached.
138
234
See [ Memory usage tuning] [ ] for more information on the speed/memory/compression
139
235
tradeoffs involved in ` zlib ` usage.
140
236
141
- ``` js
237
+ ``` mjs
238
+ // Client request example
239
+ import fs from ' node:fs' ;
240
+ import zlib from ' node:zlib' ;
241
+ import http from ' node:http' ;
242
+ import process from ' node:process' ;
243
+ import { pipeline } from ' node:stream' ;
244
+
245
+ const request = http .get ({ host: ' example.com' ,
246
+ path: ' /' ,
247
+ port: 80 ,
248
+ headers: { ' Accept-Encoding' : ' br,gzip,deflate' } });
249
+ request .on (' response' , (response ) => {
250
+ const output = fs .createWriteStream (' example.com_index.html' );
251
+
252
+ const onError = (err ) => {
253
+ if (err) {
254
+ console .error (' An error occurred:' , err);
255
+ process .exitCode = 1 ;
256
+ }
257
+ };
258
+
259
+ switch (response .headers [' content-encoding' ]) {
260
+ case ' br' :
261
+ pipeline (response, zlib .createBrotliDecompress (), output, onError);
262
+ break ;
263
+ // Or, just use zlib.createUnzip() to handle both of the following cases:
264
+ case ' gzip' :
265
+ pipeline (response, zlib .createGunzip (), output, onError);
266
+ break ;
267
+ case ' deflate' :
268
+ pipeline (response, zlib .createInflate (), output, onError);
269
+ break ;
270
+ default :
271
+ pipeline (response, output, onError);
272
+ break ;
273
+ }
274
+ });
275
+ ```
276
+
277
+ ``` cjs
142
278
// Client request example
143
279
const zlib = require (' node:zlib' );
144
280
const http = require (' node:http' );
@@ -177,7 +313,52 @@ request.on('response', (response) => {
177
313
});
178
314
```
179
315
180
- ``` js
316
+ ``` mjs
317
+ // server example
318
+ // Running a gzip operation on every request is quite expensive.
319
+ // It would be much more efficient to cache the compressed buffer.
320
+ import zlib from ' node:zlib' ;
321
+ import http from ' node:http' ;
322
+ import fs from ' node:fs' ;
323
+ import { pipeline } from ' node:stream' ;
324
+
325
+ http .createServer ((request , response ) => {
326
+ const raw = fs .createReadStream (' index.html' );
327
+ // Store both a compressed and an uncompressed version of the resource.
328
+ response .setHeader (' Vary' , ' Accept-Encoding' );
329
+ const acceptEncoding = request .headers [' accept-encoding' ] || ' ' ;
330
+
331
+ const onError = (err ) => {
332
+ if (err) {
333
+ // If an error occurs, there's not much we can do because
334
+ // the server has already sent the 200 response code and
335
+ // some amount of data has already been sent to the client.
336
+ // The best we can do is terminate the response immediately
337
+ // and log the error.
338
+ response .end ();
339
+ console .error (' An error occurred:' , err);
340
+ }
341
+ };
342
+
343
+ // Note: This is not a conformant accept-encoding parser.
344
+ // See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
345
+ if (/ \b deflate\b / .test (acceptEncoding)) {
346
+ response .writeHead (200 , { ' Content-Encoding' : ' deflate' });
347
+ pipeline (raw, zlib .createDeflate (), response, onError);
348
+ } else if (/ \b gzip\b / .test (acceptEncoding)) {
349
+ response .writeHead (200 , { ' Content-Encoding' : ' gzip' });
350
+ pipeline (raw, zlib .createGzip (), response, onError);
351
+ } else if (/ \b br\b / .test (acceptEncoding)) {
352
+ response .writeHead (200 , { ' Content-Encoding' : ' br' });
353
+ pipeline (raw, zlib .createBrotliCompress (), response, onError);
354
+ } else {
355
+ response .writeHead (200 , {});
356
+ pipeline (raw, response, onError);
357
+ }
358
+ }).listen (1337 );
359
+ ```
360
+
361
+ ``` cjs
181
362
// server example
182
363
// Running a gzip operation on every request is quite expensive.
183
364
// It would be much more efficient to cache the compressed buffer.
@@ -315,7 +496,43 @@ quality, but can be useful when data needs to be available as soon as possible.
315
496
In the following example, ` flush() ` is used to write a compressed partial
316
497
HTTP response to the client:
317
498
318
- ``` js
499
+ ``` mjs
500
+ import zlib from ' node:zlib' ;
501
+ import http from ' node:http' ;
502
+ import { pipeline } from ' node:stream' ;
503
+
504
+ http .createServer ((request , response ) => {
505
+ // For the sake of simplicity, the Accept-Encoding checks are omitted.
506
+ response .writeHead (200 , { ' content-encoding' : ' gzip' });
507
+ const output = zlib .createGzip ();
508
+ let i;
509
+
510
+ pipeline (output, response, (err ) => {
511
+ if (err) {
512
+ // If an error occurs, there's not much we can do because
513
+ // the server has already sent the 200 response code and
514
+ // some amount of data has already been sent to the client.
515
+ // The best we can do is terminate the response immediately
516
+ // and log the error.
517
+ clearInterval (i);
518
+ response .end ();
519
+ console .error (' An error occurred:' , err);
520
+ }
521
+ });
522
+
523
+ i = setInterval (() => {
524
+ output .write (` The current time is ${ Date ()} \n ` , () => {
525
+ // The data has been passed to zlib, but the compression algorithm may
526
+ // have decided to buffer the data for more efficient compression.
527
+ // Calling .flush() will make the data available as soon as the client
528
+ // is ready to receive it.
529
+ output .flush ();
530
+ });
531
+ }, 1000 );
532
+ }).listen (1337 );
533
+ ```
534
+
535
+ ``` cjs
319
536
const zlib = require (' node:zlib' );
320
537
const http = require (' node:http' );
321
538
const { pipeline } = require (' node:stream' );
0 commit comments