@@ -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,7 +25,43 @@ 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
28
+ ``` mjs
29
+ import { createGzip } from ' node:zlib' ;
30
+ import { pipeline } from ' node:stream' ;
31
+ import {
32
+ createReadStream ,
33
+ createWriteStream ,
34
+ } from ' node:fs' ;
35
+
36
+ const gzip = createGzip ();
37
+ const source = createReadStream (' input.txt' );
38
+ const destination = createWriteStream (' input.txt.gz' );
39
+
40
+ pipeline (source, gzip, destination, (err ) => {
41
+ if (err) {
42
+ console .error (' An error occurred:' , err);
43
+ process .exitCode = 1 ;
44
+ }
45
+ });
46
+
47
+ // Or, Promisified
48
+ import { pipeline } from ' node:stream/promises' ;
49
+
50
+ async function do_gzip (input , output ) {
51
+ const gzip = createGzip ();
52
+ const source = createReadStream (input);
53
+ const destination = createWriteStream (output);
54
+ await pipe (source, gzip, destination);
55
+ }
56
+
57
+ do_gzip (' input.txt' , ' input.txt.gz' )
58
+ .catch ((err ) => {
59
+ console .error (' An error occurred:' , err);
60
+ process .exitCode = 1 ;
61
+ });
62
+ ```
63
+
64
+ ``` cjs
25
65
const { createGzip } = require (' node:zlib' );
26
66
const { pipeline } = require (' node:stream' );
27
67
const {
@@ -41,9 +81,7 @@ pipeline(source, gzip, destination, (err) => {
41
81
});
42
82
43
83
// Or, Promisified
44
-
45
- const { promisify } = require (' node:util' );
46
- const pipe = promisify (pipeline);
84
+ const { pipeline } = require (' node:stream/promises' );
47
85
48
86
async function do_gzip (input , output ) {
49
87
const gzip = createGzip ();
@@ -61,7 +99,41 @@ do_gzip('input.txt', 'input.txt.gz')
61
99
62
100
It is also possible to compress or decompress data in a single step:
63
101
64
- ``` js
102
+ ``` mjs
103
+ import { deflate , unzip } from ' node:zlib' ;
104
+
105
+ const input = ' .................................' ;
106
+ deflate (input, (err , buffer ) => {
107
+ if (err) {
108
+ console .error (' An error occurred:' , err);
109
+ process .exitCode = 1 ;
110
+ }
111
+ console .log (buffer .toString (' base64' ));
112
+ });
113
+
114
+ const buffer = Buffer .from (' eJzT0yMAAGTvBe8=' , ' base64' );
115
+ unzip (buffer, (err , buffer ) => {
116
+ if (err) {
117
+ console .error (' An error occurred:' , err);
118
+ process .exitCode = 1 ;
119
+ }
120
+ console .log (buffer .toString ());
121
+ });
122
+
123
+ // Or, Promisified
124
+
125
+ import { promisify } from ' node:util' ;
126
+ const do_unzip = promisify (unzip);
127
+
128
+ do_unzip (buffer)
129
+ .then ((buf ) => console .log (buf .toString ()))
130
+ .catch ((err ) => {
131
+ console .error (' An error occurred:' , err);
132
+ process .exitCode = 1 ;
133
+ });
134
+ ```
135
+
136
+ ``` cjs
65
137
const { deflate , unzip } = require (' node:zlib' );
66
138
67
139
const input = ' .................................' ;
@@ -104,7 +176,18 @@ limitations in some applications.
104
176
Creating and using a large number of zlib objects simultaneously can cause
105
177
significant memory fragmentation.
106
178
107
- ``` js
179
+ ``` mjs
180
+ import zlib from ' node:zlib' ;
181
+
182
+ const payload = Buffer .from (' This is some data' );
183
+
184
+ // WARNING: DO NOT DO THIS!
185
+ for (let i = 0 ; i < 30000 ; ++ i) {
186
+ zlib .deflate (payload, (err , buffer ) => {});
187
+ }
188
+ ```
189
+
190
+ ``` cjs
108
191
const zlib = require (' node:zlib' );
109
192
110
193
const payload = Buffer .from (' This is some data' );
@@ -138,7 +221,46 @@ Using `zlib` encoding can be expensive, and the results ought to be cached.
138
221
See [ Memory usage tuning] [ ] for more information on the speed/memory/compression
139
222
tradeoffs involved in ` zlib ` usage.
140
223
141
- ``` js
224
+ ``` mjs
225
+ // Client request example
226
+ import zlib from ' node:zlib' ;
227
+ import http from ' node:http' ;
228
+ import fs from ' node:fs' ;
229
+ import { pipeline } from ' node:stream' ;
230
+
231
+ const request = http .get ({ host: ' example.com' ,
232
+ path: ' /' ,
233
+ port: 80 ,
234
+ headers: { ' Accept-Encoding' : ' br,gzip,deflate' } });
235
+ request .on (' response' , (response ) => {
236
+ const output = fs .createWriteStream (' example.com_index.html' );
237
+
238
+ const onError = (err ) => {
239
+ if (err) {
240
+ console .error (' An error occurred:' , err);
241
+ process .exitCode = 1 ;
242
+ }
243
+ };
244
+
245
+ switch (response .headers [' content-encoding' ]) {
246
+ case ' br' :
247
+ pipeline (response, zlib .createBrotliDecompress (), output, onError);
248
+ break ;
249
+ // Or, just use zlib.createUnzip() to handle both of the following cases:
250
+ case ' gzip' :
251
+ pipeline (response, zlib .createGunzip (), output, onError);
252
+ break ;
253
+ case ' deflate' :
254
+ pipeline (response, zlib .createInflate (), output, onError);
255
+ break ;
256
+ default :
257
+ pipeline (response, output, onError);
258
+ break ;
259
+ }
260
+ });
261
+ ```
262
+
263
+ ``` cjs
142
264
// Client request example
143
265
const zlib = require (' node:zlib' );
144
266
const http = require (' node:http' );
@@ -177,7 +299,52 @@ request.on('response', (response) => {
177
299
});
178
300
```
179
301
180
- ``` js
302
+ ``` mjs
303
+ // server example
304
+ // Running a gzip operation on every request is quite expensive.
305
+ // It would be much more efficient to cache the compressed buffer.
306
+ import zlib from ' node:zlib' ;
307
+ import http from ' node:http' ;
308
+ import fs from ' node:fs' ;
309
+ import { pipeline } from ' node:stream' ;
310
+
311
+ http .createServer ((request , response ) => {
312
+ const raw = fs .createReadStream (' index.html' );
313
+ // Store both a compressed and an uncompressed version of the resource.
314
+ response .setHeader (' Vary' , ' Accept-Encoding' );
315
+ const acceptEncoding = request .headers [' accept-encoding' ] || ' ' ;
316
+
317
+ const onError = (err ) => {
318
+ if (err) {
319
+ // If an error occurs, there's not much we can do because
320
+ // the server has already sent the 200 response code and
321
+ // some amount of data has already been sent to the client.
322
+ // The best we can do is terminate the response immediately
323
+ // and log the error.
324
+ response .end ();
325
+ console .error (' An error occurred:' , err);
326
+ }
327
+ };
328
+
329
+ // Note: This is not a conformant accept-encoding parser.
330
+ // See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
331
+ if (/ \b deflate\b / .test (acceptEncoding)) {
332
+ response .writeHead (200 , { ' Content-Encoding' : ' deflate' });
333
+ pipeline (raw, zlib .createDeflate (), response, onError);
334
+ } else if (/ \b gzip\b / .test (acceptEncoding)) {
335
+ response .writeHead (200 , { ' Content-Encoding' : ' gzip' });
336
+ pipeline (raw, zlib .createGzip (), response, onError);
337
+ } else if (/ \b br\b / .test (acceptEncoding)) {
338
+ response .writeHead (200 , { ' Content-Encoding' : ' br' });
339
+ pipeline (raw, zlib .createBrotliCompress (), response, onError);
340
+ } else {
341
+ response .writeHead (200 , {});
342
+ pipeline (raw, response, onError);
343
+ }
344
+ }).listen (1337 );
345
+ ```
346
+
347
+ ``` cjs
181
348
// server example
182
349
// Running a gzip operation on every request is quite expensive.
183
350
// It would be much more efficient to cache the compressed buffer.
@@ -315,7 +482,43 @@ quality, but can be useful when data needs to be available as soon as possible.
315
482
In the following example, ` flush() ` is used to write a compressed partial
316
483
HTTP response to the client:
317
484
318
- ``` js
485
+ ``` mjs
486
+ import zlib from ' node:zlib;
487
+ import http from ' node:http;
488
+ import { pipeline } from ' node:stream;
489
+
490
+ http.createServer((request, response) => {
491
+ // For the sake of simplicity, the Accept-Encoding checks are omitted.
492
+ response.writeHead(200, { ' content-encoding' : ' gzip' });
493
+ const output = zlib.createGzip();
494
+ let i;
495
+
496
+ pipeline(output, response, (err) => {
497
+ if (err) {
498
+ // If an error occurs, there' s not much we can do because
499
+ // the server has already sent the 200 response code and
500
+ // some amount of data has already been sent to the client.
501
+ // The best we can do is terminate the response immediately
502
+ // and log the error.
503
+ clearInterval (i);
504
+ response .end ();
505
+ console .error (' An error occurred:' , err);
506
+ }
507
+ });
508
+
509
+ i = setInterval (() => {
510
+ output .write (` The current time is ${ Date ()} \n ` , () => {
511
+ // The data has been passed to zlib, but the compression algorithm may
512
+ // have decided to buffer the data for more efficient compression.
513
+ // Calling .flush() will make the data available as soon as the client
514
+ // is ready to receive it.
515
+ output .flush ();
516
+ });
517
+ }, 1000 );
518
+ }).listen (1337 );
519
+ ```
520
+
521
+ ``` cjs
319
522
const zlib = require (' node:zlib' );
320
523
const http = require (' node:http' );
321
524
const { pipeline } = require (' node:stream' );
0 commit comments