UNPKG

h3-fast-compression

Version:

Adds compression to h3 request (brotli, gzip, deflate)

86 lines (78 loc) 3.31 kB
'use strict'; const node_util = require('node:util'); const zlib = require('node:zlib'); const h3 = require('h3'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } const zlib__default = /*#__PURE__*/_interopDefaultCompat(zlib); const MINIMUM_COMPRESSION_INPUT_SIZE = 1024; function getAnyCompression(event) { const encoding = h3.getRequestHeader(event, "accept-encoding"); if (encoding?.includes("br")) return "br"; if (encoding?.includes("gzip")) return "gzip"; if (encoding?.includes("deflate")) return "deflate"; return void 0; } async function compress(event, response, method) { const acceptEncoding = h3.getRequestHeader(event, "accept-encoding")?.includes(method); const contentEncoding = h3.getResponseHeader(event, "content-encoding"); const responseBody = response.body; const shouldCompress = typeof responseBody === "string" && !contentEncoding && responseBody.length >= MINIMUM_COMPRESSION_INPUT_SIZE && acceptEncoding; if (shouldCompress) { h3.setResponseHeader(event, "Content-Encoding", method); const compressed = await (method === "br" ? node_util.promisify(zlib__default.brotliCompress)(responseBody, { params: { [zlib__default.constants.BROTLI_PARAM_MODE]: zlib__default.constants.BROTLI_MODE_TEXT, // 4 is generally more appropriate for dynamic content, faster than gzip and better compression ratio [zlib__default.constants.BROTLI_PARAM_QUALITY]: 4 } }) : node_util.promisify(zlib__default[method])(responseBody)); void h3.send(event, compressed); } } async function compressStream(event, response, method) { const stream = new Response(response.body).body; const acceptsEncoding = h3.getRequestHeader(event, "accept-encoding")?.includes( method ); if (acceptsEncoding) { h3.setResponseHeader(event, "Content-Encoding", method); response.body = stream.pipeThrough(new CompressionStream(method)); } else { response.body = stream; } } async function useGZipCompression(event, response) { await compress(event, response, "gzip"); } async function useDeflateCompression(event, response) { await compress(event, response, "deflate"); } async function useBrotliCompression(event, response) { await compress(event, response, "br"); } async function useCompression(event, response) { const compression = getAnyCompression(event); if (compression) await compress(event, response, compression); } async function useGZipCompressionStream(event, response) { await compressStream(event, response, "gzip"); } async function useDeflateCompressionStream(event, response) { await compressStream(event, response, "deflate"); } async function useCompressionStream(event, response) { const compression = getAnyCompression(event); if (compression && compression !== "br") await compressStream(event, response, compression); } exports.useBrotliCompression = useBrotliCompression; exports.useCompression = useCompression; exports.useCompressionStream = useCompressionStream; exports.useDeflateCompression = useDeflateCompression; exports.useDeflateCompressionStream = useDeflateCompressionStream; exports.useGZipCompression = useGZipCompression; exports.useGZipCompressionStream = useGZipCompressionStream;