| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -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 (/\bdeflate\b/.test(acceptEncoding)) { | ||
| 346 | + response.writeHead(200, { 'Content-Encoding': 'deflate' }); | ||
| 347 | + pipeline(raw, zlib.createDeflate(), response, onError); | ||
| 348 | + } else if (/\bgzip\b/.test(acceptEncoding)) { | ||
| 349 | + response.writeHead(200, { 'Content-Encoding': 'gzip' }); | ||
| 350 | + pipeline(raw, zlib.createGzip(), response, onError); | ||
| 351 | + } else if (/\bbr\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'); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments