469 lines
18 KiB
Go
469 lines
18 KiB
Go
package oss
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"net/url"
|
|
"time"
|
|
)
|
|
|
|
// ListBucketsResult defines the result object from ListBuckets request
|
|
type ListBucketsResult struct {
|
|
XMLName xml.Name `xml:"ListAllMyBucketsResult"`
|
|
Prefix string `xml:"Prefix"` // The prefix in this query
|
|
Marker string `xml:"Marker"` // The marker filter
|
|
MaxKeys int `xml:"MaxKeys"` // The max entry count to return. This information is returned when IsTruncated is true.
|
|
IsTruncated bool `xml:"IsTruncated"` // Flag true means there's remaining buckets to return.
|
|
NextMarker string `xml:"NextMarker"` // The marker filter for the next list call
|
|
Owner Owner `xml:"Owner"` // The owner information
|
|
Buckets []BucketProperties `xml:"Buckets>Bucket"` // The bucket list
|
|
}
|
|
|
|
// BucketProperties defines bucket properties
|
|
type BucketProperties struct {
|
|
XMLName xml.Name `xml:"Bucket"`
|
|
Name string `xml:"Name"` // Bucket name
|
|
Location string `xml:"Location"` // Bucket datacenter
|
|
CreationDate time.Time `xml:"CreationDate"` // Bucket create time
|
|
StorageClass string `xml:"StorageClass"` // Bucket storage class
|
|
}
|
|
|
|
// GetBucketACLResult defines GetBucketACL request's result
|
|
type GetBucketACLResult struct {
|
|
XMLName xml.Name `xml:"AccessControlPolicy"`
|
|
ACL string `xml:"AccessControlList>Grant"` // Bucket ACL
|
|
Owner Owner `xml:"Owner"` // Bucket owner
|
|
}
|
|
|
|
// LifecycleConfiguration is the Bucket Lifecycle configuration
|
|
type LifecycleConfiguration struct {
|
|
XMLName xml.Name `xml:"LifecycleConfiguration"`
|
|
Rules []LifecycleRule `xml:"Rule"`
|
|
}
|
|
|
|
// LifecycleRule defines Lifecycle rules
|
|
type LifecycleRule struct {
|
|
XMLName xml.Name `xml:"Rule"`
|
|
ID string `xml:"ID"` // The rule ID
|
|
Prefix string `xml:"Prefix"` // The object key prefix
|
|
Status string `xml:"Status"` // The rule status (enabled or not)
|
|
Expiration LifecycleExpiration `xml:"Expiration"` // The expiration property
|
|
}
|
|
|
|
// LifecycleExpiration defines the rule's expiration property
|
|
type LifecycleExpiration struct {
|
|
XMLName xml.Name `xml:"Expiration"`
|
|
Days int `xml:"Days,omitempty"` // Relative expiration time: The expiration time in days after the last modified time
|
|
Date time.Time `xml:"Date,omitempty"` // Absolute expiration time: The expiration time in date.
|
|
}
|
|
|
|
type lifecycleXML struct {
|
|
XMLName xml.Name `xml:"LifecycleConfiguration"`
|
|
Rules []lifecycleRule `xml:"Rule"`
|
|
}
|
|
|
|
type lifecycleRule struct {
|
|
XMLName xml.Name `xml:"Rule"`
|
|
ID string `xml:"ID"`
|
|
Prefix string `xml:"Prefix"`
|
|
Status string `xml:"Status"`
|
|
Expiration lifecycleExpiration `xml:"Expiration"`
|
|
}
|
|
|
|
type lifecycleExpiration struct {
|
|
XMLName xml.Name `xml:"Expiration"`
|
|
Days int `xml:"Days,omitempty"`
|
|
Date string `xml:"Date,omitempty"`
|
|
}
|
|
|
|
const expirationDateFormat = "2006-01-02T15:04:05.000Z"
|
|
|
|
func convLifecycleRule(rules []LifecycleRule) []lifecycleRule {
|
|
rs := []lifecycleRule{}
|
|
for _, rule := range rules {
|
|
r := lifecycleRule{}
|
|
r.ID = rule.ID
|
|
r.Prefix = rule.Prefix
|
|
r.Status = rule.Status
|
|
if rule.Expiration.Date.IsZero() {
|
|
r.Expiration.Days = rule.Expiration.Days
|
|
} else {
|
|
r.Expiration.Date = rule.Expiration.Date.Format(expirationDateFormat)
|
|
}
|
|
rs = append(rs, r)
|
|
}
|
|
return rs
|
|
}
|
|
|
|
// BuildLifecycleRuleByDays builds a lifecycle rule with specified expiration days
|
|
func BuildLifecycleRuleByDays(id, prefix string, status bool, days int) LifecycleRule {
|
|
var statusStr = "Enabled"
|
|
if !status {
|
|
statusStr = "Disabled"
|
|
}
|
|
return LifecycleRule{ID: id, Prefix: prefix, Status: statusStr,
|
|
Expiration: LifecycleExpiration{Days: days}}
|
|
}
|
|
|
|
// BuildLifecycleRuleByDate builds a lifecycle rule with specified expiration time.
|
|
func BuildLifecycleRuleByDate(id, prefix string, status bool, year, month, day int) LifecycleRule {
|
|
var statusStr = "Enabled"
|
|
if !status {
|
|
statusStr = "Disabled"
|
|
}
|
|
date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
|
|
return LifecycleRule{ID: id, Prefix: prefix, Status: statusStr,
|
|
Expiration: LifecycleExpiration{Date: date}}
|
|
}
|
|
|
|
// GetBucketLifecycleResult defines GetBucketLifecycle's result object
|
|
type GetBucketLifecycleResult LifecycleConfiguration
|
|
|
|
// RefererXML defines Referer configuration
|
|
type RefererXML struct {
|
|
XMLName xml.Name `xml:"RefererConfiguration"`
|
|
AllowEmptyReferer bool `xml:"AllowEmptyReferer"` // Allow empty referrer
|
|
RefererList []string `xml:"RefererList>Referer"` // Referer whitelist
|
|
}
|
|
|
|
// GetBucketRefererResult defines result object for GetBucketReferer request
|
|
type GetBucketRefererResult RefererXML
|
|
|
|
// LoggingXML defines logging configuration
|
|
type LoggingXML struct {
|
|
XMLName xml.Name `xml:"BucketLoggingStatus"`
|
|
LoggingEnabled LoggingEnabled `xml:"LoggingEnabled"` // The logging configuration information
|
|
}
|
|
|
|
type loggingXMLEmpty struct {
|
|
XMLName xml.Name `xml:"BucketLoggingStatus"`
|
|
}
|
|
|
|
// LoggingEnabled defines the logging configuration information
|
|
type LoggingEnabled struct {
|
|
XMLName xml.Name `xml:"LoggingEnabled"`
|
|
TargetBucket string `xml:"TargetBucket"` // The bucket name for storing the log files
|
|
TargetPrefix string `xml:"TargetPrefix"` // The log file prefix
|
|
}
|
|
|
|
// GetBucketLoggingResult defines the result from GetBucketLogging request
|
|
type GetBucketLoggingResult LoggingXML
|
|
|
|
// WebsiteXML defines Website configuration
|
|
type WebsiteXML struct {
|
|
XMLName xml.Name `xml:"WebsiteConfiguration"`
|
|
IndexDocument IndexDocument `xml:"IndexDocument"` // The index page
|
|
ErrorDocument ErrorDocument `xml:"ErrorDocument"` // The error page
|
|
}
|
|
|
|
// IndexDocument defines the index page info
|
|
type IndexDocument struct {
|
|
XMLName xml.Name `xml:"IndexDocument"`
|
|
Suffix string `xml:"Suffix"` // The file name for the index page
|
|
}
|
|
|
|
// ErrorDocument defines the 404 error page info
|
|
type ErrorDocument struct {
|
|
XMLName xml.Name `xml:"ErrorDocument"`
|
|
Key string `xml:"Key"` // 404 error file name
|
|
}
|
|
|
|
// GetBucketWebsiteResult defines the result from GetBucketWebsite request.
|
|
type GetBucketWebsiteResult WebsiteXML
|
|
|
|
// CORSXML defines CORS configuration
|
|
type CORSXML struct {
|
|
XMLName xml.Name `xml:"CORSConfiguration"`
|
|
CORSRules []CORSRule `xml:"CORSRule"` // CORS rules
|
|
}
|
|
|
|
// CORSRule defines CORS rules
|
|
type CORSRule struct {
|
|
XMLName xml.Name `xml:"CORSRule"`
|
|
AllowedOrigin []string `xml:"AllowedOrigin"` // Allowed origins. By default it's wildcard '*'
|
|
AllowedMethod []string `xml:"AllowedMethod"` // Allowed methods
|
|
AllowedHeader []string `xml:"AllowedHeader"` // Allowed headers
|
|
ExposeHeader []string `xml:"ExposeHeader"` // Allowed response headers
|
|
MaxAgeSeconds int `xml:"MaxAgeSeconds"` // Max cache ages in seconds
|
|
}
|
|
|
|
// GetBucketCORSResult defines the result from GetBucketCORS request.
|
|
type GetBucketCORSResult CORSXML
|
|
|
|
// GetBucketInfoResult defines the result from GetBucketInfo request.
|
|
type GetBucketInfoResult struct {
|
|
XMLName xml.Name `xml:"BucketInfo"`
|
|
BucketInfo BucketInfo `xml:"Bucket"`
|
|
}
|
|
|
|
// BucketInfo defines Bucket information
|
|
type BucketInfo struct {
|
|
XMLName xml.Name `xml:"Bucket"`
|
|
Name string `xml:"Name"` // Bucket name
|
|
Location string `xml:"Location"` // Bucket datacenter
|
|
CreationDate time.Time `xml:"CreationDate"` // Bucket creation time
|
|
ExtranetEndpoint string `xml:"ExtranetEndpoint"` // Bucket external endpoint
|
|
IntranetEndpoint string `xml:"IntranetEndpoint"` // Bucket internal endpoint
|
|
ACL string `xml:"AccessControlList>Grant"` // Bucket ACL
|
|
Owner Owner `xml:"Owner"` // Bucket owner
|
|
StorageClass string `xml:"StorageClass"` // Bucket storage class
|
|
}
|
|
|
|
// ListObjectsResult defines the result from ListObjects request
|
|
type ListObjectsResult struct {
|
|
XMLName xml.Name `xml:"ListBucketResult"`
|
|
Prefix string `xml:"Prefix"` // The object prefix
|
|
Marker string `xml:"Marker"` // The marker filter.
|
|
MaxKeys int `xml:"MaxKeys"` // Max keys to return
|
|
Delimiter string `xml:"Delimiter"` // The delimiter for grouping objects' name
|
|
IsTruncated bool `xml:"IsTruncated"` // Flag indicates if all results are returned (when it's false)
|
|
NextMarker string `xml:"NextMarker"` // The start point of the next query
|
|
Objects []ObjectProperties `xml:"Contents"` // Object list
|
|
CommonPrefixes []string `xml:"CommonPrefixes>Prefix"` // You can think of commonprefixes as "folders" whose names end with the delimiter
|
|
}
|
|
|
|
// ObjectProperties defines Objecct properties
|
|
type ObjectProperties struct {
|
|
XMLName xml.Name `xml:"Contents"`
|
|
Key string `xml:"Key"` // Object key
|
|
Type string `xml:"Type"` // Object type
|
|
Size int64 `xml:"Size"` // Object size
|
|
ETag string `xml:"ETag"` // Object ETag
|
|
Owner Owner `xml:"Owner"` // Object owner information
|
|
LastModified time.Time `xml:"LastModified"` // Object last modified time
|
|
StorageClass string `xml:"StorageClass"` // Object storage class (Standard, IA, Archive)
|
|
}
|
|
|
|
// Owner defines Bucket/Object's owner
|
|
type Owner struct {
|
|
XMLName xml.Name `xml:"Owner"`
|
|
ID string `xml:"ID"` // Owner ID
|
|
DisplayName string `xml:"DisplayName"` // Owner's display name
|
|
}
|
|
|
|
// CopyObjectResult defines result object of CopyObject
|
|
type CopyObjectResult struct {
|
|
XMLName xml.Name `xml:"CopyObjectResult"`
|
|
LastModified time.Time `xml:"LastModified"` // New object's last modified time.
|
|
ETag string `xml:"ETag"` // New object's ETag
|
|
}
|
|
|
|
// GetObjectACLResult defines result of GetObjectACL request
|
|
type GetObjectACLResult GetBucketACLResult
|
|
|
|
type deleteXML struct {
|
|
XMLName xml.Name `xml:"Delete"`
|
|
Objects []DeleteObject `xml:"Object"` // Objects to delete
|
|
Quiet bool `xml:"Quiet"` // Flag of quiet mode.
|
|
}
|
|
|
|
// DeleteObject defines the struct for deleting object
|
|
type DeleteObject struct {
|
|
XMLName xml.Name `xml:"Object"`
|
|
Key string `xml:"Key"` // Object name
|
|
}
|
|
|
|
// DeleteObjectsResult defines result of DeleteObjects request
|
|
type DeleteObjectsResult struct {
|
|
XMLName xml.Name `xml:"DeleteResult"`
|
|
DeletedObjects []string `xml:"Deleted>Key"` // Deleted object list
|
|
}
|
|
|
|
// InitiateMultipartUploadResult defines result of InitiateMultipartUpload request
|
|
type InitiateMultipartUploadResult struct {
|
|
XMLName xml.Name `xml:"InitiateMultipartUploadResult"`
|
|
Bucket string `xml:"Bucket"` // Bucket name
|
|
Key string `xml:"Key"` // Object name to upload
|
|
UploadID string `xml:"UploadId"` // Generated UploadId
|
|
}
|
|
|
|
// UploadPart defines the upload/copy part
|
|
type UploadPart struct {
|
|
XMLName xml.Name `xml:"Part"`
|
|
PartNumber int `xml:"PartNumber"` // Part number
|
|
ETag string `xml:"ETag"` // ETag value of the part's data
|
|
}
|
|
|
|
type uploadParts []UploadPart
|
|
|
|
func (slice uploadParts) Len() int {
|
|
return len(slice)
|
|
}
|
|
|
|
func (slice uploadParts) Less(i, j int) bool {
|
|
return slice[i].PartNumber < slice[j].PartNumber
|
|
}
|
|
|
|
func (slice uploadParts) Swap(i, j int) {
|
|
slice[i], slice[j] = slice[j], slice[i]
|
|
}
|
|
|
|
// UploadPartCopyResult defines result object of multipart copy request.
|
|
type UploadPartCopyResult struct {
|
|
XMLName xml.Name `xml:"CopyPartResult"`
|
|
LastModified time.Time `xml:"LastModified"` // Last modified time
|
|
ETag string `xml:"ETag"` // ETag
|
|
}
|
|
|
|
type completeMultipartUploadXML struct {
|
|
XMLName xml.Name `xml:"CompleteMultipartUpload"`
|
|
Part []UploadPart `xml:"Part"`
|
|
}
|
|
|
|
// CompleteMultipartUploadResult defines result object of CompleteMultipartUploadRequest
|
|
type CompleteMultipartUploadResult struct {
|
|
XMLName xml.Name `xml:"CompleteMultipartUploadResult"`
|
|
Location string `xml:"Location"` // Object URL
|
|
Bucket string `xml:"Bucket"` // Bucket name
|
|
ETag string `xml:"ETag"` // Object ETag
|
|
Key string `xml:"Key"` // Object name
|
|
}
|
|
|
|
// ListUploadedPartsResult defines result object of ListUploadedParts
|
|
type ListUploadedPartsResult struct {
|
|
XMLName xml.Name `xml:"ListPartsResult"`
|
|
Bucket string `xml:"Bucket"` // Bucket name
|
|
Key string `xml:"Key"` // Object name
|
|
UploadID string `xml:"UploadId"` // Upload ID
|
|
NextPartNumberMarker string `xml:"NextPartNumberMarker"` // Next part number
|
|
MaxParts int `xml:"MaxParts"` // Max parts count
|
|
IsTruncated bool `xml:"IsTruncated"` // Flag indicates all entries returned.false: all entries returned.
|
|
UploadedParts []UploadedPart `xml:"Part"` // Uploaded parts
|
|
}
|
|
|
|
// UploadedPart defines uploaded part
|
|
type UploadedPart struct {
|
|
XMLName xml.Name `xml:"Part"`
|
|
PartNumber int `xml:"PartNumber"` // Part number
|
|
LastModified time.Time `xml:"LastModified"` // Last modified time
|
|
ETag string `xml:"ETag"` // ETag cache
|
|
Size int `xml:"Size"` // Part size
|
|
}
|
|
|
|
// ListMultipartUploadResult defines result object of ListMultipartUpload
|
|
type ListMultipartUploadResult struct {
|
|
XMLName xml.Name `xml:"ListMultipartUploadsResult"`
|
|
Bucket string `xml:"Bucket"` // Bucket name
|
|
Delimiter string `xml:"Delimiter"` // Delimiter for grouping object.
|
|
Prefix string `xml:"Prefix"` // Object prefix
|
|
KeyMarker string `xml:"KeyMarker"` // Object key marker
|
|
UploadIDMarker string `xml:"UploadIdMarker"` // UploadId marker
|
|
NextKeyMarker string `xml:"NextKeyMarker"` // Next key marker, if not all entries returned.
|
|
NextUploadIDMarker string `xml:"NextUploadIdMarker"` // Next uploadId marker, if not all entries returned.
|
|
MaxUploads int `xml:"MaxUploads"` // Max uploads to return
|
|
IsTruncated bool `xml:"IsTruncated"` // Flag indicates all entries are returned.
|
|
Uploads []UncompletedUpload `xml:"Upload"` // Ongoing uploads (not completed, not aborted)
|
|
CommonPrefixes []string `xml:"CommonPrefixes>Prefix"` // Common prefixes list.
|
|
}
|
|
|
|
// UncompletedUpload structure wraps an uncompleted upload task
|
|
type UncompletedUpload struct {
|
|
XMLName xml.Name `xml:"Upload"`
|
|
Key string `xml:"Key"` // Object name
|
|
UploadID string `xml:"UploadId"` // The UploadId
|
|
Initiated time.Time `xml:"Initiated"` // Initialization time in the format such as 2012-02-23T04:18:23.000Z
|
|
}
|
|
|
|
// ProcessObjectResult defines result object of ProcessObject
|
|
type ProcessObjectResult struct {
|
|
Bucket string `json:"bucket"`
|
|
FileSize int `json:"fileSize"`
|
|
Object string `json:"object"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
// decodeDeleteObjectsResult decodes deleting objects result in URL encoding
|
|
func decodeDeleteObjectsResult(result *DeleteObjectsResult) error {
|
|
var err error
|
|
for i := 0; i < len(result.DeletedObjects); i++ {
|
|
result.DeletedObjects[i], err = url.QueryUnescape(result.DeletedObjects[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// decodeListObjectsResult decodes list objects result in URL encoding
|
|
func decodeListObjectsResult(result *ListObjectsResult) error {
|
|
var err error
|
|
result.Prefix, err = url.QueryUnescape(result.Prefix)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.Marker, err = url.QueryUnescape(result.Marker)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.Delimiter, err = url.QueryUnescape(result.Delimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.NextMarker, err = url.QueryUnescape(result.NextMarker)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for i := 0; i < len(result.Objects); i++ {
|
|
result.Objects[i].Key, err = url.QueryUnescape(result.Objects[i].Key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := 0; i < len(result.CommonPrefixes); i++ {
|
|
result.CommonPrefixes[i], err = url.QueryUnescape(result.CommonPrefixes[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// decodeListUploadedPartsResult decodes
|
|
func decodeListUploadedPartsResult(result *ListUploadedPartsResult) error {
|
|
var err error
|
|
result.Key, err = url.QueryUnescape(result.Key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// decodeListMultipartUploadResult decodes list multipart upload result in URL encoding
|
|
func decodeListMultipartUploadResult(result *ListMultipartUploadResult) error {
|
|
var err error
|
|
result.Prefix, err = url.QueryUnescape(result.Prefix)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.Delimiter, err = url.QueryUnescape(result.Delimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.KeyMarker, err = url.QueryUnescape(result.KeyMarker)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.NextKeyMarker, err = url.QueryUnescape(result.NextKeyMarker)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for i := 0; i < len(result.Uploads); i++ {
|
|
result.Uploads[i].Key, err = url.QueryUnescape(result.Uploads[i].Key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := 0; i < len(result.CommonPrefixes); i++ {
|
|
result.CommonPrefixes[i], err = url.QueryUnescape(result.CommonPrefixes[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// createBucketConfiguration defines the configuration for creating a bucket.
|
|
type createBucketConfiguration struct {
|
|
XMLName xml.Name `xml:"CreateBucketConfiguration"`
|
|
StorageClass StorageClassType `xml:"StorageClass,omitempty"`
|
|
}
|