refactor: move request-compression out of codegen, avoid some buffering (#118)
This commit is contained in:
47
pkg/gzip/pipe.go
Normal file
47
pkg/gzip/pipe.go
Normal file
@ -0,0 +1,47 @@
|
||||
package gzip
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"io"
|
||||
)
|
||||
|
||||
var _ io.ReadCloser = (*gzipPipe)(nil)
|
||||
|
||||
type gzipPipe struct {
|
||||
underlying io.ReadCloser
|
||||
pipeOut io.ReadCloser
|
||||
}
|
||||
|
||||
// NewGzipPipe returns an io.ReadCloser that wraps an input data stream,
|
||||
// applying gzip compression to the underlying data on Read and closing the
|
||||
// underlying data on Close.
|
||||
func NewGzipPipe(in io.ReadCloser) *gzipPipe {
|
||||
pr, pw := io.Pipe()
|
||||
gw := gzip.NewWriter(pw)
|
||||
|
||||
go func() {
|
||||
_, err := io.Copy(gw, in)
|
||||
gw.Close()
|
||||
if err != nil {
|
||||
pw.CloseWithError(err)
|
||||
} else {
|
||||
pw.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
return &gzipPipe{underlying: in, pipeOut: pr}
|
||||
}
|
||||
|
||||
func (gzp gzipPipe) Read(p []byte) (int, error) {
|
||||
return gzp.pipeOut.Read(p)
|
||||
}
|
||||
|
||||
func (gzp gzipPipe) Close() error {
|
||||
if err := gzp.pipeOut.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gzp.underlying.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
66
pkg/gzip/pipe_test.go
Normal file
66
pkg/gzip/pipe_test.go
Normal file
@ -0,0 +1,66 @@
|
||||
package gzip_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
pgzip "github.com/influxdata/influx-cli/v2/pkg/gzip"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGzipPipe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := strings.Repeat("Data data I'm some data\n", 1024)
|
||||
reader := strings.NewReader(data)
|
||||
pipe := pgzip.NewGzipPipe(ioutil.NopCloser(reader))
|
||||
defer pipe.Close()
|
||||
gunzip, err := gzip.NewReader(pipe)
|
||||
require.NoError(t, err)
|
||||
defer gunzip.Close()
|
||||
|
||||
out := bytes.Buffer{}
|
||||
_, err = io.Copy(&out, gunzip)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, data, out.String())
|
||||
})
|
||||
|
||||
t.Run("error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader := &failingReader{n: 3, err: errors.New("I BROKE")}
|
||||
pipe := pgzip.NewGzipPipe(ioutil.NopCloser(reader))
|
||||
defer pipe.Close()
|
||||
gunzip, err := gzip.NewReader(pipe)
|
||||
require.NoError(t, err)
|
||||
defer gunzip.Close()
|
||||
|
||||
out := bytes.Buffer{}
|
||||
_, err = io.Copy(&out, gunzip)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, reader.err, err)
|
||||
})
|
||||
}
|
||||
|
||||
type failingReader struct {
|
||||
n int
|
||||
err error
|
||||
}
|
||||
|
||||
func (frc *failingReader) Read(p []byte) (int, error) {
|
||||
if frc.n <= 0 {
|
||||
return 0, frc.err
|
||||
}
|
||||
frc.n--
|
||||
p[0] = 'a'
|
||||
return 1, nil
|
||||
}
|
Reference in New Issue
Block a user