forked from TrueCloudLab/rclone
lib/readers: add NoCloser to stop upgrades from io.Reader to io.ReadCloser
This commit is contained in:
parent
73e010aff9
commit
ce3340621f
2 changed files with 73 additions and 0 deletions
29
lib/readers/noclose.go
Normal file
29
lib/readers/noclose.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package readers
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// noClose is used to wrap an io.Reader to stop it being upgraded
|
||||||
|
type noClose struct {
|
||||||
|
in io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read implements io.Closer by passing it straight on
|
||||||
|
func (nc noClose) Read(p []byte) (n int, err error) {
|
||||||
|
return nc.in.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoCloser makes sure that the io.Reader passed in can't upgraded to
|
||||||
|
// an io.Closer.
|
||||||
|
//
|
||||||
|
// This is for use with http.NewRequest to make sure the body doesn't
|
||||||
|
// get upgraded to an io.Closer and the body closed unexpectedly.
|
||||||
|
func NoCloser(in io.Reader) io.Reader {
|
||||||
|
if in == nil {
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
// if in doesn't implement io.Closer, just return it
|
||||||
|
if _, canClose := in.(io.Closer); !canClose {
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
return noClose{in: in}
|
||||||
|
}
|
44
lib/readers/noclose_test.go
Normal file
44
lib/readers/noclose_test.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package readers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errRead = errors.New("read error")
|
||||||
|
|
||||||
|
type readOnly struct{}
|
||||||
|
|
||||||
|
func (readOnly) Read(p []byte) (n int, err error) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
type readClose struct{}
|
||||||
|
|
||||||
|
func (readClose) Read(p []byte) (n int, err error) {
|
||||||
|
return 0, errRead
|
||||||
|
}
|
||||||
|
|
||||||
|
func (readClose) Close() (err error) {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoCloser(t *testing.T) {
|
||||||
|
assert.Equal(t, nil, NoCloser(nil))
|
||||||
|
|
||||||
|
ro := readOnly{}
|
||||||
|
assert.Equal(t, ro, NoCloser(ro))
|
||||||
|
|
||||||
|
rc := readClose{}
|
||||||
|
nc := NoCloser(rc)
|
||||||
|
assert.NotEqual(t, nc, rc)
|
||||||
|
|
||||||
|
_, hasClose := nc.(io.Closer)
|
||||||
|
assert.False(t, hasClose)
|
||||||
|
|
||||||
|
_, err := nc.Read(nil)
|
||||||
|
assert.Equal(t, errRead, err)
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue