diff --git a/backend/backend.go b/backend/backend.go index 979d440..06560bc 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -15,6 +15,8 @@ type Backend interface { Shutdown() ListBuckets() (*s3response.ListAllMyBucketsList, s3err.ErrorCode) + HeadBucket(bucket string) (*s3response.HeadBucketResponse, s3err.ErrorCode) + GetBucketAcl(bucket string) (*s3response.GetBucketAclResponse, s3err.ErrorCode) PutBucket(bucket string) s3err.ErrorCode DeleteBucket(bucket string) s3err.ErrorCode @@ -27,7 +29,10 @@ type Backend interface { PutObjectPart(bucket, object, uploadID string, part int, r io.Reader) (etag string, err s3err.ErrorCode) PutObject(bucket, object string, r io.Reader) (string, s3err.ErrorCode) + HeadObject(bucket, object string, etag string) (*s3response.HeadObjectResponse, s3err.ErrorCode) GetObject(bucket, object string, startOffset, length int64, writer io.Writer, etag string) (*s3response.GetObjectResponse, s3err.ErrorCode) + GetObjectAcl(bucket, object string) (*s3response.GetObjectAccessControlPolicyResponse, s3err.ErrorCode) + GetObjectAttributes(bucket, object string, attributes []string) (*s3response.GetObjectAttributesResponse, s3err.ErrorCode) CopyObject(srcBucket, srcObject, DstBucket, dstObject string) (*s3response.CopyObjectResponse, s3err.ErrorCode) ListObjects(bucket, prefix, marker, delim string, maxkeys int) (*s3response.ListBucketResult, s3err.ErrorCode) ListObjectsV2(bucket, prefix, marker, delim string, maxkeys int) (*s3response.ListBucketResultV2, s3err.ErrorCode) @@ -58,6 +63,12 @@ func (BackendUnsupported) String() string { func (BackendUnsupported) ListBuckets() (*s3response.ListAllMyBucketsList, s3err.ErrorCode) { return nil, s3err.ErrNotImplemented } +func (BackendUnsupported) GetBucketAcl(bucket string) (*s3response.GetBucketAclResponse, s3err.ErrorCode) { + return nil, s3err.ErrNotImplemented +} +func (BackendUnsupported) HeadBucket(bucket string) (*s3response.HeadBucketResponse, s3err.ErrorCode) { + return nil, s3err.ErrNotImplemented +} func (BackendUnsupported) PutBucket(bucket string) s3err.ErrorCode { return s3err.ErrNotImplemented } @@ -99,6 +110,15 @@ func (BackendUnsupported) DeleteObjects(bucket string, object []string) s3err.Er func (BackendUnsupported) GetObject(bucket, object string, startOffset, length int64, writer io.Writer, etag string) (*s3response.GetObjectResponse, s3err.ErrorCode) { return nil, s3err.ErrNotImplemented } +func (BackendUnsupported) HeadObject(bucket, object string, etag string) (*s3response.HeadObjectResponse, s3err.ErrorCode) { + return nil, s3err.ErrNotImplemented +} +func (BackendUnsupported) GetObjectAcl(bucket, object string) (*s3response.GetObjectAccessControlPolicyResponse, s3err.ErrorCode) { + return nil, s3err.ErrNotImplemented +} +func (BackendUnsupported) GetObjectAttributes(bucket, object string, attributes []string) (*s3response.GetObjectAttributesResponse, s3err.ErrorCode) { + return nil, s3err.ErrNotImplemented +} func (BackendUnsupported) CopyObject(srcBucket, srcObject, DstBucket, dstObject string) (*s3response.CopyObjectResponse, s3err.ErrorCode) { return nil, s3err.ErrNotImplemented } diff --git a/s3api/router.go b/s3api/router.go index dd1c3eb..3572f43 100644 --- a/s3api/router.go +++ b/s3api/router.go @@ -9,6 +9,7 @@ import ( "github.com/versity/scoutgw/internal" "github.com/versity/scoutgw/s3err" "github.com/versity/scoutgw/s3response" + "strconv" "strings" ) @@ -35,22 +36,78 @@ func (sa *S3ApiRouter) Init(app *fiber.App, be backend.Backend) { return responce[internal.Any](ctx, nil, code) }) + // HeadBucket + app.Head("/:bucket", func(ctx *fiber.Ctx) error { + res, code := be.HeadBucket(ctx.Params("bucket")) + return responce[*s3response.HeadBucketResponse](ctx, res, code) + }) + // GetBucketAcl action // ListObjects action // ListObjectsV2 action app.Get("/:bucket", func(ctx *fiber.Ctx) error { - listType := ctx.QueryInt("list-type") + if ctx.Request().URI().QueryArgs().Has("acl") { + res, code := be.GetBucketAcl(ctx.Params("bucket")) + return responce[*s3response.GetBucketAclResponse](ctx, res, code) + } - if listType == 2 { + if ctx.QueryInt("list-type") == 2 { res, code := be.ListObjectsV2(ctx.Params("bucket"), "", "", "", 1) return responce[*s3response.ListBucketResultV2](ctx, res, code) - } else { - res, code := be.ListObjects(ctx.Params("bucket"), "", "", "", 1) - return responce[*s3response.ListBucketResult](ctx, res, code) } + + res, code := be.ListObjects(ctx.Params("bucket"), "", "", "", 1) + return responce[*s3response.ListBucketResult](ctx, res, code) + }) + // GetObjectAcl action + // GetObject action + //todo: will continue HeadObject implementation + app.Get("/:bucket/:key/*", func(ctx *fiber.Ctx) error { + if ctx.Request().URI().QueryArgs().Has("acl") { + res, code := be.GetObjectAcl(ctx.Params("bucket"), ctx.Params("key")) + return responce[*s3response.GetObjectAccessControlPolicyResponse](ctx, res, code) + } + + if attrs := ctx.Get("X-Amz-Object-Attributes"); attrs != "" { + res, code := be.GetObjectAttributes(ctx.Params("bucket"), ctx.Params("key"), strings.Split(ctx.Get("key"), ",")) + return responce[*s3response.GetObjectAttributesResponse](ctx, res, code) + } + + bucket, key, keyEnd := ctx.Params("bucket"), ctx.Params("key"), ctx.Params("*1") + if keyEnd != "" { + key = strings.Join([]string{key, keyEnd}, "/") + } + + bRangeSl := strings.Split(ctx.Get("Range"), "=") + if len(bRangeSl) < 2 { + return errors.New("wrong api call") + } + + bRange := strings.Split(bRangeSl[1], "-") + if len(bRange) < 2 { + return errors.New("wrong api call") + } + + startOffset, err := strconv.Atoi(bRange[0]) + if err != nil { + return errors.New("wrong api call") + } + + length, err := strconv.Atoi(bRange[1]) + if err != nil { + return errors.New("wrong api call") + } + + res, code := be.GetObject(bucket, key, int64(startOffset), int64(length), ctx.Response().BodyWriter(), "") + return responce[*s3response.GetObjectResponse](ctx, res, code) }) // DeleteObject action - app.Delete("/:bucket/:key", func(ctx *fiber.Ctx) error { - code := be.DeleteObject(ctx.Params("bucket"), ctx.Params("key")) + app.Delete("/:bucket/:key/*", func(ctx *fiber.Ctx) error { + bucket, key, keyEnd := ctx.Params("bucket"), ctx.Params("key"), ctx.Params("*1") + if keyEnd != "" { + key = strings.Join([]string{key, keyEnd}, "/") + } + + code := be.DeleteObject(bucket, key) return responce[internal.Any](ctx, nil, code) }) // DeleteObjects action diff --git a/s3response/AmazonS3-additions.xsd b/s3response/AmazonS3-additions.xsd new file mode 100644 index 0000000..0132af3 --- /dev/null +++ b/s3response/AmazonS3-additions.xsd @@ -0,0 +1,851 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/s3response/README.txt b/s3response/README.txt index 99fafb2..879e8ab 100644 --- a/s3response/README.txt +++ b/s3response/README.txt @@ -4,3 +4,4 @@ see https://blog.aqwari.net/xml-schema-go/ go install aqwari.net/xml/cmd/xsdgen@latest xsdgen -o s3api_xsd_generated.go -pkg s3response AmazonS3.xsd +xsdgen -o s3api_xsd_generated.go -pkg s3response AmazonS3-additions.xsd \ No newline at end of file diff --git a/s3response/s3api_xsd_generated.go b/s3response/s3api_xsd_generated.go index 729786e..4c82d92 100644 --- a/s3response/s3api_xsd_generated.go +++ b/s3response/s3api_xsd_generated.go @@ -31,6 +31,13 @@ type CanonicalUser struct { DisplayName string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ DisplayName,omitempty"` } +type Checksum struct { + ChecksumCRC32 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumCRC32"` + ChecksumCRC32C string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumCRC32C"` + ChecksumSHA1 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumSHA1"` + ChecksumSHA256 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumSHA256"` +} + type CopyObject struct { SourceBucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ SourceBucket"` SourceKey string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ SourceKey"` @@ -279,6 +286,65 @@ type GetBucketAccessControlPolicyResponse struct { GetBucketAccessControlPolicyResponse AccessControlPolicy `xml:"http://s3.amazonaws.com/doc/2006-03-01/ GetBucketAccessControlPolicyResponse"` } +type GetBucketAcl struct { + Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *GetBucketAcl) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T GetBucketAcl + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *GetBucketAcl) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T GetBucketAcl + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type GetBucketAclResponse struct { + CanonicalUser CanonicalUser `xml:"http://s3.amazonaws.com/doc/2006-03-01/ CanonicalUser"` + AccessControlList AccessControlList `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AccessControlList"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *GetBucketAclResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T GetBucketAclResponse + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *GetBucketAclResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T GetBucketAclResponse + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + type GetBucketLoggingStatus struct { Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` @@ -379,6 +445,82 @@ type GetObjectAccessControlPolicyResponse struct { GetObjectAccessControlPolicyResponse AccessControlPolicy `xml:"http://s3.amazonaws.com/doc/2006-03-01/ GetObjectAccessControlPolicyResponse"` } +type GetObjectAcl struct { + Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` + Key string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Key"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *GetObjectAcl) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T GetObjectAcl + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *GetObjectAcl) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T GetObjectAcl + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type GetObjectAclResponse struct { + Owner CanonicalUser `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Owner"` + Grants AccessControlList `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Grants"` + RequestCharged string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ RequestCharged"` +} + +type GetObjectAttributes struct { + Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` + Key string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Key"` + Attributes string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Attributes"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *GetObjectAttributes) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T GetObjectAttributes + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *GetObjectAttributes) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T GetObjectAttributes + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type GetObjectAttributesResponse struct { + Etag string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Etag"` + Checksum Checksum `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Checksum"` + RequestCharged string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ RequestCharged"` + ObjectParts ObjectParts `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ObjectParts"` + StorageClass string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ StorageClass"` + ObjectSize int64 `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ObjectSize"` +} + type GetObjectExtended struct { Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` Key string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Key"` @@ -480,6 +622,121 @@ type Group struct { URI string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ URI"` } +type HeadBucket struct { + Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *HeadBucket) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T HeadBucket + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *HeadBucket) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T HeadBucket + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type HeadBucketResponse struct { + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *HeadBucketResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T HeadBucketResponse + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *HeadBucketResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T HeadBucketResponse + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type HeadObject struct { + Bucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Bucket"` + Key string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Key"` + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *HeadObject) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T HeadObject + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *HeadObject) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T HeadObject + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + +type HeadObjectResponse struct { + AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` + Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + Signature string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Signature,omitempty"` + Credential string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Credential,omitempty"` +} + +func (t *HeadObjectResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type T HeadObjectResponse + var layout struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + layout.T = (*T)(t) + layout.Timestamp = (*xsdDateTime)(&layout.T.Timestamp) + return e.EncodeElement(layout, start) +} +func (t *HeadObjectResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + type T HeadObjectResponse + var overlay struct { + *T + Timestamp *xsdDateTime `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` + } + overlay.T = (*T)(t) + overlay.Timestamp = (*xsdDateTime)(&overlay.T.Timestamp) + return d.DecodeElement(&overlay, &start) +} + type ListAllMyBuckets struct { AWSAccessKeyId string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ AWSAccessKeyId,omitempty"` Timestamp time.Time `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Timestamp,omitempty"` @@ -667,6 +924,24 @@ type NotificationConfiguration struct { TopicConfiguration []TopicConfiguration `xml:"http://s3.amazonaws.com/doc/2006-03-01/ TopicConfiguration,omitempty"` } +type ObjectParts struct { + IsTruncated bool `xml:"http://s3.amazonaws.com/doc/2006-03-01/ IsTruncated"` + MaxParts int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ MaxParts"` + NextPartNumberMarker int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ NextPartNumberMarker"` + PartNumberMarker int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ PartNumberMarker"` + Part Part `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Part"` + PartsCount int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ PartsCount"` +} + +type Part struct { + ChecksumCRC32 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumCRC32"` + ChecksumCRC32C string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumCRC32C"` + ChecksumSHA1 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumSHA1"` + ChecksumSHA256 string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ChecksumSHA256"` + PartNumber int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ PartNumber"` + Size int `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Size"` +} + // May be one of BucketOwner, Requester type Payer string diff --git a/s3response/s3response.go b/s3response/s3response.go index 0b7337b..18d0e63 100644 --- a/s3response/s3response.go +++ b/s3response/s3response.go @@ -25,14 +25,6 @@ type LocationResponse struct { Location string `xml:",chardata"` } -// Part container for part metadata. -type Part struct { - PartNumber int - LastModified string - ETag string - Size int64 -} - // ListPartsResponse - format for list parts response. type ListPartsResponse struct { XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ ListPartsResult" json:"-"`