summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/api-get-object.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/minio-go/api-get-object.go')
-rw-r--r--vendor/github.com/minio/minio-go/api-get-object.go101
1 files changed, 40 insertions, 61 deletions
diff --git a/vendor/github.com/minio/minio-go/api-get-object.go b/vendor/github.com/minio/minio-go/api-get-object.go
index 9bd784ffa..50bbc2201 100644
--- a/vendor/github.com/minio/minio-go/api-get-object.go
+++ b/vendor/github.com/minio/minio-go/api-get-object.go
@@ -1,5 +1,6 @@
/*
- * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016, 2017 Minio, Inc.
+ * Minio Go Library for Amazon S3 Compatible Cloud Storage
+ * Copyright 2015-2017 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +18,7 @@
package minio
import (
+ "context"
"errors"
"fmt"
"io"
@@ -36,27 +38,16 @@ func (c Client) GetEncryptedObject(bucketName, objectName string, encryptMateria
return nil, ErrInvalidArgument("Unable to recognize empty encryption properties")
}
- // Fetch encrypted object
- encReader, err := c.GetObject(bucketName, objectName)
- if err != nil {
- return nil, err
- }
- // Stat object to get its encryption metadata
- st, err := encReader.Stat()
- if err != nil {
- return nil, err
- }
-
- // Setup object for decrytion, object is transparently
- // decrypted as the consumer starts reading.
- encryptMaterials.SetupDecryptMode(encReader, st.Metadata.Get(amzHeaderIV), st.Metadata.Get(amzHeaderKey))
-
- // Success.
- return encryptMaterials, nil
+ return c.GetObject(bucketName, objectName, GetObjectOptions{Materials: encryptMaterials})
}
// GetObject - returns an seekable, readable object.
-func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
+func (c Client) GetObject(bucketName, objectName string, opts GetObjectOptions) (*Object, error) {
+ return c.getObjectWithContext(context.Background(), bucketName, objectName, opts)
+}
+
+// GetObject wrapper function that accepts a request context
+func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName string, opts GetObjectOptions) (*Object, error) {
// Input validation.
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
return nil, err
@@ -102,34 +93,26 @@ func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
if req.isFirstReq {
// First request is a Read/ReadAt.
if req.isReadOp {
- reqHeaders := NewGetReqHeaders()
// Differentiate between wanting the whole object and just a range.
if req.isReadAt {
// If this is a ReadAt request only get the specified range.
// Range is set with respect to the offset and length of the buffer requested.
// Do not set objectInfo from the first readAt request because it will not get
// the whole object.
- reqHeaders.SetRange(req.Offset, req.Offset+int64(len(req.Buffer))-1)
- httpReader, objectInfo, err = c.getObject(bucketName, objectName, reqHeaders)
- } else {
- if req.Offset > 0 {
- reqHeaders.SetRange(req.Offset, 0)
- }
-
- // First request is a Read request.
- httpReader, objectInfo, err = c.getObject(bucketName, objectName, reqHeaders)
+ opts.SetRange(req.Offset, req.Offset+int64(len(req.Buffer))-1)
+ } else if req.Offset > 0 {
+ opts.SetRange(req.Offset, 0)
}
+ httpReader, objectInfo, err = c.getObject(ctx, bucketName, objectName, opts)
if err != nil {
- resCh <- getResponse{
- Error: err,
- }
+ resCh <- getResponse{Error: err}
return
}
etag = objectInfo.ETag
// Read at least firstReq.Buffer bytes, if not we have
// reached our EOF.
size, err := io.ReadFull(httpReader, req.Buffer)
- if err == io.ErrUnexpectedEOF {
+ if size > 0 && err == io.ErrUnexpectedEOF {
// If an EOF happens after reading some but not
// all the bytes ReadFull returns ErrUnexpectedEOF
err = io.EOF
@@ -144,7 +127,7 @@ func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
} else {
// First request is a Stat or Seek call.
// Only need to run a StatObject until an actual Read or ReadAt request comes through.
- objectInfo, err = c.StatObject(bucketName, objectName)
+ objectInfo, err = c.statObject(ctx, bucketName, objectName, StatObjectOptions{opts})
if err != nil {
resCh <- getResponse{
Error: err,
@@ -159,11 +142,10 @@ func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
}
}
} else if req.settingObjectInfo { // Request is just to get objectInfo.
- reqHeaders := NewGetReqHeaders()
if etag != "" {
- reqHeaders.SetMatchETag(etag)
+ opts.SetMatchETag(etag)
}
- objectInfo, err := c.statObject(bucketName, objectName, reqHeaders)
+ objectInfo, err := c.statObject(ctx, bucketName, objectName, StatObjectOptions{opts})
if err != nil {
resCh <- getResponse{
Error: err,
@@ -183,9 +165,8 @@ func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
// new ones when they haven't been already.
// All readAt requests are new requests.
if req.DidOffsetChange || !req.beenRead {
- reqHeaders := NewGetReqHeaders()
if etag != "" {
- reqHeaders.SetMatchETag(etag)
+ opts.SetMatchETag(etag)
}
if httpReader != nil {
// Close previously opened http reader.
@@ -194,16 +175,11 @@ func (c Client) GetObject(bucketName, objectName string) (*Object, error) {
// If this request is a readAt only get the specified range.
if req.isReadAt {
// Range is set with respect to the offset and length of the buffer requested.
- reqHeaders.SetRange(req.Offset, req.Offset+int64(len(req.Buffer))-1)
- httpReader, _, err = c.getObject(bucketName, objectName, reqHeaders)
- } else {
- // Range is set with respect to the offset.
- if req.Offset > 0 {
- reqHeaders.SetRange(req.Offset, 0)
- }
-
- httpReader, objectInfo, err = c.getObject(bucketName, objectName, reqHeaders)
+ opts.SetRange(req.Offset, req.Offset+int64(len(req.Buffer))-1)
+ } else if req.Offset > 0 { // Range is set with respect to the offset.
+ opts.SetRange(req.Offset, 0)
}
+ httpReader, objectInfo, err = c.getObject(ctx, bucketName, objectName, opts)
if err != nil {
resCh <- getResponse{
Error: err,
@@ -626,7 +602,7 @@ func newObject(reqCh chan<- getRequest, resCh <-chan getResponse, doneCh chan<-
//
// For more information about the HTTP Range header.
// go to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.
-func (c Client) getObject(bucketName, objectName string, reqHeaders RequestHeaders) (io.ReadCloser, ObjectInfo, error) {
+func (c Client) getObject(ctx context.Context, bucketName, objectName string, opts GetObjectOptions) (io.ReadCloser, ObjectInfo, error) {
// Validate input arguments.
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
return nil, ObjectInfo{}, err
@@ -635,18 +611,12 @@ func (c Client) getObject(bucketName, objectName string, reqHeaders RequestHeade
return nil, ObjectInfo{}, err
}
- // Set all the necessary reqHeaders.
- customHeader := make(http.Header)
- for key, value := range reqHeaders.Header {
- customHeader[key] = value
- }
-
// Execute GET on objectName.
- resp, err := c.executeMethod("GET", requestMetadata{
- bucketName: bucketName,
- objectName: objectName,
- customHeader: customHeader,
- contentSHA256Bytes: emptySHA256,
+ resp, err := c.executeMethod(ctx, "GET", requestMetadata{
+ bucketName: bucketName,
+ objectName: objectName,
+ customHeader: opts.Header(),
+ contentSHA256Hex: emptySHA256Hex,
})
if err != nil {
return nil, ObjectInfo{}, err
@@ -692,6 +662,15 @@ func (c Client) getObject(bucketName, objectName string, reqHeaders RequestHeade
Metadata: extractObjMetadata(resp.Header),
}
+ reader := resp.Body
+ if opts.Materials != nil {
+ err = opts.Materials.SetupDecryptMode(reader, objectStat.Metadata.Get(amzHeaderIV), objectStat.Metadata.Get(amzHeaderKey))
+ if err != nil {
+ return nil, ObjectInfo{}, err
+ }
+ reader = opts.Materials
+ }
+
// do not close body here, caller will close
- return resp.Body, objectStat, nil
+ return reader, objectStat, nil
}