Skip to content
Merged
129 changes: 129 additions & 0 deletions api-get-object-attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package minio
Comment thread
zveinn marked this conversation as resolved.

import (
"context"
"encoding/xml"
"net/http"
"net/url"
"time"

"github.com/minio/minio-go/v7/pkg/encrypt"
"github.com/minio/minio-go/v7/pkg/s3utils"
)

// ObjectAttributesOptions is an API call that combines
// HeadObject and ListParts.
//
// VersionID - The object version you want to attributes for
// ServerSideEncryption - The server-side encryption algorithm used when storing this object in Minio
type ObjectAttributesOptions struct {
VersionID string
ServerSideEncryption encrypt.ServerSide
}

// ObjectAttributes ...
type ObjectAttributes struct {
objectAttributesResponse
Comment thread
zveinn marked this conversation as resolved.
Outdated
LastModified time.Time
VersionID string
}

func (o *ObjectAttributes) parseResponse(resp *http.Response) (err error) {
mod, err := parseRFC7231Time(resp.Header.Get("Last-Modified"))
if err != nil {
return err
}
o.LastModified = mod
o.VersionID = resp.Header.Get(amzVersionID)

response := new(objectAttributesResponse)
if err := xml.NewDecoder(resp.Body).Decode(response); err != nil {
return err
}
o.objectAttributesResponse = *response

return
}

type objectAttributesResponse struct {
ETag string `xml:",omitempty"`
StorageClass string
ObjectSize int
Checksum struct {
ChecksumCRC32 string `xml:",omitempty"`
ChecksumCRC32C string `xml:",omitempty"`
ChecksumSHA1 string `xml:",omitempty"`
ChecksumSHA256 string `xml:",omitempty"`
}
ObjectParts struct {
PartsCount int
Parts []*objectPart `xml:"Part"`
Comment thread
zveinn marked this conversation as resolved.
Outdated
}
}

type objectPart struct {
ChecksumCRC32 string `xml:",omitempty"`
ChecksumCRC32C string `xml:",omitempty"`
ChecksumSHA1 string `xml:",omitempty"`
ChecksumSHA256 string `xml:",omitempty"`
PartNumber int
Size int
}

// GetObjectAttributes ...
Comment thread
zveinn marked this conversation as resolved.
Outdated
// This API combines HeadObject and ListParts.
func (c *Client) GetObjectAttributes(ctx context.Context, bucketName, objectName string, opts ObjectAttributesOptions) (ObjectAttributes, error) {
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
return ObjectAttributes{}, err
}

if err := s3utils.CheckValidObjectName(objectName); err != nil {
return ObjectAttributes{}, err
}

urlValues := make(url.Values)
urlValues.Add("attributes", "")
if opts.VersionID != "" {
urlValues.Add("versionId", opts.VersionID)
}

headers := make(http.Header)
headers.Set(amzObjectAttributes, GetObjectAttributesTags)

headers.Set(amzPartNumberMarker, "0")
headers.Set(amzMaxParts, "0")
Comment thread
harshavardhana marked this conversation as resolved.
Outdated

if opts.ServerSideEncryption != nil {
opts.ServerSideEncryption.Marshal(headers)
}

resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{
bucketName: bucketName,
objectName: objectName,
queryValues: urlValues,
contentSHA256Hex: emptySHA256Hex,
customHeader: headers,
})
if err != nil {
return ObjectAttributes{}, err
}

if resp.StatusCode != http.StatusOK {
ER := new(ErrorResponse)
if err := xml.NewDecoder(resp.Body).Decode(ER); err != nil {
return ObjectAttributes{}, err
}

return ObjectAttributes{}, *ER
}

defer closeResponse(resp)
Comment thread
zveinn marked this conversation as resolved.
Outdated

OA := new(ObjectAttributes)
err = OA.parseResponse(resp)
if err != nil {
return ObjectAttributes{}, err
}

return *OA, nil
}
11 changes: 11 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,23 @@ const (
)

const (
GetObjectAttributesTags = "ETag,Checksum,StorageClass,ObjectSize,ObjectParts"
)

const (

// Storage class header.
amzStorageClass = "X-Amz-Storage-Class"

// Website redirect location header
amzWebsiteRedirectLocation = "X-Amz-Website-Redirect-Location"

// GetObjectAttributes headers
amzPartNumberMarker = "X-Amz-Part-Number-Marker"
amzExpectedBucketOnwer = "X-Amz-Expected-Bucket-Owner"
amzMaxParts = "X-Amz-Max-Parts"
amzObjectAttributes = "X-Amz-Object-Attributes"

// Object Tagging headers
amzTaggingHeader = "X-Amz-Tagging"
amzTaggingHeaderDirective = "X-Amz-Tagging-Directive"
Expand Down
Loading