@@ -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,7 +25,43 @@ 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
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
2565const { createGzip } = require (' node:zlib' );
2666const { pipeline } = require (' node:stream' );
2767const {
@@ -41,9 +81,7 @@ pipeline(source, gzip, destination, (err) => {
4181});
4282
4383// Or, Promisified
44-
45- const { promisify } = require (' node:util' );
46- const pipe = promisify (pipeline);
84+ const { pipeline } = require (' node:stream/promises' );
4785
4886async function do_gzip (input , output ) {
4987 const gzip = createGzip ();
@@ -61,7 +99,41 @@ do_gzip('input.txt', 'input.txt.gz')
6199
62100It is also possible to compress or decompress data in a single step:
63101
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
65137const { deflate , unzip } = require (' node:zlib' );
66138
67139const input = ' .................................' ;
@@ -104,7 +176,18 @@ limitations in some applications.
104176Creating and using a large number of zlib objects simultaneously can cause
105177significant memory fragmentation.
106178
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
108191const zlib = require (' node:zlib' );
109192
110193const payload = Buffer .from (' This is some data' );
@@ -138,7 +221,46 @@ Using `zlib` encoding can be expensive, and the results ought to be cached.
138221See [ Memory usage tuning] [ ] for more information on the speed/memory/compression
139222tradeoffs involved in ` zlib ` usage.
140223
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
142264// Client request example
143265const zlib = require (' node:zlib' );
144266const http = require (' node:http' );
@@ -177,7 +299,52 @@ request.on('response', (response) => {
177299});
178300```
179301
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
181348// server example
182349// Running a gzip operation on every request is quite expensive.
183350// 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.
315482In the following example, ` flush() ` is used to write a compressed partial
316483HTTP response to the client:
317484
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
319522const zlib = require (' node:zlib' );
320523const http = require (' node:http' );
321524const { pipeline } = require (' node:stream' );
0 commit comments