Visitar URL original
Brotli compression not working · Issue #868 · go-chi/chi · GitHub
Skip to content

Brotli compression not working #868

Closed

Description

@mateors
import brotli_enc "gopkg.in/kothar/brotli-go.v0/enc"

compressor := middleware.NewCompressor(5, "text/html")
compressor.SetEncoder("br", func(w http.ResponseWriter, level int) io.Writer {
  params := brotli_enc.NewBrotliParams()
  params.SetQuality(level)
  return brotli_enc.NewBrotliWriter(params, w)
})

the above code shows error, but following seems working but compression not working what's wrong?

	r := chi.NewRouter() //chi.NewMux()
	//r.Use(middleware.Logger)

	compressor := middleware.NewCompressor(5, "/*") //"/*"
	compressor.SetEncoder("br", func(w io.Writer, level int) io.Writer {
		params := brotli_enc.NewBrotliParams()
		params.SetQuality(level)
		return brotli_enc.NewBrotliWriter(params, w)
	})
	r.Use(compressor.Handler) //

Activity

  1. pscheid92 commented on Feb 7, 2026

    @pscheid92

    First Error

    compressor.SetEncoder("br", func(w http.ResponseWriter, level int) io.Writer {

    The SetEncoder method expects an EncoderFunc, which has the signature func(w io.Writer, level int) io.Writer. Using http.ResponseWriter as the first parameter won't compile because Go requires exact type matches in function signatures, even though http.ResponseWriter implements io.Writer. The fix is to change http.ResponseWriter to io.Writer:

    compressor.SetEncoder("br", func(w io.Writer, level int) io.Writer {
        params := brotli_enc.NewBrotliParams()
        params.SetQuality(level)
        return brotli_enc.NewBrotliWriter(params, w)
    })

    Second Error

    The encoder setup is correct here, but the issue is NewCompressor(5, "/*"). The "/*" pattern is parsed by stripping the trailing /*, which leaves an empty string as the wildcard key. When a response comes in with e.g. Content-Type: text/html, the compressor tries to match the prefix "text" against the stored wildcards. But only "" is stored, so nothing ever matches and compression is silently skipped.

    Unfortunately, there's no way to express "compress all content types" with a single wildcard pattern right now:

    • "/*" silently produces a key that never matches (this bug)
    • "*/*" panics because * before /* is rejected by validation

    Workaround: Use explicit category wildcards to cover the types you need:

    compressor := middleware.NewCompressor(5, "text/*", "application/*")

    Or omit the types argument entirely to use the built-in defaults (which cover the 10 most common compressible types like text/html, application/json, text/css, etc.):

    compressor := middleware.NewCompressor(5)

    Note that the defaults don't match all content types. Types like image/png or application/octet-stream are excluded, which is generally desirable since those are already compressed or don't benefit from compression.


    If this matter has already been resolved, please close your issue. This helps the maintainers to have a good overview.

  2. happysnaker commented on Jul 1, 2026

    @happysnaker
    Contributor

    I took a pass at this as an implementation fix.

    The encoder callback signature issue is already covered by the current docs/example types, but there is also a real behavior bug in the wildcard path: NewCompressor(5, "/*") currently stores an empty wildcard key and then never matches it during Content-Type checks, so the intended all-types wildcard silently compresses nothing.

    I am preparing a small patch that makes the empty wildcard key behave as an actual “match any top-level media type” sentinel and adds regression coverage for both application/* and text/* responses.

  3. VojtechVitek commented on Aug 20, 2026

    @VojtechVitek
    Contributor

    Fixed in #1156.

    The "/*" pattern never actually worked -- it passed validation but stored an empty wildcard key that never matched any Content-Type, so it silently compressed nothing.

    I decided not to turn it into a catch-all. Compressing every response is a footgun: it burns CPU recompressing already-compressed types (zip, jpeg, png, video) for no gain. So NewCompressor now panics on "/*" and "*/*" at startup -- a misconfiguration fails loudly instead of silently shipping uncompressed responses.

    I want users to be explicit about what they compress:

    middleware.NewCompressor(5, "text/html", "application/*")
    
    // or use the curated defaults
    middleware.NewCompressor(5)

    The SetEncoder signature error from the original report was already answered above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions