From 005dc1ade98d2f5a20c2cc9278a8c960af6cc971 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Sun, 28 May 2017 23:48:53 +0100 Subject: [PATCH] get: Fix reading an object if its size is unknown Getting an object and reading it doesn't work as expected when S3 server doesn't return the object content length, which happens sometimes with Google Cloud Service. --- api-get-object.go | 14 +++++++++----- api-stat.go | 11 +++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/api-get-object.go b/api-get-object.go index 2abd4608e..92a64fd7b 100644 --- a/api-get-object.go +++ b/api-get-object.go @@ -328,14 +328,14 @@ func (o *Object) setOffset(bytesRead int64) error { // Update the currentOffset. o.currOffset += bytesRead - if o.currOffset >= o.objectInfo.Size { + if o.objectInfo.Size > -1 && o.currOffset >= o.objectInfo.Size { return io.EOF } return nil } // Read reads up to len(b) bytes into b. It returns the number of -// bytes read (0 <= n <= len(p)) and any error encountered. Returns +// bytes read (0 <= n <= len(b)) and any error encountered. Returns // io.EOF upon end of file. func (o *Object) Read(b []byte) (n int, err error) { if o == nil { @@ -442,7 +442,7 @@ func (o *Object) ReadAt(b []byte, offset int64) (n int, err error) { if o.objectInfoSet { // If offset is negative than we return io.EOF. // If offset is greater than or equal to object size we return io.EOF. - if offset >= o.objectInfo.Size || offset < 0 { + if (o.objectInfo.Size > -1 && offset >= o.objectInfo.Size) || offset < 0 { return 0, io.EOF } } @@ -542,16 +542,20 @@ func (o *Object) Seek(offset int64, whence int) (n int64, err error) { default: return 0, ErrInvalidArgument(fmt.Sprintf("Invalid whence %d", whence)) case 0: - if offset > o.objectInfo.Size { + if o.objectInfo.Size > -1 && offset > o.objectInfo.Size { return 0, io.EOF } o.currOffset = offset case 1: - if o.currOffset+offset > o.objectInfo.Size { + if o.objectInfo.Size > -1 && o.currOffset+offset > o.objectInfo.Size { return 0, io.EOF } o.currOffset += offset case 2: + // If we don't know the object size return an error for io.SeekEnd + if o.objectInfo.Size < 0 { + return 0, ErrInvalidArgument("Whence END is not supported when the object size is unknown") + } // Seeking to positive offset is valid for whence '2', but // since we are backing a Reader we have reached 'EOF' if // offset is positive. diff --git a/api-stat.go b/api-stat.go index 5b3dfe1b4..94f35db2a 100644 --- a/api-stat.go +++ b/api-stat.go @@ -21,8 +21,6 @@ import ( "strconv" "strings" "time" - - "github.com/minio/minio-go/pkg/s3utils" ) // BucketExists verify if bucket exists and you have permission to access it. @@ -126,12 +124,13 @@ func (c Client) statObject(bucketName, objectName string, reqHeaders RequestHead md5sum := strings.TrimPrefix(resp.Header.Get("ETag"), "\"") md5sum = strings.TrimSuffix(md5sum, "\"") - // Content-Length is not valid for Google Cloud Storage, do not verify. + // Parse content length is exists var size int64 = -1 - if !s3utils.IsGoogleEndpoint(c.endpointURL) { - // Parse content length. - size, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) + contentLengthStr := resp.Header.Get("Content-Length") + if contentLengthStr != "" { + size, err = strconv.ParseInt(contentLengthStr, 10, 64) if err != nil { + // Content-Length is not valid return ObjectInfo{}, ErrorResponse{ Code: "InternalError", Message: "Content-Length is invalid. " + reportIssue,