@@ -11,7 +11,11 @@ Gzip, Deflate/Inflate, and Brotli.
1111
1212To access it:
1313
14- ``` js
14+ ``` mjs
15+ import os from ' node:zlib' ;
16+ ```
17+
18+ ``` cjs
1519const zlib = require (' node:zlib' );
1620```
1721
@@ -21,13 +25,35 @@ Compressing or decompressing a stream (such as a file) can be accomplished by
2125piping the source stream through a ` zlib ` ` Transform ` stream into a destination
2226stream:
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
2750const {
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
3258const gzip = createGzip ();
3359const 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
48104async function do_gzip (input , output ) {
49105 const gzip = createGzip ();
@@ -61,7 +117,43 @@ do_gzip('input.txt', 'input.txt.gz')
61117
62118It 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
65157const { deflate , unzip } = require (' node:zlib' );
66158
67159const input = ' .................................' ;
@@ -104,7 +196,19 @@ limitations in some applications.
104196Creating and using a large number of zlib objects simultaneously can cause
105197significant 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
108212const zlib = require (' node:zlib' );
109213
110214const payload = Buffer .from (' This is some data' );
@@ -138,7 +242,47 @@ Using `zlib` encoding can be expensive, and the results ought to be cached.
138242See [ Memory usage tuning] [ ] for more information on the speed/memory/compression
139243tradeoffs 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
143287const zlib = require (' node:zlib' );
144288const 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 (/ \b deflate\b / .test (acceptEncoding)) {
354+ response .writeHead (200 , { ' Content-Encoding' : ' deflate' });
355+ pipeline (raw, zlib .createDeflate (), response, onError);
356+ } else if (/ \b gzip\b / .test (acceptEncoding)) {
357+ response .writeHead (200 , { ' Content-Encoding' : ' gzip' });
358+ pipeline (raw, zlib .createGzip (), response, onError);
359+ } else if (/ \b br\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.
315504In the following example, ` flush() ` is used to write a compressed partial
316505HTTP 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
319544const zlib = require (' node:zlib' );
320545const http = require (' node:http' );
321546const { pipeline } = require (' node:stream' );
0 commit comments