Skip to content
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

Fix deflate algorithm to adhere to RFC 1950 #824

Merged
merged 5 commits into from
Mar 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions internal/compression/deflate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,49 @@
package compression

import (
"compress/flate"
"errors"
"compress/zlib"
"io"

"connectrpc.com/connect"
)

// deflateDecompressor is a thin wrapper around a flate Reader.
// deflateDecompressor is a thin wrapper around a zlib Reader. Note that due to
// an unfortunate misnomer with the RFC 2616 specification, HTTP deflate is
// actually RFC 1950 with zlib headers, rather than RFC 1951. gRPC uses the same
// nomenclature.
type deflateDecompressor struct {
reader io.ReadCloser
}

func (c *deflateDecompressor) Read(bytes []byte) (int, error) {
if c.reader == nil {
return 0, io.EOF
}
return c.reader.Read(bytes)
}
func (c *deflateDecompressor) Reset(rdr io.Reader) error {
resetter, ok := c.reader.(flate.Resetter)
if !ok {
// This should never happen as the returned type from flate should always
// implement Resetter, but the check is here as a safeguard just in case.
// This error would be a very exceptional / unexpected occurrence.
return errors.New("deflate reader is not able to be used as a resetter")
reader, err := zlib.NewReader(rdr)
if err != nil {
c.reader = &errorDecompressor{err: err}
return err
}
// Mimics NewReader internal logic, which initializes the internal dict to nil
return resetter.Reset(rdr, nil)
c.reader = reader
return nil
}
func (c *deflateDecompressor) Close() error {
if c.reader == nil {
return nil
}
return c.reader.Close()
}

// NewDeflateDecompressor returns a new deflate Decompressor.
func NewDeflateDecompressor() connect.Decompressor {
return &deflateDecompressor{
reader: flate.NewReader(nil),
}
return &deflateDecompressor{}
jchadwick-buf marked this conversation as resolved.
Show resolved Hide resolved
}

// NewDeflateCompressor returns a new deflate Compressor.
func NewDeflateCompressor() connect.Compressor {
// Construct a new flate Writer with default compression level
w, err := flate.NewWriter(nil, 1)
if err != nil {
return &errorCompressor{err: err}
}
return w
// Construct a new zlib Writer with default compression level
return zlib.NewWriter(nil)
}
Loading