[#313] client/object: Always return number of bytes read from Get stream (#316)

Fix failure to comply with a requirement of stdlib `io.Reader` docs: `When
Read encounters an error or end-of-file condition after successfully reading
n > 0 bytes, it returns the number of bytes read.`

Prepare a platform for unit tests and test the affected case.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-06-23 14:15:58 +03:00 committed by GitHub
parent 616b4b71a1
commit 6d531a07a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 112 additions and 11 deletions

View file

@ -496,31 +496,35 @@ func (p *GetObjectParams) WithPayloadReaderHandler(f ReaderHandler) *GetObjectPa
// wrapper over the Object Get stream that provides io.Reader.
type objectPayloadReader struct {
stream *rpcapi.GetResponseReader
stream interface {
Read(*v2object.GetResponse) error
}
resp v2object.GetResponse
tail []byte
}
func (x *objectPayloadReader) Read(p []byte) (int, error) {
func (x *objectPayloadReader) Read(p []byte) (read int, err error) {
// read remaining tail
read := copy(p, x.tail)
read = copy(p, x.tail)
x.tail = x.tail[read:]
if len(p)-read == 0 {
return read, nil
return
}
// receive message from server stream
err := x.stream.Read(&x.resp)
err = x.stream.Read(&x.resp)
if err != nil {
if errors.Is(err, io.EOF) {
return 0, io.EOF
err = io.EOF
return
}
return 0, fmt.Errorf("reading the response failed: %w", err)
err = fmt.Errorf("reading the response failed: %w", err)
return
}
// get chunk part message
@ -528,12 +532,14 @@ func (x *objectPayloadReader) Read(p []byte) (int, error) {
chunkPart, ok := part.(*v2object.GetObjectPartChunk)
if !ok {
return 0, errWrongMessageSeq
err = errWrongMessageSeq
return
}
// verify response structure
if err := signature.VerifyServiceMessage(&x.resp); err != nil {
return 0, fmt.Errorf("response verification failed: %w", err)
if err = signature.VerifyServiceMessage(&x.resp); err != nil {
err = fmt.Errorf("response verification failed: %w", err)
return
}
// read new chunk
@ -546,7 +552,7 @@ func (x *objectPayloadReader) Read(p []byte) (int, error) {
// save the tail
x.tail = append(x.tail, chunk[tailOffset:]...)
return read, nil
return
}
var errWrongMessageSeq = errors.New("incorrect message sequence")