Skip to content

Add CompressionStream #1723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Tracked by #159
Symbitic opened this issue Jan 4, 2023 · 37 comments
Open
Tracked by #159

Add CompressionStream #1723

Symbitic opened this issue Jan 4, 2023 · 37 comments
Assignees
Labels
enhancement New feature or request web-api Something that relates to a standard Web API wintercg Web-interoperable Runtimes Community Group compatiblity

Comments

@Symbitic
Copy link

Symbitic commented Jan 4, 2023

What is the problem this feature would solve?

The compress middleware in Hono depends on CompressStream, which isn't implemented by WebKit. By adding it, it would increase the performance of transferring static assets such as CSS and SVG files.

What is the feature you are proposing to solve the problem?

Implement CompressionStream in Bun. That would automatically allow the compress middleware in Hono to work, and it would enable more Bun-optimized frameworks like Elysia to design their own middleware.

What alternatives have you considered?

It might be possible to implement CompressStream in WebKit and use that.

@Symbitic Symbitic added the enhancement New feature or request label Jan 4, 2023
@Jarred-Sumner
Copy link
Collaborator

Yeah we need to do this

WebKit has a CompressionStream/DecompressionStream we could use and uWebSockets (our HTTP server lib) also has builtin support for compression. Neither are wired up yet.

@Electroid Electroid added the web-api Something that relates to a standard Web API label Jan 5, 2023
@Jarred-Sumner
Copy link
Collaborator

Prerequisite 3b25921

@vesamet
Copy link

vesamet commented Feb 26, 2023

Out of curiosity, what is the state of this issue?
(My app really depends on Hono's compression middleware 😅)

@cloudspeech
Copy link

My node app uses DecompressionStream to unpack npm packages 'manually', i.e. without official npm tooling - I would very much like to switch to bun, but this is blocking me ATM.

@marc-barry
Copy link

We just tried to port our proxy from Deno to Bun as sadly Bun doesn't support compression on its own. So we have to use https://hono.dev/middleware/builtin/compress with Bun. Is there another way to handle HTTP compression in Bun?

@niklasgrewe
Copy link

any news about this issue? I also use Hono and want to use there compress middleware

@venkatd
Copy link

venkatd commented Aug 28, 2023

Our backend is unable to run without DecompressionStream, putting in my vote for this!

@tomek-f
Copy link

tomek-f commented Sep 10, 2023

Any news about this issue?

@ewrogers
Copy link

Out of curiosity, what is the state of this issue? (My app really depends on Hono's compression middleware 😅)

+1 for the same reason, though I can disable it for now it would be great to have this soon.

@cloudspeech
Copy link

One could try https://github.com/101arrowz/compression-streams-polyfill in the meantime.

@jimmywarting
Copy link

jimmywarting commented Oct 22, 2023

I wired up my own compression stream polyfill that is based upon zlip instead of using fflate

// @bun

/*! MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
import zlib from 'node:zlib'

// fyi, Byte streams aren't really implemented anywhere yet
// It only exist as a issue: https://github.com/WICG/compression/issues/31

const make = (ctx, handle) => Object.assign(ctx, {
  writable: new WritableStream({
    write: chunk => handle.write(chunk),
    close: () => handle.end()
  }),
  readable: new ReadableStream({
    type: 'bytes',
    start (ctrl) {
      handle.on('data', chunk => ctrl.enqueue(chunk))
      handle.once('end', () => ctrl.close())
    }
  })
})

globalThis.CompressionStream ??= class CompressionStream {
  constructor(format) {
    make(this, format === 'deflate' ? zlib.createDeflate() :
    format === 'gzip' ? zlib.createGzip() : zlib.createDeflateRaw())
  }
}

globalThis.DecompressionStream ??= class DecompressionStream {
  constructor(format) {
    make(this, format === 'deflate' ? zlib.createInflate() :
    format === 'gzip' ? zlib.createGunzip() :
    zlib.createInflateRaw())
  }
}

( this is only needed in Bun - all other env have compression stream right now... )

@javalsai
Copy link

javalsai commented Jan 4, 2024

I think this might be relevant in here, I was doing stuff with gzip streams in bun and I found a weird bug with following code:
import { createGzip } from 'node:zlib'
import { Readable, pipeline } from 'node:stream'

const gzip = createGzip()

pipeline(
    Readable.toWeb(process.stdin),
    gzip,
    process.stdout,
    () => {},
)

Now, you should be able to run the program with echo <some data> | bun/node <path> > /dev/null and they should behave the same way, but in my case I was doing random data and big streams and found out from dd with bs=1K and count=16 up, the program hangs forever, so:

  • dd if=/dev/urandom bs=1K count=15 | bun std-gzip-pipe.js > /dev/null: works in under 0.002 secs on my machine
  • dd if=/dev/urandom bs=1K count=16 | bun std-gzip-pipe.js > /dev/null: hangs forever on bun, node works however

It turns out to be a stdio issue

@sbenzemame
Copy link

Any news about this issue?

@danthegoodman1
Copy link

This is a bit of a blocker for a use case I have for bun. In the meantime I can use third party packages but I hope this is supported soon.

@sunneydev
Copy link

sunneydev commented Feb 3, 2024

Before this issue is resolved you can use https://www.npmjs.com/package/bun-compression. I just ported the compression middleware that Elysia was using for hono.

@codedread
Copy link

Does this bug also cover the DecompressionStream implementation? If so, can someone update the bug title?

@Mehuge
Copy link

Mehuge commented Mar 8, 2024

My deduplication backup [ddb] software uses streams with compression, specifically it .pipe()s to and from a compressor (gzip/gunzip). It operates over http as well as over the file system. Loading an entire file into memory is ofc not an option, so has to use streams.

@danielniccoli
Copy link

It's on the roadmap #159

I, too, hope for a soon implementation. 🙏☺️

@WebReflection
Copy link
Contributor

it looks like Safari has it too https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream/CompressionStream#browser_compatibility ... and so does WebKit https://github.com/WebKit/WebKit/blob/f40dca81c492428dec3f1c977b27ed2e906bbf30/Source/WebCore/Modules/compression/CompressionStream.idl#L32 ... what is stopping this feature to land? 🤔

@nektro nektro self-assigned this Sep 28, 2024
@tiagorangel1

This comment has been minimized.

@WebReflection
Copy link
Contributor

I think @tiagorangel1 meant to say bump to which I agree ... is there at least any ETA to share about this, or what are the main blockers? 🤔

@WebReflection
Copy link
Contributor

To whom it might concern, I've published a ponyfill that bsically patches only Bun https://github.com/ungap/compression-stream.

It's mostly based on this code which works indeed pretty well (at least for my use-case) so thank you @jimmywarting and happy to improve any credits you like in there too, if needed.

I hope this won't be needed in the near future, it just exports back native classes if found in the global context.

@WebReflection
Copy link
Contributor

maybe unnecessary but (imho) worth asking to @Jarred-Sumner: if a polyfill is "that trivial", wouldn't it make sense for Bun to just ship a non-optimized, JS based version, of such polyfill to enable all people dependent on such feature and then, eventually, put in the pipe possible native optimizations to be released? Me, among others, really need this feature which also feels super natural to use in an engine that promotes Reponse style/related patterns in a way that can't provide compression otherwise ... feel free to embed my lib or Jimm's code and let's close this for the time being? 🤔

@vuolter
Copy link

vuolter commented Nov 17, 2024

If anyone needs zstd/brotli/gzip compression in hono I made a plugin that also work with bun: https://github.com/vuolter/hono-compress

@albert-92
Copy link

Any news on this? I don't see it on the roadmap #159 anymore.

@LeulAria

This comment has been minimized.

@WebReflection
Copy link
Contributor

it looks like both CompressionStream and DecompressionStream are now part of the TC55 (recently landed) standard API ... https://min-common-api.proposal.wintercg.org/#api-index

Is there any reason this has not already landed in bun in a way or another?

@WebReflection
Copy link
Contributor

it's awkward nobody is answering around this issue ... and there's no progress whatsoever ... can anyone please provide an ETA, a statement, or something around this issue? Thank you 🙏

@Jarred-Sumner
Copy link
Collaborator

Jarred-Sumner commented Mar 16, 2025 via email

@SohelIslamImran
Copy link

For now, I'm using this polyfill

// compression-polyfill.ts
/**
 * This is a polyfill for the CompressionStream and DecompressionStream.
 * This solves the issue where Drizzle Studio Can't find variable: CompressionStream
 *
 * ![BUG]: ReferenceError: Can't find variable: CompressionStream
 * @see https://github.com/drizzle-team/drizzle-orm/issues/3880
 *
 * Bun doesn't have CompressionStream and DecompressionStream yet
 * @see https://github.com/oven-sh/bun/issues/1723
 */

import zlib from "node:zlib";

class CompressionStream {
  readable;
  writable;
  constructor(format: "deflate" | "deflate-raw" | "gzip") {
    const handle =
      format === "deflate"
        ? zlib.createDeflate()
        : format === "gzip"
          ? zlib.createGzip()
          : zlib.createDeflateRaw();
    this.readable = new ReadableStream({
      start(controller) {
        handle.on("data", (chunk) => controller.enqueue(chunk));
        handle.once("end", () => controller.close());
      },
    });
    this.writable = new WritableStream({
      write: (chunk) => {
        handle.write(chunk);
      },
      close: () => {
        handle.end();
      },
    });
  }
}

globalThis.CompressionStream ??= CompressionStream;
globalThis.DecompressionStream ??= CompressionStream;
import "./compression-polyfill";

@kravetsone
Copy link

We will implement CompressionStream support. Probably not this month.
Potentially next month.

On Sun, Mar 16, 2025 at 10:36 AM Andrea Giammarchi @.***>
wrote:

it's awkward nobody is answering around this issue ... and there's no
progress whatsoever ... can anyone please provide an ETA, a statement, or
something around this issue? Thank you 🙏


Reply to this email directly, view it on GitHub
#1723 (comment), or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAFNGS4WIBXV4NR2UKRDTQT2UWZADAVCNFSM6AAAAAATRK56HSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOMRXGU2TMOJTGA
.
You are receiving this because you were mentioned.Message ID:
@.***>
[image: WebReflection]WebReflection left a comment (#1723)
#1723 (comment)

it's awkward nobody is answering around this issue ... and there's no
progress whatsoever ... can anyone please provide an ETA, a statement, or
something around this issue? Thank you 🙏


Reply to this email directly, view it on GitHub
#1723 (comment), or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAFNGS4WIBXV4NR2UKRDTQT2UWZADAVCNFSM6AAAAAATRK56HSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOMRXGU2TMOJTGA
.
You are receiving this because you were mentioned.Message ID:
@.***>

Why not implement slow polyfill and then fix it?

For now it's hard to inject it for cli's like drizzle studio

@WebReflection
Copy link
Contributor

WebReflection commented Mar 16, 2025

@SohelIslamImran I wrote and published one already #1723 (comment) edit and your decompression feels like it won't work at all

... and ...

@kravetsone I've proposed that too but no answer #1723 (comment)

... still ...

@Jarred-Sumner thanks for that ETA, looking forward to make my poly/ponyfill deprecated ASAP 🙏

@ufwo
Copy link

ufwo commented May 21, 2025

👀

@jimmywarting
Copy link

@SohelIslamImran #1723 (comment)
This is wrong...

globalThis.DecompressionStream ??= CompressionStream;

@SohelIslamImran
Copy link

This is wrong...
globalThis.DecompressionStream ??= CompressionStream;

But working! 👀.. I'm just using this hack for Drizale Studio for just development, not as a production solution. @jimmywarting

@jimmywarting
Copy link

jimmywarting commented May 21, 2025

maybe a better version of my previous code:

// @bun
/*! MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
import zlib from 'node:zlib'
import stream from 'node:stream'

// fyi, Byte streams aren't really implemented anywhere yet
// It only exist as a issue: https://github.com/WICG/compression/issues/31

const make = (ctx, handle) => Object.assign(ctx, {
  readable: new stream.Readable.toWeb(handle),
  writable: new stream.Writable.toWeb(handle),
})

globalThis.CompressionStream ??= class CompressionStream {
  constructor(format) {
    make(this, format === 'deflate' ? zlib.createDeflate() :
    format === 'gzip' ? zlib.createGzip() : zlib.createDeflateRaw())
  }
}

globalThis.DecompressionStream ??= class DecompressionStream {
  constructor(format) {
    make(this, format === 'deflate' ? zlib.createInflate() :
    format === 'gzip' ? zlib.createGunzip() :
    zlib.createInflateRaw())
  }
}

@LeulAria
Copy link

++ the long awaited

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request web-api Something that relates to a standard Web API wintercg Web-interoperable Runtimes Community Group compatiblity
Projects
None yet
Development

No branches or pull requests