h3-compression
Version:
Adds compression to h3 request (brotli, gzip, deflate)
67 lines (62 loc) • 2.35 kB
JavaScript
import { promisify } from 'node:util';
import zlib from 'node:zlib';
import { Buffer } from 'node:buffer';
import { getRequestHeader, setResponseHeader, send } from 'h3';
function getAnyCompression(event) {
const encoding = 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 compression = promisify(zlib[method === "br" ? "brotliCompress" : method]);
const acceptsEncoding = getRequestHeader(event, "accept-encoding")?.includes(
method
);
if (acceptsEncoding && typeof response.body === "string") {
setResponseHeader(event, "Content-Encoding", method);
send(event, await compression(Buffer.from(response.body)));
}
}
async function compressStream(event, response, method) {
const stream = new Response(response.body).body;
const acceptsEncoding = getRequestHeader(event, "accept-encoding")?.includes(
method
);
if (acceptsEncoding) {
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);
}
export { useBrotliCompression, useCompression, useCompressionStream, useDeflateCompression, useDeflateCompressionStream, useGZipCompression, useGZipCompressionStream };