Update dependencies. (#13778)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1a82e3e575
Коммит
d7206d2ede
5
vendor/github.com/minio/minio-go/v6/Makefile
сгенерированный
поставляемый
5
vendor/github.com/minio/minio-go/v6/Makefile
сгенерированный
поставляемый
@@ -15,3 +15,8 @@ examples:
|
||||
|
||||
functional-test:
|
||||
@GO111MODULE=on SERVER_ENDPOINT=localhost:9000 ACCESS_KEY=minio SECRET_KEY=minio123 ENABLE_HTTPS=1 MINT_MODE=full go run functional_tests.go
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up all the generated files"
|
||||
@find . -name '*.test' | xargs rm -fv
|
||||
@find . -name '*~' | xargs rm -fv
|
||||
|
||||
102
vendor/github.com/minio/minio-go/v6/api-compose-object.go
сгенерированный
поставляемый
102
vendor/github.com/minio/minio-go/v6/api-compose-object.go
сгенерированный
поставляемый
@@ -36,18 +36,53 @@ import (
|
||||
// created via server-side copy requests, using the Compose API.
|
||||
type DestinationInfo struct {
|
||||
bucket, object string
|
||||
encryption encrypt.ServerSide
|
||||
opts DestInfoOptions
|
||||
}
|
||||
|
||||
// DestInfoOptions represents options specified by user for NewDestinationInfo call
|
||||
type DestInfoOptions struct {
|
||||
// `Encryption` is the key info for server-side-encryption with customer
|
||||
// provided key. If it is nil, no encryption is performed.
|
||||
Encryption encrypt.ServerSide
|
||||
|
||||
// `userMeta` is the user-metadata key-value pairs to be set on the
|
||||
// destination. The keys are automatically prefixed with `x-amz-meta-`
|
||||
// if needed. If nil is passed, and if only a single source (of any
|
||||
// size) is provided in the ComposeObject call, then metadata from the
|
||||
// source is copied to the destination.
|
||||
// if no user-metadata is provided, it is copied from source
|
||||
// (when there is only once source object in the compose
|
||||
// request)
|
||||
userMetadata map[string]string
|
||||
UserMeta map[string]string
|
||||
|
||||
// `userTags` is the user defined object tags to be set on destination.
|
||||
// This will be set only if the `replaceTags` field is set to true.
|
||||
// Otherwise this field is ignored
|
||||
UserTags map[string]string
|
||||
ReplaceTags bool
|
||||
}
|
||||
|
||||
// Process custom-metadata to remove a `x-amz-meta-` prefix if
|
||||
// present and validate that keys are distinct (after this
|
||||
// prefix removal).
|
||||
func filterCustomMeta(userMeta map[string]string) (map[string]string, error) {
|
||||
m := make(map[string]string)
|
||||
for k, v := range userMeta {
|
||||
if strings.HasPrefix(strings.ToLower(k), "x-amz-meta-") {
|
||||
k = k[len("x-amz-meta-"):]
|
||||
}
|
||||
if _, ok := m[k]; ok {
|
||||
return nil, ErrInvalidArgument(fmt.Sprintf("Cannot add both %s and x-amz-meta-%s keys as custom metadata", k, k))
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// NewDestinationInfo - creates a compose-object/copy-source
|
||||
// destination info object.
|
||||
//
|
||||
// `encSSEC` is the key info for server-side-encryption with customer
|
||||
// `sse` is the key info for server-side-encryption with customer
|
||||
// provided key. If it is nil, no encryption is performed.
|
||||
//
|
||||
// `userMeta` is the user-metadata key-value pairs to be set on the
|
||||
@@ -63,26 +98,41 @@ func NewDestinationInfo(bucket, object string, sse encrypt.ServerSide, userMeta
|
||||
if err = s3utils.CheckValidObjectName(object); err != nil {
|
||||
return d, err
|
||||
}
|
||||
|
||||
// Process custom-metadata to remove a `x-amz-meta-` prefix if
|
||||
// present and validate that keys are distinct (after this
|
||||
// prefix removal).
|
||||
m := make(map[string]string)
|
||||
for k, v := range userMeta {
|
||||
if strings.HasPrefix(strings.ToLower(k), "x-amz-meta-") {
|
||||
k = k[len("x-amz-meta-"):]
|
||||
}
|
||||
if _, ok := m[k]; ok {
|
||||
return d, ErrInvalidArgument(fmt.Sprintf("Cannot add both %s and x-amz-meta-%s keys as custom metadata", k, k))
|
||||
}
|
||||
m[k] = v
|
||||
m, err := filterCustomMeta(userMeta)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
opts := DestInfoOptions{
|
||||
Encryption: sse,
|
||||
UserMeta: m,
|
||||
UserTags: nil,
|
||||
ReplaceTags: false,
|
||||
}
|
||||
|
||||
return DestinationInfo{
|
||||
bucket: bucket,
|
||||
object: object,
|
||||
encryption: sse,
|
||||
userMetadata: m,
|
||||
bucket: bucket,
|
||||
object: object,
|
||||
opts: opts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewDestinationInfoWithOptions - creates a compose-object/copy-source
|
||||
// destination info object.
|
||||
func NewDestinationInfoWithOptions(bucket, object string, destOpts DestInfoOptions) (d DestinationInfo, err error) {
|
||||
// Input validation.
|
||||
if err = s3utils.CheckValidBucketName(bucket); err != nil {
|
||||
return d, err
|
||||
}
|
||||
if err = s3utils.CheckValidObjectName(object); err != nil {
|
||||
return d, err
|
||||
}
|
||||
destOpts.UserMeta, err = filterCustomMeta(destOpts.UserMeta)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
return DestinationInfo{
|
||||
bucket: bucket,
|
||||
object: object,
|
||||
opts: destOpts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -93,14 +143,14 @@ func NewDestinationInfo(bucket, object string, sse encrypt.ServerSide, userMeta
|
||||
// `REPLACE`, so that metadata headers from the source are not copied
|
||||
// over.
|
||||
func (d *DestinationInfo) getUserMetaHeadersMap(withCopyDirectiveHeader bool) map[string]string {
|
||||
if len(d.userMetadata) == 0 {
|
||||
if len(d.opts.UserMeta) == 0 {
|
||||
return nil
|
||||
}
|
||||
r := make(map[string]string)
|
||||
if withCopyDirectiveHeader {
|
||||
r["x-amz-metadata-directive"] = "REPLACE"
|
||||
}
|
||||
for k, v := range d.userMetadata {
|
||||
for k, v := range d.opts.UserMeta {
|
||||
if isAmzHeader(k) || isStandardHeader(k) || isStorageClassHeader(k) {
|
||||
r[k] = v
|
||||
} else {
|
||||
@@ -447,7 +497,7 @@ func (c Client) ComposeObjectWithProgress(dst DestinationInfo, srcs []SourceInfo
|
||||
metaHeaders[k] = v
|
||||
}
|
||||
|
||||
uploadID, err := c.newUploadID(ctx, dst.bucket, dst.object, PutObjectOptions{ServerSideEncryption: dst.encryption, UserMetadata: metaHeaders})
|
||||
uploadID, err := c.newUploadID(ctx, dst.bucket, dst.object, PutObjectOptions{ServerSideEncryption: dst.opts.Encryption, UserMetadata: metaHeaders})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -461,8 +511,8 @@ func (c Client) ComposeObjectWithProgress(dst DestinationInfo, srcs []SourceInfo
|
||||
encrypt.SSECopy(src.encryption).Marshal(h)
|
||||
}
|
||||
// Add destination encryption headers
|
||||
if dst.encryption != nil {
|
||||
dst.encryption.Marshal(h)
|
||||
if dst.opts.Encryption != nil {
|
||||
dst.opts.Encryption.Marshal(h)
|
||||
}
|
||||
|
||||
// calculate start/end indices of parts after
|
||||
|
||||
45
vendor/github.com/minio/minio-go/v6/api-datatypes.go
сгенерированный
поставляемый
45
vendor/github.com/minio/minio-go/v6/api-datatypes.go
сгенерированный
поставляемый
@@ -18,6 +18,8 @@
|
||||
package minio
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@@ -30,6 +32,36 @@ type BucketInfo struct {
|
||||
CreationDate time.Time `json:"creationDate"`
|
||||
}
|
||||
|
||||
// StringMap represents map with custom UnmarshalXML
|
||||
type StringMap map[string]string
|
||||
|
||||
// UnmarshalXML unmarshals the XML into a map of string to strings,
|
||||
// creating a key in the map for each tag and setting it's value to the
|
||||
// tags contents.
|
||||
//
|
||||
// The fact this function is on the pointer of Map is important, so that
|
||||
// if m is nil it can be initialized, which is often the case if m is
|
||||
// nested in another xml structurel. This is also why the first thing done
|
||||
// on the first line is initialize it.
|
||||
func (m *StringMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
*m = StringMap{}
|
||||
type xmlMapEntry struct {
|
||||
XMLName xml.Name
|
||||
Value string `xml:",chardata"`
|
||||
}
|
||||
for {
|
||||
var e xmlMapEntry
|
||||
err := d.Decode(&e)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
(*m)[e.XMLName.Local] = e.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectInfo container for object metadata.
|
||||
type ObjectInfo struct {
|
||||
// An ETag is optionally set to md5sum of an object. In case of multipart objects,
|
||||
@@ -47,12 +79,25 @@ type ObjectInfo struct {
|
||||
// eg: x-amz-meta-*, content-encoding etc.
|
||||
Metadata http.Header `json:"metadata" xml:"-"`
|
||||
|
||||
// x-amz-meta-* headers stripped "x-amz-meta-" prefix containing the first value.
|
||||
UserMetadata StringMap `json:"userMetadata"`
|
||||
|
||||
// Owner name.
|
||||
Owner struct {
|
||||
DisplayName string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
} `json:"owner"`
|
||||
|
||||
// ACL grant.
|
||||
Grant []struct {
|
||||
Grantee struct {
|
||||
ID string `xml:"ID"`
|
||||
DisplayName string `xml:"DisplayName"`
|
||||
URI string `xml:"URI"`
|
||||
} `xml:"Grantee"`
|
||||
Permission string `xml:"Permission"`
|
||||
} `xml:"Grant"`
|
||||
|
||||
// The class of storage used to store the object.
|
||||
StorageClass string `json:"storageClass"`
|
||||
|
||||
|
||||
4
vendor/github.com/minio/minio-go/v6/api-error-response.go
сгенерированный
поставляемый
4
vendor/github.com/minio/minio-go/v6/api-error-response.go
сгенерированный
поставляемый
@@ -51,6 +51,9 @@ type ErrorResponse struct {
|
||||
// only in HEAD bucket and ListObjects response.
|
||||
Region string
|
||||
|
||||
// Captures the server string returned in response header.
|
||||
Server string
|
||||
|
||||
// Underlying HTTP status code for the returned error
|
||||
StatusCode int `xml:"-" json:"-"`
|
||||
}
|
||||
@@ -105,6 +108,7 @@ func httpRespToErrorResponse(resp *http.Response, bucketName, objectName string)
|
||||
|
||||
errResp := ErrorResponse{
|
||||
StatusCode: resp.StatusCode,
|
||||
Server: resp.Header.Get("Server"),
|
||||
}
|
||||
|
||||
err := xmlDecoder(resp.Body, &errResp)
|
||||
|
||||
140
vendor/github.com/minio/minio-go/v6/api-get-object-acl-context.go
сгенерированный
поставляемый
Обычный файл
140
vendor/github.com/minio/minio-go/v6/api-get-object-acl-context.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
|
||||
* Copyright 2018 MinIO, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package minio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type accessControlPolicy struct {
|
||||
Owner struct {
|
||||
ID string `xml:"ID"`
|
||||
DisplayName string `xml:"DisplayName"`
|
||||
} `xml:"Owner"`
|
||||
AccessControlList struct {
|
||||
Grant []struct {
|
||||
Grantee struct {
|
||||
ID string `xml:"ID"`
|
||||
DisplayName string `xml:"DisplayName"`
|
||||
URI string `xml:"URI"`
|
||||
} `xml:"Grantee"`
|
||||
Permission string `xml:"Permission"`
|
||||
} `xml:"Grant"`
|
||||
} `xml:"AccessControlList"`
|
||||
}
|
||||
|
||||
//GetObjectACLWithContext get object ACLs
|
||||
func (c Client) GetObjectACLWithContext(ctx context.Context, bucketName, objectName string) (*ObjectInfo, error) {
|
||||
resp, err := c.executeMethod(ctx, "GET", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: url.Values{
|
||||
"acl": []string{""},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer closeResponse(resp)
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
|
||||
res := &accessControlPolicy{}
|
||||
|
||||
if err := xmlDecoder(resp.Body, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objInfo, err := c.statObject(ctx, bucketName, objectName, StatObjectOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objInfo.Owner.DisplayName = res.Owner.DisplayName
|
||||
objInfo.Owner.ID = res.Owner.ID
|
||||
|
||||
objInfo.Grant = append(objInfo.Grant, res.AccessControlList.Grant...)
|
||||
|
||||
cannedACL := getCannedACL(res)
|
||||
if cannedACL != "" {
|
||||
objInfo.Metadata.Add("X-Amz-Acl", cannedACL)
|
||||
return &objInfo, nil
|
||||
}
|
||||
|
||||
grantACL := getAmzGrantACL(res)
|
||||
for k, v := range grantACL {
|
||||
objInfo.Metadata[k] = v
|
||||
}
|
||||
|
||||
return &objInfo, nil
|
||||
}
|
||||
|
||||
func getCannedACL(aCPolicy *accessControlPolicy) string {
|
||||
grants := aCPolicy.AccessControlList.Grant
|
||||
|
||||
switch {
|
||||
case len(grants) == 1:
|
||||
if grants[0].Grantee.URI == "" && grants[0].Permission == "FULL_CONTROL" {
|
||||
return "private"
|
||||
}
|
||||
case len(grants) == 2:
|
||||
for _, g := range grants {
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" && g.Permission == "READ" {
|
||||
return "authenticated-read"
|
||||
}
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "READ" {
|
||||
return "public-read"
|
||||
}
|
||||
if g.Permission == "READ" && g.Grantee.ID == aCPolicy.Owner.ID {
|
||||
return "bucket-owner-read"
|
||||
}
|
||||
}
|
||||
case len(grants) == 3:
|
||||
for _, g := range grants {
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "WRITE" {
|
||||
return "public-read-write"
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getAmzGrantACL(aCPolicy *accessControlPolicy) map[string][]string {
|
||||
grants := aCPolicy.AccessControlList.Grant
|
||||
res := map[string][]string{}
|
||||
|
||||
for _, g := range grants {
|
||||
switch {
|
||||
case g.Permission == "READ":
|
||||
res["X-Amz-Grant-Read"] = append(res["X-Amz-Grant-Read"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "WRITE":
|
||||
res["X-Amz-Grant-Write"] = append(res["X-Amz-Grant-Write"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "READ_ACP":
|
||||
res["X-Amz-Grant-Read-Acp"] = append(res["X-Amz-Grant-Read-Acp"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "WRITE_ACP":
|
||||
res["X-Amz-Grant-Write-Acp"] = append(res["X-Amz-Grant-Write-Acp"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "FULL_CONTROL":
|
||||
res["X-Amz-Grant-Full-Control"] = append(res["X-Amz-Grant-Full-Control"], "id="+g.Grantee.ID)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
111
vendor/github.com/minio/minio-go/v6/api-get-object-acl.go
сгенерированный
поставляемый
111
vendor/github.com/minio/minio-go/v6/api-get-object-acl.go
сгенерированный
поставляемый
@@ -19,118 +19,9 @@ package minio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type accessControlPolicy struct {
|
||||
Owner struct {
|
||||
ID string `xml:"ID"`
|
||||
DisplayName string `xml:"DisplayName"`
|
||||
} `xml:"Owner"`
|
||||
AccessControlList struct {
|
||||
Grant []struct {
|
||||
Grantee struct {
|
||||
ID string `xml:"ID"`
|
||||
DisplayName string `xml:"DisplayName"`
|
||||
URI string `xml:"URI"`
|
||||
} `xml:"Grantee"`
|
||||
Permission string `xml:"Permission"`
|
||||
} `xml:"Grant"`
|
||||
} `xml:"AccessControlList"`
|
||||
}
|
||||
|
||||
//GetObjectACL get object ACLs
|
||||
func (c Client) GetObjectACL(bucketName, objectName string) (*ObjectInfo, error) {
|
||||
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: url.Values{
|
||||
"acl": []string{""},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer closeResponse(resp)
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
|
||||
res := &accessControlPolicy{}
|
||||
|
||||
if err := xmlDecoder(resp.Body, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objInfo, err := c.statObject(context.Background(), bucketName, objectName, StatObjectOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cannedACL := getCannedACL(res)
|
||||
if cannedACL != "" {
|
||||
objInfo.Metadata.Add("X-Amz-Acl", cannedACL)
|
||||
return &objInfo, nil
|
||||
}
|
||||
|
||||
grantACL := getAmzGrantACL(res)
|
||||
for k, v := range grantACL {
|
||||
objInfo.Metadata[k] = v
|
||||
}
|
||||
|
||||
return &objInfo, nil
|
||||
}
|
||||
|
||||
func getCannedACL(aCPolicy *accessControlPolicy) string {
|
||||
grants := aCPolicy.AccessControlList.Grant
|
||||
|
||||
switch {
|
||||
case len(grants) == 1:
|
||||
if grants[0].Grantee.URI == "" && grants[0].Permission == "FULL_CONTROL" {
|
||||
return "private"
|
||||
}
|
||||
case len(grants) == 2:
|
||||
for _, g := range grants {
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" && g.Permission == "READ" {
|
||||
return "authenticated-read"
|
||||
}
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "READ" {
|
||||
return "public-read"
|
||||
}
|
||||
if g.Permission == "READ" && g.Grantee.ID == aCPolicy.Owner.ID {
|
||||
return "bucket-owner-read"
|
||||
}
|
||||
}
|
||||
case len(grants) == 3:
|
||||
for _, g := range grants {
|
||||
if g.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" && g.Permission == "WRITE" {
|
||||
return "public-read-write"
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getAmzGrantACL(aCPolicy *accessControlPolicy) map[string][]string {
|
||||
grants := aCPolicy.AccessControlList.Grant
|
||||
res := map[string][]string{}
|
||||
|
||||
for _, g := range grants {
|
||||
switch {
|
||||
case g.Permission == "READ":
|
||||
res["X-Amz-Grant-Read"] = append(res["X-Amz-Grant-Read"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "WRITE":
|
||||
res["X-Amz-Grant-Write"] = append(res["X-Amz-Grant-Write"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "READ_ACP":
|
||||
res["X-Amz-Grant-Read-Acp"] = append(res["X-Amz-Grant-Read-Acp"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "WRITE_ACP":
|
||||
res["X-Amz-Grant-Write-Acp"] = append(res["X-Amz-Grant-Write-Acp"], "id="+g.Grantee.ID)
|
||||
case g.Permission == "FULL_CONTROL":
|
||||
res["X-Amz-Grant-Full-Control"] = append(res["X-Amz-Grant-Full-Control"], "id="+g.Grantee.ID)
|
||||
}
|
||||
}
|
||||
return res
|
||||
return c.GetObjectACLWithContext(context.Background(), bucketName, objectName)
|
||||
}
|
||||
|
||||
21
vendor/github.com/minio/minio-go/v6/api-get-object.go
сгенерированный
поставляемый
21
vendor/github.com/minio/minio-go/v6/api-get-object.go
сгенерированный
поставляемый
@@ -45,6 +45,14 @@ func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Detect if snowball is server location we are talking to.
|
||||
var snowball bool
|
||||
if location, ok := c.bucketLocCache.Get(bucketName); ok {
|
||||
if location == "snowball" {
|
||||
snowball = true
|
||||
}
|
||||
}
|
||||
|
||||
var httpReader io.ReadCloser
|
||||
var objectInfo ObjectInfo
|
||||
var err error
|
||||
@@ -136,7 +144,10 @@ func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName
|
||||
} else if req.settingObjectInfo { // Request is just to get objectInfo.
|
||||
// Remove range header if already set, for stat Operations to get original file size.
|
||||
delete(opts.headers, "Range")
|
||||
if etag != "" {
|
||||
// Check whether this is snowball
|
||||
// if yes do not use If-Match feature
|
||||
// it doesn't work.
|
||||
if etag != "" && !snowball {
|
||||
opts.SetMatchETag(etag)
|
||||
}
|
||||
objectInfo, err := c.statObject(ctx, bucketName, objectName, StatObjectOptions{opts})
|
||||
@@ -159,7 +170,10 @@ func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName
|
||||
// new ones when they haven't been already.
|
||||
// All readAt requests are new requests.
|
||||
if req.DidOffsetChange || !req.beenRead {
|
||||
if etag != "" {
|
||||
// Check whether this is snowball
|
||||
// if yes do not use If-Match feature
|
||||
// it doesn't work.
|
||||
if etag != "" && !snowball {
|
||||
opts.SetMatchETag(etag)
|
||||
}
|
||||
if httpReader != nil {
|
||||
@@ -622,8 +636,7 @@ func (c Client) getObject(ctx context.Context, bucketName, objectName string, op
|
||||
}
|
||||
|
||||
// Trim off the odd double quotes from ETag in the beginning and end.
|
||||
md5sum := strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
|
||||
md5sum = strings.TrimSuffix(md5sum, "\"")
|
||||
md5sum := trimEtag(resp.Header.Get("ETag"))
|
||||
|
||||
// Parse the date.
|
||||
date, err := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
|
||||
|
||||
113
vendor/github.com/minio/minio-go/v6/api-list.go
сгенерированный
поставляемый
113
vendor/github.com/minio/minio-go/v6/api-list.go
сгенерированный
поставляемый
@@ -19,11 +19,9 @@ package minio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
@@ -39,8 +37,23 @@ import (
|
||||
// }
|
||||
//
|
||||
func (c Client) ListBuckets() ([]BucketInfo, error) {
|
||||
return c.ListBucketsWithContext(context.Background())
|
||||
}
|
||||
|
||||
// ListBucketsWithContext list all buckets owned by this authenticated user,
|
||||
// accepts a context for facilitate cancellation.
|
||||
//
|
||||
// This call requires explicit authentication, no anonymous requests are
|
||||
// allowed for listing buckets.
|
||||
//
|
||||
// api := client.New(....)
|
||||
// for message := range api.ListBucketsWithContext(context.Background()) {
|
||||
// fmt.Println(message)
|
||||
// }
|
||||
//
|
||||
func (c Client) ListBucketsWithContext(ctx context.Context) ([]BucketInfo, error) {
|
||||
// Execute GET on service.
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{contentSHA256Hex: emptySHA256Hex})
|
||||
resp, err := c.executeMethod(ctx, "GET", requestMetadata{contentSHA256Hex: emptySHA256Hex})
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -60,9 +73,13 @@ func (c Client) ListBuckets() ([]BucketInfo, error) {
|
||||
|
||||
/// Bucket Read Operations.
|
||||
|
||||
// ListObjectsV2 lists all objects matching the objectPrefix from
|
||||
// the specified bucket. If recursion is enabled it would list
|
||||
// all subdirectories and all its contents.
|
||||
// ListObjectsV2WithMetadata lists all objects matching the objectPrefix
|
||||
// from the specified bucket. If recursion is enabled it would list
|
||||
// all subdirectories and all its contents. This call adds
|
||||
// UserMetadata information as well for each object.
|
||||
//
|
||||
// This is a MinIO extension, this will not work against other S3
|
||||
// compatible object storage vendors.
|
||||
//
|
||||
// Your input parameters are just bucketName, objectPrefix, recursive
|
||||
// and a done channel for pro-actively closing the internal go
|
||||
@@ -76,11 +93,24 @@ func (c Client) ListBuckets() ([]BucketInfo, error) {
|
||||
// defer close(doneCh)
|
||||
// // Recursively list all objects in 'mytestbucket'
|
||||
// recursive := true
|
||||
// for message := range api.ListObjectsV2("mytestbucket", "starthere", recursive, doneCh) {
|
||||
// // Add metadata
|
||||
// metadata := true
|
||||
// for message := range api.ListObjectsV2WithMetadata("mytestbucket", "starthere", recursive, doneCh) {
|
||||
// fmt.Println(message)
|
||||
// }
|
||||
//
|
||||
func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan ObjectInfo {
|
||||
func (c Client) ListObjectsV2WithMetadata(bucketName, objectPrefix string, recursive bool,
|
||||
doneCh <-chan struct{}) <-chan ObjectInfo {
|
||||
// Check whether this is snowball region, if yes ListObjectsV2 doesn't work, fallback to listObjectsV1.
|
||||
if location, ok := c.bucketLocCache.Get(bucketName); ok {
|
||||
if location == "snowball" {
|
||||
return c.ListObjects(bucketName, objectPrefix, recursive, doneCh)
|
||||
}
|
||||
}
|
||||
return c.listObjectsV2(bucketName, objectPrefix, recursive, true, doneCh)
|
||||
}
|
||||
|
||||
func (c Client) listObjectsV2(bucketName, objectPrefix string, recursive, metadata bool, doneCh <-chan struct{}) <-chan ObjectInfo {
|
||||
// Allocate new list objects channel.
|
||||
objectStatCh := make(chan ObjectInfo, 1)
|
||||
// Default listing is delimited at "/"
|
||||
@@ -118,7 +148,8 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
|
||||
var continuationToken string
|
||||
for {
|
||||
// Get list of objects a maximum of 1000 per request.
|
||||
result, err := c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, 1000, "")
|
||||
result, err := c.listObjectsV2Query(bucketName, objectPrefix, continuationToken,
|
||||
fetchOwner, metadata, delimiter, 0, "")
|
||||
if err != nil {
|
||||
objectStatCh <- ObjectInfo{
|
||||
Err: err,
|
||||
@@ -128,6 +159,7 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
|
||||
|
||||
// If contents are available loop through and send over channel.
|
||||
for _, object := range result.Contents {
|
||||
object.ETag = trimEtag(object.ETag)
|
||||
select {
|
||||
// Send object content.
|
||||
case objectStatCh <- object:
|
||||
@@ -163,6 +195,36 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
|
||||
return objectStatCh
|
||||
}
|
||||
|
||||
// ListObjectsV2 lists all objects matching the objectPrefix from
|
||||
// the specified bucket. If recursion is enabled it would list
|
||||
// all subdirectories and all its contents.
|
||||
//
|
||||
// Your input parameters are just bucketName, objectPrefix, recursive
|
||||
// and a done channel for pro-actively closing the internal go
|
||||
// routine. If you enable recursive as 'true' this function will
|
||||
// return back all the objects in a given bucket name and object
|
||||
// prefix.
|
||||
//
|
||||
// api := client.New(....)
|
||||
// // Create a done channel.
|
||||
// doneCh := make(chan struct{})
|
||||
// defer close(doneCh)
|
||||
// // Recursively list all objects in 'mytestbucket'
|
||||
// recursive := true
|
||||
// for message := range api.ListObjectsV2("mytestbucket", "starthere", recursive, doneCh) {
|
||||
// fmt.Println(message)
|
||||
// }
|
||||
//
|
||||
func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, doneCh <-chan struct{}) <-chan ObjectInfo {
|
||||
// Check whether this is snowball region, if yes ListObjectsV2 doesn't work, fallback to listObjectsV1.
|
||||
if location, ok := c.bucketLocCache.Get(bucketName); ok {
|
||||
if location == "snowball" {
|
||||
return c.ListObjects(bucketName, objectPrefix, recursive, doneCh)
|
||||
}
|
||||
}
|
||||
return c.listObjectsV2(bucketName, objectPrefix, recursive, false, doneCh)
|
||||
}
|
||||
|
||||
// listObjectsV2Query - (List Objects V2) - List some or all (up to 1000) of the objects in a bucket.
|
||||
//
|
||||
// You can use the request parameters as selection criteria to return a subset of the objects in a bucket.
|
||||
@@ -173,7 +235,8 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
|
||||
// ?prefix - Limits the response to keys that begin with the specified prefix.
|
||||
// ?max-keys - Sets the maximum number of keys returned in the response body.
|
||||
// ?start-after - Specifies the key to start after when listing objects in a bucket.
|
||||
func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int, startAfter string) (ListBucketV2Result, error) {
|
||||
// ?metadata - Specifies if we want metadata for the objects as part of list operation.
|
||||
func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken string, fetchOwner, metadata bool, delimiter string, maxkeys int, startAfter string) (ListBucketV2Result, error) {
|
||||
// Validate bucket name.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return ListBucketV2Result{}, err
|
||||
@@ -189,6 +252,10 @@ func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken s
|
||||
// Always set list-type in ListObjects V2
|
||||
urlValues.Set("list-type", "2")
|
||||
|
||||
if metadata {
|
||||
urlValues.Set("metadata", "true")
|
||||
}
|
||||
|
||||
// Always set encoding-type in ListObjects V2
|
||||
urlValues.Set("encoding-type", "url")
|
||||
|
||||
@@ -243,7 +310,10 @@ func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken s
|
||||
// This is an additional verification check to make
|
||||
// sure proper responses are received.
|
||||
if listBucketResult.IsTruncated && listBucketResult.NextContinuationToken == "" {
|
||||
return listBucketResult, errors.New("Truncated response should have continuation token set")
|
||||
return listBucketResult, ErrorResponse{
|
||||
Code: "NotImplemented",
|
||||
Message: "Truncated response should have continuation token set",
|
||||
}
|
||||
}
|
||||
|
||||
for i, obj := range listBucketResult.Contents {
|
||||
@@ -319,7 +389,7 @@ func (c Client) ListObjects(bucketName, objectPrefix string, recursive bool, don
|
||||
var marker string
|
||||
for {
|
||||
// Get list of objects a maximum of 1000 per request.
|
||||
result, err := c.listObjectsQuery(bucketName, objectPrefix, marker, delimiter, 1000)
|
||||
result, err := c.listObjectsQuery(bucketName, objectPrefix, marker, delimiter, 0)
|
||||
if err != nil {
|
||||
objectStatCh <- ObjectInfo{
|
||||
Err: err,
|
||||
@@ -513,7 +583,7 @@ func (c Client) listIncompleteUploads(bucketName, objectPrefix string, recursive
|
||||
var uploadIDMarker string
|
||||
for {
|
||||
// list all multipart uploads.
|
||||
result, err := c.listMultipartUploadsQuery(bucketName, objectMarker, uploadIDMarker, objectPrefix, delimiter, 1000)
|
||||
result, err := c.listMultipartUploadsQuery(bucketName, objectMarker, uploadIDMarker, objectPrefix, delimiter, 0)
|
||||
if err != nil {
|
||||
objectMultipartStatCh <- ObjectMultipartInfo{
|
||||
Err: err,
|
||||
@@ -600,11 +670,10 @@ func (c Client) listMultipartUploadsQuery(bucketName, keyMarker, uploadIDMarker,
|
||||
urlValues.Set("encoding-type", "url")
|
||||
|
||||
// maxUploads should be 1000 or less.
|
||||
if maxUploads == 0 || maxUploads > 1000 {
|
||||
maxUploads = 1000
|
||||
if maxUploads > 0 {
|
||||
// Set max-uploads.
|
||||
urlValues.Set("max-uploads", fmt.Sprintf("%d", maxUploads))
|
||||
}
|
||||
// Set max-uploads.
|
||||
urlValues.Set("max-uploads", fmt.Sprintf("%d", maxUploads))
|
||||
|
||||
// Execute GET on bucketName to list multipart uploads.
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
|
||||
@@ -669,8 +738,7 @@ func (c Client) listObjectParts(bucketName, objectName, uploadID string) (partsI
|
||||
// Append to parts info.
|
||||
for _, part := range listObjPartsResult.ObjectParts {
|
||||
// Trim off the odd double quotes from ETag in the beginning and end.
|
||||
part.ETag = strings.TrimPrefix(part.ETag, "\"")
|
||||
part.ETag = strings.TrimSuffix(part.ETag, "\"")
|
||||
part.ETag = trimEtag(part.ETag)
|
||||
partsInfo[part.PartNumber] = part
|
||||
}
|
||||
// Keep part number marker, for the next iteration.
|
||||
@@ -740,11 +808,10 @@ func (c Client) listObjectPartsQuery(bucketName, objectName, uploadID string, pa
|
||||
urlValues.Set("uploadId", uploadID)
|
||||
|
||||
// maxParts should be 1000 or less.
|
||||
if maxParts == 0 || maxParts > 1000 {
|
||||
maxParts = 1000
|
||||
if maxParts > 0 {
|
||||
// Set max parts.
|
||||
urlValues.Set("max-parts", fmt.Sprintf("%d", maxParts))
|
||||
}
|
||||
// Set max parts.
|
||||
urlValues.Set("max-parts", fmt.Sprintf("%d", maxParts))
|
||||
|
||||
// Execute GET on objectName to get list of parts.
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
|
||||
|
||||
232
vendor/github.com/minio/minio-go/v6/api-object-lock.go
сгенерированный
поставляемый
Обычный файл
232
vendor/github.com/minio/minio-go/v6/api-object-lock.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
|
||||
* Copyright 2019 MinIO, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package minio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
|
||||
// RetentionMode - object retention mode.
|
||||
type RetentionMode string
|
||||
|
||||
const (
|
||||
// Governance - goverance mode.
|
||||
Governance RetentionMode = "GOVERNANCE"
|
||||
|
||||
// Compliance - compliance mode.
|
||||
Compliance RetentionMode = "COMPLIANCE"
|
||||
)
|
||||
|
||||
func (r RetentionMode) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
// IsValid - check whether this retention mode is valid or not.
|
||||
func (r RetentionMode) IsValid() bool {
|
||||
return r == Governance || r == Compliance
|
||||
}
|
||||
|
||||
// ValidityUnit - retention validity unit.
|
||||
type ValidityUnit string
|
||||
|
||||
const (
|
||||
// Days - denotes no. of days.
|
||||
Days ValidityUnit = "DAYS"
|
||||
|
||||
// Years - denotes no. of years.
|
||||
Years ValidityUnit = "YEARS"
|
||||
)
|
||||
|
||||
func (unit ValidityUnit) String() string {
|
||||
return string(unit)
|
||||
}
|
||||
|
||||
// IsValid - check whether this validity unit is valid or not.
|
||||
func (unit ValidityUnit) isValid() bool {
|
||||
return unit == Days || unit == Years
|
||||
}
|
||||
|
||||
// Retention - bucket level retention configuration.
|
||||
type Retention struct {
|
||||
Mode RetentionMode
|
||||
Validity time.Duration
|
||||
}
|
||||
|
||||
func (r Retention) String() string {
|
||||
return fmt.Sprintf("{Mode:%v, Validity:%v}", r.Mode, r.Validity)
|
||||
}
|
||||
|
||||
// IsEmpty - returns whether retention is empty or not.
|
||||
func (r Retention) IsEmpty() bool {
|
||||
return r.Mode == "" || r.Validity == 0
|
||||
}
|
||||
|
||||
// objectLockConfig - object lock configuration specified in
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/Type_API_ObjectLockConfiguration.html
|
||||
type objectLockConfig struct {
|
||||
XMLNS string `xml:"xmlns,attr,omitempty"`
|
||||
XMLName xml.Name `xml:"ObjectLockConfiguration"`
|
||||
ObjectLockEnabled string `xml:"ObjectLockEnabled"`
|
||||
Rule *struct {
|
||||
DefaultRetention struct {
|
||||
Mode RetentionMode `xml:"Mode"`
|
||||
Days *uint `xml:"Days"`
|
||||
Years *uint `xml:"Years"`
|
||||
} `xml:"DefaultRetention"`
|
||||
} `xml:"Rule,omitempty"`
|
||||
}
|
||||
|
||||
func newObjectLockConfig(mode *RetentionMode, validity *uint, unit *ValidityUnit) (*objectLockConfig, error) {
|
||||
config := &objectLockConfig{
|
||||
ObjectLockEnabled: "Enabled",
|
||||
}
|
||||
|
||||
if mode != nil && validity != nil && unit != nil {
|
||||
if !mode.IsValid() {
|
||||
return nil, fmt.Errorf("invalid retention mode `%v`", mode)
|
||||
}
|
||||
|
||||
if !unit.isValid() {
|
||||
return nil, fmt.Errorf("invalid validity unit `%v`", unit)
|
||||
}
|
||||
|
||||
config.Rule = &struct {
|
||||
DefaultRetention struct {
|
||||
Mode RetentionMode `xml:"Mode"`
|
||||
Days *uint `xml:"Days"`
|
||||
Years *uint `xml:"Years"`
|
||||
} `xml:"DefaultRetention"`
|
||||
}{}
|
||||
|
||||
config.Rule.DefaultRetention.Mode = *mode
|
||||
if *unit == Days {
|
||||
config.Rule.DefaultRetention.Days = validity
|
||||
} else {
|
||||
config.Rule.DefaultRetention.Years = validity
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
if mode == nil && validity == nil && unit == nil {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("all of retention mode, validity and validity unit must be passed")
|
||||
}
|
||||
|
||||
// SetBucketObjectLockConfig sets object lock configuration in given bucket. mode, validity and unit are either all set or all nil.
|
||||
func (c Client) SetBucketObjectLockConfig(bucketName string, mode *RetentionMode, validity *uint, unit *ValidityUnit) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("object-lock", "")
|
||||
|
||||
config, err := newObjectLockConfig(mode, validity, unit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configData, err := xml.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqMetadata := requestMetadata{
|
||||
bucketName: bucketName,
|
||||
queryValues: urlValues,
|
||||
contentBody: bytes.NewReader(configData),
|
||||
contentLength: int64(len(configData)),
|
||||
contentMD5Base64: sumMD5Base64(configData),
|
||||
contentSHA256Hex: sum256Hex(configData),
|
||||
}
|
||||
|
||||
// Execute PUT bucket object lock configuration.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp, bucketName, "")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBucketObjectLockConfig gets object lock configuration of given bucket.
|
||||
func (c Client) GetBucketObjectLockConfig(bucketName string) (mode *RetentionMode, validity *uint, unit *ValidityUnit, err error) {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("object-lock", "")
|
||||
|
||||
// Execute GET on bucket to list objects.
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
queryValues: urlValues,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
})
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, nil, nil, httpRespToErrorResponse(resp, bucketName, "")
|
||||
}
|
||||
}
|
||||
config := &objectLockConfig{}
|
||||
if err = xml.NewDecoder(resp.Body).Decode(config); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if config.Rule != nil {
|
||||
mode = &config.Rule.DefaultRetention.Mode
|
||||
if config.Rule.DefaultRetention.Days != nil {
|
||||
validity = config.Rule.DefaultRetention.Days
|
||||
days := Days
|
||||
unit = &days
|
||||
} else {
|
||||
validity = config.Rule.DefaultRetention.Years
|
||||
years := Years
|
||||
unit = &years
|
||||
}
|
||||
|
||||
return mode, validity, unit, nil
|
||||
}
|
||||
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
168
vendor/github.com/minio/minio-go/v6/api-object-retention.go
сгенерированный
поставляемый
Обычный файл
168
vendor/github.com/minio/minio-go/v6/api-object-retention.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
|
||||
* Copyright 2019 MinIO, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package minio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
|
||||
// objectRetention - object retention specified in
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/Type_API_ObjectLockConfiguration.html
|
||||
type objectRetention struct {
|
||||
XMLNS string `xml:"xmlns,attr,omitempty"`
|
||||
XMLName xml.Name `xml:"Retention"`
|
||||
Mode RetentionMode `xml:"Mode"`
|
||||
RetainUntilDate time.Time `type:"timestamp" timestampFormat:"iso8601" xml:"RetainUntilDate"`
|
||||
}
|
||||
|
||||
func newObjectRetention(mode *RetentionMode, date *time.Time) (*objectRetention, error) {
|
||||
if mode == nil {
|
||||
return nil, fmt.Errorf("Mode not set")
|
||||
}
|
||||
|
||||
if date == nil {
|
||||
return nil, fmt.Errorf("RetainUntilDate not set")
|
||||
}
|
||||
|
||||
if !mode.IsValid() {
|
||||
return nil, fmt.Errorf("invalid retention mode `%v`", mode)
|
||||
}
|
||||
objectRetention := &objectRetention{
|
||||
Mode: *mode,
|
||||
RetainUntilDate: *date,
|
||||
}
|
||||
return objectRetention, nil
|
||||
}
|
||||
|
||||
// PutObjectRetentionOptions represents options specified by user for PutObject call
|
||||
type PutObjectRetentionOptions struct {
|
||||
GovernanceBypass bool
|
||||
Mode *RetentionMode
|
||||
RetainUntilDate *time.Time
|
||||
VersionID string
|
||||
}
|
||||
|
||||
// PutObjectRetention : sets object retention for a given object and versionID.
|
||||
func (c Client) PutObjectRetention(bucketName, objectName string, opts PutObjectRetentionOptions) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s3utils.CheckValidObjectName(objectName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("retention", "")
|
||||
|
||||
if opts.VersionID != "" {
|
||||
urlValues.Set("versionId", opts.VersionID)
|
||||
}
|
||||
|
||||
retention, err := newObjectRetention(opts.Mode, opts.RetainUntilDate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retentionData, err := xml.Marshal(retention)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build headers.
|
||||
headers := make(http.Header)
|
||||
|
||||
if opts.GovernanceBypass {
|
||||
// Set the bypass goverenance retention header
|
||||
headers.Set("x-amz-bypass-governance-retention", "True")
|
||||
}
|
||||
|
||||
reqMetadata := requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: urlValues,
|
||||
contentBody: bytes.NewReader(retentionData),
|
||||
contentLength: int64(len(retentionData)),
|
||||
contentMD5Base64: sumMD5Base64(retentionData),
|
||||
contentSHA256Hex: sum256Hex(retentionData),
|
||||
customHeader: headers,
|
||||
}
|
||||
|
||||
// Execute PUT Object Retention.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
|
||||
return httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetObjectRetention gets retention of given object.
|
||||
func (c Client) GetObjectRetention(bucketName, objectName, versionID string) (mode *RetentionMode, retainUntilDate *time.Time, err error) {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := s3utils.CheckValidObjectName(objectName); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("retention", "")
|
||||
if versionID != "" {
|
||||
urlValues.Set("versionId", versionID)
|
||||
}
|
||||
// Execute GET on bucket to list objects.
|
||||
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: urlValues,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
})
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, nil, httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
}
|
||||
retention := &objectRetention{}
|
||||
if err = xml.NewDecoder(resp.Body).Decode(retention); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &retention.Mode, &retention.RetainUntilDate, nil
|
||||
}
|
||||
163
vendor/github.com/minio/minio-go/v6/api-object-tagging.go
сгенерированный
поставляемый
Обычный файл
163
vendor/github.com/minio/minio-go/v6/api-object-tagging.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* MinIO Go Library for Amazon S3 Compatible Cloud Storage
|
||||
* Copyright 2020 MinIO, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package minio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
|
||||
// PutObjectTagging replaces or creates object tag(s)
|
||||
func (c Client) PutObjectTagging(bucketName, objectName string, objectTags map[string]string) error {
|
||||
return c.PutObjectTaggingWithContext(context.Background(), bucketName, objectName, objectTags)
|
||||
}
|
||||
|
||||
// PutObjectTaggingWithContext replaces or creates object tag(s) with a context to control cancellations
|
||||
// and timeouts.
|
||||
func (c Client) PutObjectTaggingWithContext(ctx context.Context, bucketName, objectName string, objectTags map[string]string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("tagging", "")
|
||||
|
||||
tags := make([]tag, 0)
|
||||
for k, v := range objectTags {
|
||||
t := tag{
|
||||
Key: k,
|
||||
Value: v,
|
||||
}
|
||||
tags = append(tags, t)
|
||||
}
|
||||
|
||||
// Prepare Tagging struct
|
||||
reqBody := tagging{
|
||||
TagSet: tagSet{
|
||||
Tags: tags,
|
||||
},
|
||||
}
|
||||
|
||||
reqBytes, err := xml.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqMetadata := requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: urlValues,
|
||||
contentBody: bytes.NewReader(reqBytes),
|
||||
contentLength: int64(len(reqBytes)),
|
||||
contentMD5Base64: sumMD5Base64(reqBytes),
|
||||
}
|
||||
|
||||
// Execute PUT to set a object tagging.
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetObjectTagging fetches object tag(s)
|
||||
func (c Client) GetObjectTagging(bucketName, objectName string) (string, error) {
|
||||
return c.GetObjectTaggingWithContext(context.Background(), bucketName, objectName)
|
||||
}
|
||||
|
||||
// GetObjectTaggingWithContext fetches object tag(s) with a context to control cancellations
|
||||
// and timeouts.
|
||||
func (c Client) GetObjectTaggingWithContext(ctx context.Context, bucketName, objectName string) (string, error) {
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("tagging", "")
|
||||
|
||||
// Execute GET on object to get object tag(s)
|
||||
resp, err := c.executeMethod(ctx, "GET", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: urlValues,
|
||||
})
|
||||
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
}
|
||||
|
||||
tagBuf, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(tagBuf), err
|
||||
}
|
||||
|
||||
// RemoveObjectTagging deletes object tag(s)
|
||||
func (c Client) RemoveObjectTagging(bucketName, objectName string) error {
|
||||
return c.RemoveObjectTaggingWithContext(context.Background(), bucketName, objectName)
|
||||
}
|
||||
|
||||
// RemoveObjectTaggingWithContext removes object tag(s) with a context to control cancellations
|
||||
// and timeouts.
|
||||
func (c Client) RemoveObjectTaggingWithContext(ctx context.Context, bucketName, objectName string) error {
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("tagging", "")
|
||||
|
||||
// Execute DELETE on object to remove object tag(s)
|
||||
resp, err := c.executeMethod(ctx, "DELETE", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
queryValues: urlValues,
|
||||
})
|
||||
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp, bucketName, objectName)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
170
vendor/github.com/minio/minio-go/v6/api-put-bucket.go
сгенерированный
поставляемый
170
vendor/github.com/minio/minio-go/v6/api-put-bucket.go
сгенерированный
поставляемый
@@ -31,14 +31,7 @@ import (
|
||||
|
||||
/// Bucket operations
|
||||
|
||||
// MakeBucket creates a new bucket with bucketName.
|
||||
//
|
||||
// Location is an optional argument, by default all buckets are
|
||||
// created in US Standard Region.
|
||||
//
|
||||
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
|
||||
func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||
func (c Client) makeBucket(ctx context.Context, bucketName string, location string, objectLockEnabled bool) (err error) {
|
||||
defer func() {
|
||||
// Save the location into cache on a successful makeBucket response.
|
||||
if err == nil {
|
||||
@@ -66,6 +59,12 @@ func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||
bucketLocation: location,
|
||||
}
|
||||
|
||||
if objectLockEnabled {
|
||||
headers := make(http.Header)
|
||||
headers.Add("x-amz-bucket-object-lock-enabled", "true")
|
||||
reqMetadata.customHeader = headers
|
||||
}
|
||||
|
||||
// If location is not 'us-east-1' create bucket location config.
|
||||
if location != "us-east-1" && location != "" {
|
||||
createBucketConfig := createBucketConfiguration{}
|
||||
@@ -82,7 +81,7 @@ func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||
}
|
||||
|
||||
// Execute PUT to create a new bucket.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -98,8 +97,58 @@ func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeBucket creates a new bucket with bucketName.
|
||||
//
|
||||
// Location is an optional argument, by default all buckets are
|
||||
// created in US Standard Region.
|
||||
//
|
||||
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
|
||||
func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||
return c.MakeBucketWithContext(context.Background(), bucketName, location)
|
||||
}
|
||||
|
||||
// MakeBucketWithContext creates a new bucket with bucketName with a context to control cancellations and timeouts.
|
||||
//
|
||||
// Location is an optional argument, by default all buckets are
|
||||
// created in US Standard Region.
|
||||
//
|
||||
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
|
||||
func (c Client) MakeBucketWithContext(ctx context.Context, bucketName string, location string) (err error) {
|
||||
return c.makeBucket(ctx, bucketName, location, false)
|
||||
}
|
||||
|
||||
// MakeBucketWithObjectLock creates a object lock enabled new bucket with bucketName.
|
||||
//
|
||||
// Location is an optional argument, by default all buckets are
|
||||
// created in US Standard Region.
|
||||
//
|
||||
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
|
||||
func (c Client) MakeBucketWithObjectLock(bucketName string, location string) (err error) {
|
||||
return c.MakeBucketWithObjectLockWithContext(context.Background(), bucketName, location)
|
||||
}
|
||||
|
||||
// MakeBucketWithObjectLockWithContext creates a object lock enabled new bucket with bucketName with a context to
|
||||
// control cancellations and timeouts.
|
||||
//
|
||||
// Location is an optional argument, by default all buckets are
|
||||
// created in US Standard Region.
|
||||
//
|
||||
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
|
||||
func (c Client) MakeBucketWithObjectLockWithContext(ctx context.Context, bucketName string, location string) (err error) {
|
||||
return c.makeBucket(ctx, bucketName, location, true)
|
||||
}
|
||||
|
||||
// SetBucketPolicy set the access permissions on an existing bucket.
|
||||
func (c Client) SetBucketPolicy(bucketName, policy string) error {
|
||||
return c.SetBucketPolicyWithContext(context.Background(), bucketName, policy)
|
||||
}
|
||||
|
||||
// SetBucketPolicyWithContext set the access permissions on an existing bucket.
|
||||
func (c Client) SetBucketPolicyWithContext(ctx context.Context, bucketName, policy string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -107,15 +156,15 @@ func (c Client) SetBucketPolicy(bucketName, policy string) error {
|
||||
|
||||
// If policy is empty then delete the bucket policy.
|
||||
if policy == "" {
|
||||
return c.removeBucketPolicy(bucketName)
|
||||
return c.removeBucketPolicy(ctx, bucketName)
|
||||
}
|
||||
|
||||
// Save the updated policies.
|
||||
return c.putBucketPolicy(bucketName, policy)
|
||||
return c.putBucketPolicy(ctx, bucketName, policy)
|
||||
}
|
||||
|
||||
// Saves a new bucket policy.
|
||||
func (c Client) putBucketPolicy(bucketName, policy string) error {
|
||||
func (c Client) putBucketPolicy(ctx context.Context, bucketName, policy string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -141,7 +190,7 @@ func (c Client) putBucketPolicy(bucketName, policy string) error {
|
||||
}
|
||||
|
||||
// Execute PUT to upload a new bucket policy.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -155,7 +204,7 @@ func (c Client) putBucketPolicy(bucketName, policy string) error {
|
||||
}
|
||||
|
||||
// Removes all policies on a bucket.
|
||||
func (c Client) removeBucketPolicy(bucketName string) error {
|
||||
func (c Client) removeBucketPolicy(ctx context.Context, bucketName string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -166,7 +215,7 @@ func (c Client) removeBucketPolicy(bucketName string) error {
|
||||
urlValues.Set("policy", "")
|
||||
|
||||
// Execute DELETE on objectName.
|
||||
resp, err := c.executeMethod(context.Background(), "DELETE", requestMetadata{
|
||||
resp, err := c.executeMethod(ctx, "DELETE", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
queryValues: urlValues,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
@@ -180,6 +229,11 @@ func (c Client) removeBucketPolicy(bucketName string) error {
|
||||
|
||||
// SetBucketLifecycle set the lifecycle on an existing bucket.
|
||||
func (c Client) SetBucketLifecycle(bucketName, lifecycle string) error {
|
||||
return c.SetBucketLifecycleWithContext(context.Background(), bucketName, lifecycle)
|
||||
}
|
||||
|
||||
// SetBucketLifecycleWithContext set the lifecycle on an existing bucket with a context to control cancellations and timeouts.
|
||||
func (c Client) SetBucketLifecycleWithContext(ctx context.Context, bucketName, lifecycle string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -187,15 +241,15 @@ func (c Client) SetBucketLifecycle(bucketName, lifecycle string) error {
|
||||
|
||||
// If lifecycle is empty then delete it.
|
||||
if lifecycle == "" {
|
||||
return c.removeBucketLifecycle(bucketName)
|
||||
return c.removeBucketLifecycle(ctx, bucketName)
|
||||
}
|
||||
|
||||
// Save the updated lifecycle.
|
||||
return c.putBucketLifecycle(bucketName, lifecycle)
|
||||
return c.putBucketLifecycle(ctx, bucketName, lifecycle)
|
||||
}
|
||||
|
||||
// Saves a new bucket lifecycle.
|
||||
func (c Client) putBucketLifecycle(bucketName, lifecycle string) error {
|
||||
func (c Client) putBucketLifecycle(ctx context.Context, bucketName, lifecycle string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -222,7 +276,7 @@ func (c Client) putBucketLifecycle(bucketName, lifecycle string) error {
|
||||
}
|
||||
|
||||
// Execute PUT to upload a new bucket lifecycle.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -236,7 +290,7 @@ func (c Client) putBucketLifecycle(bucketName, lifecycle string) error {
|
||||
}
|
||||
|
||||
// Remove lifecycle from a bucket.
|
||||
func (c Client) removeBucketLifecycle(bucketName string) error {
|
||||
func (c Client) removeBucketLifecycle(ctx context.Context, bucketName string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -247,7 +301,7 @@ func (c Client) removeBucketLifecycle(bucketName string) error {
|
||||
urlValues.Set("lifecycle", "")
|
||||
|
||||
// Execute DELETE on objectName.
|
||||
resp, err := c.executeMethod(context.Background(), "DELETE", requestMetadata{
|
||||
resp, err := c.executeMethod(ctx, "DELETE", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
queryValues: urlValues,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
@@ -261,6 +315,12 @@ func (c Client) removeBucketLifecycle(bucketName string) error {
|
||||
|
||||
// SetBucketNotification saves a new bucket notification.
|
||||
func (c Client) SetBucketNotification(bucketName string, bucketNotification BucketNotification) error {
|
||||
return c.SetBucketNotificationWithContext(context.Background(), bucketName, bucketNotification)
|
||||
}
|
||||
|
||||
// SetBucketNotificationWithContext saves a new bucket notification with a context to control cancellations
|
||||
// and timeouts.
|
||||
func (c Client) SetBucketNotificationWithContext(ctx context.Context, bucketName string, bucketNotification BucketNotification) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -287,7 +347,7 @@ func (c Client) SetBucketNotification(bucketName string, bucketNotification Buck
|
||||
}
|
||||
|
||||
// Execute PUT to upload a new bucket notification.
|
||||
resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -304,3 +364,69 @@ func (c Client) SetBucketNotification(bucketName string, bucketNotification Buck
|
||||
func (c Client) RemoveAllBucketNotification(bucketName string) error {
|
||||
return c.SetBucketNotification(bucketName, BucketNotification{})
|
||||
}
|
||||
|
||||
var (
|
||||
versionEnableConfig = []byte("<VersioningConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Status>Enabled</Status></VersioningConfiguration>")
|
||||
versionEnableConfigLen = int64(len(versionEnableConfig))
|
||||
versionEnableConfigMD5Sum = sumMD5Base64(versionEnableConfig)
|
||||
versionEnableConfigSHA256 = sum256Hex(versionEnableConfig)
|
||||
|
||||
versionDisableConfig = []byte("<VersioningConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Status>Suspended</Status></VersioningConfiguration>")
|
||||
versionDisableConfigLen = int64(len(versionDisableConfig))
|
||||
versionDisableConfigMD5Sum = sumMD5Base64(versionDisableConfig)
|
||||
versionDisableConfigSHA256 = sum256Hex(versionDisableConfig)
|
||||
)
|
||||
|
||||
func (c Client) setVersioning(ctx context.Context, bucketName string, config []byte, length int64, md5sum, sha256sum string) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("versioning", "")
|
||||
|
||||
reqMetadata := requestMetadata{
|
||||
bucketName: bucketName,
|
||||
queryValues: urlValues,
|
||||
contentBody: bytes.NewReader(config),
|
||||
contentLength: length,
|
||||
contentMD5Base64: md5sum,
|
||||
contentSHA256Hex: sha256sum,
|
||||
}
|
||||
|
||||
// Execute PUT to set a bucket versioning.
|
||||
resp, err := c.executeMethod(ctx, "PUT", reqMetadata)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp, bucketName, "")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableVersioning - Enable object versioning in given bucket.
|
||||
func (c Client) EnableVersioning(bucketName string) error {
|
||||
return c.EnableVersioningWithContext(context.Background(), bucketName)
|
||||
}
|
||||
|
||||
// EnableVersioningWithContext - Enable object versioning in given bucket with a context to control cancellations and timeouts.
|
||||
func (c Client) EnableVersioningWithContext(ctx context.Context, bucketName string) error {
|
||||
return c.setVersioning(ctx, bucketName, versionEnableConfig, versionEnableConfigLen, versionEnableConfigMD5Sum, versionEnableConfigSHA256)
|
||||
}
|
||||
|
||||
// DisableVersioning - Disable object versioning in given bucket.
|
||||
func (c Client) DisableVersioning(bucketName string) error {
|
||||
return c.DisableVersioningWithContext(context.Background(), bucketName)
|
||||
}
|
||||
|
||||
// DisableVersioningWithContext - Disable object versioning in given bucket with a context to control cancellations and timeouts.
|
||||
func (c Client) DisableVersioningWithContext(ctx context.Context, bucketName string) error {
|
||||
return c.setVersioning(ctx, bucketName, versionDisableConfig, versionDisableConfigLen, versionDisableConfigMD5Sum, versionDisableConfigSHA256)
|
||||
}
|
||||
|
||||
16
vendor/github.com/minio/minio-go/v6/api-put-object-common.go
сгенерированный
поставляемый
16
vendor/github.com/minio/minio-go/v6/api-put-object-common.go
сгенерированный
поставляемый
@@ -69,7 +69,9 @@ func isReadAt(reader io.Reader) (ok bool) {
|
||||
//
|
||||
func optimalPartInfo(objectSize int64, configuredPartSize uint64) (totalPartsCount int, partSize int64, lastPartSize int64, err error) {
|
||||
// object size is '-1' set it to 5TiB.
|
||||
var unknownSize bool
|
||||
if objectSize == -1 {
|
||||
unknownSize = true
|
||||
objectSize = maxMultipartPutObjectSize
|
||||
}
|
||||
|
||||
@@ -86,9 +88,11 @@ func optimalPartInfo(objectSize int64, configuredPartSize uint64) (totalPartsCou
|
||||
return
|
||||
}
|
||||
|
||||
if objectSize > (int64(configuredPartSize) * maxPartsCount) {
|
||||
err = ErrInvalidArgument("Part size * max_parts(10000) is lesser than input objectSize.")
|
||||
return
|
||||
if !unknownSize {
|
||||
if objectSize > (int64(configuredPartSize) * maxPartsCount) {
|
||||
err = ErrInvalidArgument("Part size * max_parts(10000) is lesser than input objectSize.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if configuredPartSize < absMinPartSize {
|
||||
@@ -100,7 +104,13 @@ func optimalPartInfo(objectSize int64, configuredPartSize uint64) (totalPartsCou
|
||||
err = ErrInvalidArgument("Input part size is bigger than allowed maximum of 5GiB.")
|
||||
return
|
||||
}
|
||||
|
||||
partSizeFlt = float64(configuredPartSize)
|
||||
if unknownSize {
|
||||
// If input has unknown size and part size is configured
|
||||
// keep it to maximum allowed as per 10000 parts.
|
||||
objectSize = int64(configuredPartSize) * maxPartsCount
|
||||
}
|
||||
} else {
|
||||
configuredPartSize = minPartSize
|
||||
// Use floats for part size for all calculations to avoid
|
||||
|
||||
10
vendor/github.com/minio/minio-go/v6/api-put-object-copy.go
сгенерированный
поставляемый
10
vendor/github.com/minio/minio-go/v6/api-put-object-copy.go
сгенерированный
поставляемый
@@ -24,6 +24,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/encrypt"
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
|
||||
// CopyObject - copy a source object into a new object
|
||||
@@ -39,6 +40,11 @@ func (c Client) CopyObjectWithProgress(dst DestinationInfo, src SourceInfo, prog
|
||||
header[k] = v
|
||||
}
|
||||
|
||||
if dst.opts.ReplaceTags && len(dst.opts.UserTags) != 0 {
|
||||
header.Set(amzTaggingHeaderDirective, "REPLACE")
|
||||
header.Set(amzTaggingHeader, s3utils.TagEncode(dst.opts.UserTags))
|
||||
}
|
||||
|
||||
var err error
|
||||
var size int64
|
||||
// If progress bar is specified, size should be requested as well initiate a StatObject request.
|
||||
@@ -53,8 +59,8 @@ func (c Client) CopyObjectWithProgress(dst DestinationInfo, src SourceInfo, prog
|
||||
encrypt.SSECopy(src.encryption).Marshal(header)
|
||||
}
|
||||
|
||||
if dst.encryption != nil {
|
||||
dst.encryption.Marshal(header)
|
||||
if dst.opts.Encryption != nil {
|
||||
dst.opts.Encryption.Marshal(header)
|
||||
}
|
||||
for k, v := range dst.getUserMetaHeadersMap(true) {
|
||||
header.Set(k, v)
|
||||
|
||||
10
vendor/github.com/minio/minio-go/v6/api-put-object-multipart.go
сгенерированный
поставляемый
10
vendor/github.com/minio/minio-go/v6/api-put-object-multipart.go
сгенерированный
поставляемый
@@ -137,11 +137,10 @@ func (c Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obje
|
||||
}
|
||||
|
||||
// Proceed to upload the part.
|
||||
var objPart ObjectPart
|
||||
objPart, err = c.uploadPart(ctx, bucketName, objectName, uploadID, rd, partNumber,
|
||||
objPart, uerr := c.uploadPart(ctx, bucketName, objectName, uploadID, rd, partNumber,
|
||||
md5Base64, sha256Hex, int64(length), opts.ServerSideEncryption)
|
||||
if err != nil {
|
||||
return totalUploadedSize, err
|
||||
if uerr != nil {
|
||||
return totalUploadedSize, uerr
|
||||
}
|
||||
|
||||
// Save successfully uploaded part metadata.
|
||||
@@ -294,8 +293,7 @@ func (c Client) uploadPart(ctx context.Context, bucketName, objectName, uploadID
|
||||
objPart.Size = size
|
||||
objPart.PartNumber = partNumber
|
||||
// Trim off the odd double quotes from ETag in the beginning and end.
|
||||
objPart.ETag = strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
|
||||
objPart.ETag = strings.TrimSuffix(objPart.ETag, "\"")
|
||||
objPart.ETag = trimEtag(resp.Header.Get("ETag"))
|
||||
return objPart, nil
|
||||
}
|
||||
|
||||
|
||||
35
vendor/github.com/minio/minio-go/v6/api-put-object-streaming.go
сгенерированный
поставляемый
35
vendor/github.com/minio/minio-go/v6/api-put-object-streaming.go
сгенерированный
поставляемый
@@ -67,12 +67,12 @@ type uploadedPartRes struct {
|
||||
Error error // Any error encountered while uploading the part.
|
||||
PartNum int // Number of the part uploaded.
|
||||
Size int64 // Size of the part uploaded.
|
||||
Part *ObjectPart
|
||||
Part ObjectPart
|
||||
}
|
||||
|
||||
type uploadPartReq struct {
|
||||
PartNum int // Number of the part uploaded.
|
||||
Part *ObjectPart // Size of the part uploaded.
|
||||
PartNum int // Number of the part uploaded.
|
||||
Part ObjectPart // Size of the part uploaded.
|
||||
}
|
||||
|
||||
// putObjectMultipartFromReadAt - Uploads files bigger than 128MiB.
|
||||
@@ -139,7 +139,7 @@ func (c Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketNa
|
||||
|
||||
// Send each part number to the channel to be processed.
|
||||
for p := 1; p <= totalPartsCount; p++ {
|
||||
uploadPartsCh <- uploadPartReq{PartNum: p, Part: nil}
|
||||
uploadPartsCh <- uploadPartReq{PartNum: p}
|
||||
}
|
||||
close(uploadPartsCh)
|
||||
// Receive each part number from the channel allowing three parallel uploads.
|
||||
@@ -164,13 +164,11 @@ func (c Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketNa
|
||||
sectionReader := newHook(io.NewSectionReader(reader, readOffset, partSize), opts.Progress)
|
||||
|
||||
// Proceed to upload the part.
|
||||
var objPart ObjectPart
|
||||
objPart, err = c.uploadPart(ctx, bucketName, objectName, uploadID,
|
||||
objPart, err := c.uploadPart(ctx, bucketName, objectName, uploadID,
|
||||
sectionReader, uploadReq.PartNum,
|
||||
"", "", partSize, opts.ServerSideEncryption)
|
||||
if err != nil {
|
||||
uploadedPartsCh <- uploadedPartRes{
|
||||
Size: 0,
|
||||
Error: err,
|
||||
}
|
||||
// Exit the goroutine.
|
||||
@@ -178,14 +176,13 @@ func (c Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketNa
|
||||
}
|
||||
|
||||
// Save successfully uploaded part metadata.
|
||||
uploadReq.Part = &objPart
|
||||
uploadReq.Part = objPart
|
||||
|
||||
// Send successful part info through the channel.
|
||||
uploadedPartsCh <- uploadedPartRes{
|
||||
Size: objPart.Size,
|
||||
PartNum: uploadReq.PartNum,
|
||||
Part: uploadReq.Part,
|
||||
Error: nil,
|
||||
}
|
||||
}
|
||||
}(partSize)
|
||||
@@ -198,18 +195,12 @@ func (c Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketNa
|
||||
if uploadRes.Error != nil {
|
||||
return totalUploadedSize, uploadRes.Error
|
||||
}
|
||||
// Retrieve each uploaded part and store it to be completed.
|
||||
// part, ok := partsInfo[uploadRes.PartNum]
|
||||
part := uploadRes.Part
|
||||
if part == nil {
|
||||
return 0, ErrInvalidArgument(fmt.Sprintf("Missing part number %d", uploadRes.PartNum))
|
||||
}
|
||||
// Update the totalUploadedSize.
|
||||
totalUploadedSize += uploadRes.Size
|
||||
// Store the parts to be completed in order.
|
||||
complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{
|
||||
ETag: part.ETag,
|
||||
PartNumber: part.PartNumber,
|
||||
ETag: uploadRes.Part.ETag,
|
||||
PartNumber: uploadRes.Part.PartNumber,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -277,12 +268,11 @@ func (c Client) putObjectMultipartStreamNoChecksum(ctx context.Context, bucketNa
|
||||
if partNumber == totalPartsCount {
|
||||
partSize = lastPartSize
|
||||
}
|
||||
var objPart ObjectPart
|
||||
objPart, err = c.uploadPart(ctx, bucketName, objectName, uploadID,
|
||||
objPart, uerr := c.uploadPart(ctx, bucketName, objectName, uploadID,
|
||||
io.LimitReader(hookReader, partSize),
|
||||
partNumber, "", "", partSize, opts.ServerSideEncryption)
|
||||
if err != nil {
|
||||
return totalUploadedSize, err
|
||||
if uerr != nil {
|
||||
return totalUploadedSize, uerr
|
||||
}
|
||||
|
||||
// Save successfully uploaded part metadata.
|
||||
@@ -407,8 +397,7 @@ func (c Client) putObjectDo(ctx context.Context, bucketName, objectName string,
|
||||
|
||||
var objInfo ObjectInfo
|
||||
// Trim off the odd double quotes from ETag in the beginning and end.
|
||||
objInfo.ETag = strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
|
||||
objInfo.ETag = strings.TrimSuffix(objInfo.ETag, "\"")
|
||||
objInfo.ETag = trimEtag(resp.Header.Get("ETag"))
|
||||
// A success here means data was written to server successfully.
|
||||
objInfo.Size = size
|
||||
|
||||
|
||||
38
vendor/github.com/minio/minio-go/v6/api-put-object.go
сгенерированный
поставляемый
38
vendor/github.com/minio/minio-go/v6/api-put-object.go
сгенерированный
поставляемый
@@ -25,6 +25,7 @@ import (
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/encrypt"
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
@@ -34,12 +35,15 @@ import (
|
||||
// PutObjectOptions represents options specified by user for PutObject call
|
||||
type PutObjectOptions struct {
|
||||
UserMetadata map[string]string
|
||||
UserTags map[string]string
|
||||
Progress io.Reader
|
||||
ContentType string
|
||||
ContentEncoding string
|
||||
ContentDisposition string
|
||||
ContentLanguage string
|
||||
CacheControl string
|
||||
Mode *RetentionMode
|
||||
RetainUntilDate *time.Time
|
||||
ServerSideEncryption encrypt.ServerSide
|
||||
NumThreads uint
|
||||
StorageClass string
|
||||
@@ -80,6 +84,14 @@ func (opts PutObjectOptions) Header() (header http.Header) {
|
||||
if opts.CacheControl != "" {
|
||||
header["Cache-Control"] = []string{opts.CacheControl}
|
||||
}
|
||||
|
||||
if opts.Mode != nil {
|
||||
header["x-amz-object-lock-mode"] = []string{opts.Mode.String()}
|
||||
}
|
||||
if opts.RetainUntilDate != nil {
|
||||
header["x-amz-object-lock-retain-until-date"] = []string{opts.RetainUntilDate.Format(time.RFC3339)}
|
||||
}
|
||||
|
||||
if opts.ServerSideEncryption != nil {
|
||||
opts.ServerSideEncryption.Marshal(header)
|
||||
}
|
||||
@@ -89,6 +101,9 @@ func (opts PutObjectOptions) Header() (header http.Header) {
|
||||
if opts.WebsiteRedirectLocation != "" {
|
||||
header[amzWebsiteRedirectLocation] = []string{opts.WebsiteRedirectLocation}
|
||||
}
|
||||
if len(opts.UserTags) != 0 {
|
||||
header[amzTaggingHeader] = []string{s3utils.TagEncode(opts.UserTags)}
|
||||
}
|
||||
for k, v := range opts.UserMetadata {
|
||||
if !isAmzHeader(k) && !isStandardHeader(k) && !isStorageClassHeader(k) {
|
||||
header["X-Amz-Meta-"+k] = []string{v}
|
||||
@@ -109,6 +124,11 @@ func (opts PutObjectOptions) validate() (err error) {
|
||||
return ErrInvalidArgument(v + " unsupported user defined metadata value")
|
||||
}
|
||||
}
|
||||
if opts.Mode != nil {
|
||||
if !opts.Mode.IsValid() {
|
||||
return ErrInvalidArgument(opts.Mode.String() + " unsupported retention mode")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -215,23 +235,23 @@ func (c Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketName
|
||||
defer debug.FreeOSMemory()
|
||||
|
||||
for partNumber <= totalPartsCount {
|
||||
length, rErr := io.ReadFull(reader, buf)
|
||||
if rErr == io.EOF && partNumber > 1 {
|
||||
length, rerr := io.ReadFull(reader, buf)
|
||||
if rerr == io.EOF && partNumber > 1 {
|
||||
break
|
||||
}
|
||||
if rErr != nil && rErr != io.ErrUnexpectedEOF && rErr != io.EOF {
|
||||
return 0, rErr
|
||||
if rerr != nil && rerr != io.ErrUnexpectedEOF && rerr != io.EOF {
|
||||
return 0, rerr
|
||||
}
|
||||
|
||||
// Update progress reader appropriately to the latest offset
|
||||
// as we read from the source.
|
||||
rd := newHook(bytes.NewReader(buf[:length]), opts.Progress)
|
||||
|
||||
// Proceed to upload the part.
|
||||
var objPart ObjectPart
|
||||
objPart, err = c.uploadPart(ctx, bucketName, objectName, uploadID, rd, partNumber,
|
||||
objPart, uerr := c.uploadPart(ctx, bucketName, objectName, uploadID, rd, partNumber,
|
||||
"", "", int64(length), opts.ServerSideEncryption)
|
||||
if err != nil {
|
||||
return totalUploadedSize, err
|
||||
if uerr != nil {
|
||||
return totalUploadedSize, uerr
|
||||
}
|
||||
|
||||
// Save successfully uploaded part metadata.
|
||||
@@ -245,7 +265,7 @@ func (c Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketName
|
||||
|
||||
// For unknown size, Read EOF we break away.
|
||||
// We do not have to upload till totalPartsCount.
|
||||
if rErr == io.EOF {
|
||||
if rerr == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
29
vendor/github.com/minio/minio-go/v6/api-remove.go
сгенерированный
поставляемый
29
vendor/github.com/minio/minio-go/v6/api-remove.go
сгенерированный
поставляемый
@@ -60,6 +60,17 @@ func (c Client) RemoveBucket(bucketName string) error {
|
||||
|
||||
// RemoveObject remove an object from a bucket.
|
||||
func (c Client) RemoveObject(bucketName, objectName string) error {
|
||||
return c.RemoveObjectWithOptions(bucketName, objectName, RemoveObjectOptions{})
|
||||
}
|
||||
|
||||
// RemoveObjectOptions represents options specified by user for PutObject call
|
||||
type RemoveObjectOptions struct {
|
||||
GovernanceBypass bool
|
||||
VersionID string
|
||||
}
|
||||
|
||||
// RemoveObjectWithOptions removes an object from a bucket.
|
||||
func (c Client) RemoveObjectWithOptions(bucketName, objectName string, opts RemoveObjectOptions) error {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return err
|
||||
@@ -67,11 +78,29 @@ func (c Client) RemoveObject(bucketName, objectName string) error {
|
||||
if err := s3utils.CheckValidObjectName(objectName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get resources properly escaped and lined up before
|
||||
// using them in http request.
|
||||
urlValues := make(url.Values)
|
||||
|
||||
if opts.VersionID != "" {
|
||||
urlValues.Set("versionId", opts.VersionID)
|
||||
}
|
||||
|
||||
// Build headers.
|
||||
headers := make(http.Header)
|
||||
|
||||
if opts.GovernanceBypass {
|
||||
// Set the bypass goverenance retention header
|
||||
headers.Set("x-amz-bypass-governance-retention", "True")
|
||||
}
|
||||
// Execute DELETE on objectName.
|
||||
resp, err := c.executeMethod(context.Background(), "DELETE", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
queryValues: urlValues,
|
||||
customHeader: headers,
|
||||
})
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
|
||||
16
vendor/github.com/minio/minio-go/v6/api-s3-datatypes.go
сгенерированный
поставляемый
16
vendor/github.com/minio/minio-go/v6/api-s3-datatypes.go
сгенерированный
поставляемый
@@ -243,3 +243,19 @@ type deleteMultiObjectsResult struct {
|
||||
DeletedObjects []deletedObject `xml:"Deleted"`
|
||||
UnDeletedObjects []nonDeletedObject `xml:"Error"`
|
||||
}
|
||||
|
||||
type tagging struct {
|
||||
XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ Tagging"`
|
||||
TagSet tagSet
|
||||
}
|
||||
|
||||
type tagSet struct {
|
||||
XMLName xml.Name `xml:"TagSet"`
|
||||
Tags []tag
|
||||
}
|
||||
|
||||
type tag struct {
|
||||
XMLName xml.Name `xml:"Tag"`
|
||||
Key string `xml:"Key"`
|
||||
Value string `xml:"Value"`
|
||||
}
|
||||
|
||||
37
vendor/github.com/minio/minio-go/v6/api-stat.go
сгенерированный
поставляемый
37
vendor/github.com/minio/minio-go/v6/api-stat.go
сгенерированный
поставляемый
@@ -29,13 +29,19 @@ import (
|
||||
|
||||
// BucketExists verify if bucket exists and you have permission to access it.
|
||||
func (c Client) BucketExists(bucketName string) (bool, error) {
|
||||
return c.BucketExistsWithContext(context.Background(), bucketName)
|
||||
}
|
||||
|
||||
// BucketExistsWithContext verify if bucket exists and you have permission to access it. Allows for a Context to
|
||||
// control cancellations and timeouts.
|
||||
func (c Client) BucketExistsWithContext(ctx context.Context, bucketName string) (bool, error) {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Execute HEAD on bucketName.
|
||||
resp, err := c.executeMethod(context.Background(), "HEAD", requestMetadata{
|
||||
resp, err := c.executeMethod(ctx, "HEAD", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
})
|
||||
@@ -72,7 +78,7 @@ var defaultFilterKeys = []string{
|
||||
"x-amz-id-2",
|
||||
"Content-Security-Policy",
|
||||
"X-Xss-Protection",
|
||||
|
||||
amzTaggingHeaderCount,
|
||||
// Add new headers to be ignored.
|
||||
}
|
||||
|
||||
@@ -85,12 +91,20 @@ func extractObjMetadata(header http.Header) http.Header {
|
||||
"Last-Modified",
|
||||
"Content-Type",
|
||||
"Expires",
|
||||
"X-Cache",
|
||||
"X-Cache-Lookup",
|
||||
}, defaultFilterKeys...)
|
||||
return filterHeader(header, filterKeys)
|
||||
}
|
||||
|
||||
// StatObject verifies if object exists and you have permission to access.
|
||||
func (c Client) StatObject(bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) {
|
||||
return c.StatObjectWithContext(context.Background(), bucketName, objectName, opts)
|
||||
}
|
||||
|
||||
// StatObjectWithContext verifies if object exists and you have permission to access with a context to control
|
||||
// cancellations and timeouts.
|
||||
func (c Client) StatObjectWithContext(ctx context.Context, bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
@@ -98,7 +112,7 @@ func (c Client) StatObject(bucketName, objectName string, opts StatObjectOptions
|
||||
if err := s3utils.CheckValidObjectName(objectName); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
}
|
||||
return c.statObject(context.Background(), bucketName, objectName, opts)
|
||||
return c.statObject(ctx, bucketName, objectName, opts)
|
||||
}
|
||||
|
||||
// Lower level API for statObject supporting pre-conditions and range headers.
|
||||
@@ -129,8 +143,7 @@ func (c Client) statObject(ctx context.Context, bucketName, objectName string, o
|
||||
}
|
||||
|
||||
// Trim off the odd double quotes from ETag in the beginning and end.
|
||||
md5sum := strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
|
||||
md5sum = strings.TrimSuffix(md5sum, "\"")
|
||||
md5sum := trimEtag(resp.Header.Get("ETag"))
|
||||
|
||||
// Parse content length is exists
|
||||
var size int64 = -1
|
||||
@@ -176,6 +189,17 @@ func (c Client) statObject(ctx context.Context, bucketName, objectName string, o
|
||||
if t, err := time.Parse(http.TimeFormat, expiryStr); err == nil {
|
||||
expTime = t.UTC()
|
||||
}
|
||||
|
||||
metadata := extractObjMetadata(resp.Header)
|
||||
userMetadata := map[string]string{}
|
||||
const xamzmeta = "x-amz-meta-"
|
||||
const xamzmetaLen = len(xamzmeta)
|
||||
for k, v := range metadata {
|
||||
if strings.HasPrefix(strings.ToLower(k), xamzmeta) {
|
||||
userMetadata[k[xamzmetaLen:]] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Save object metadata info.
|
||||
return ObjectInfo{
|
||||
ETag: md5sum,
|
||||
@@ -187,6 +211,7 @@ func (c Client) statObject(ctx context.Context, bucketName, objectName string, o
|
||||
// Extract only the relevant header keys describing the object.
|
||||
// following function filters out a list of standard set of keys
|
||||
// which are not part of object metadata.
|
||||
Metadata: extractObjMetadata(resp.Header),
|
||||
Metadata: metadata,
|
||||
UserMetadata: userMetadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
18
vendor/github.com/minio/minio-go/v6/api.go
сгенерированный
поставляемый
18
vendor/github.com/minio/minio-go/v6/api.go
сгенерированный
поставляемый
@@ -104,7 +104,7 @@ type Options struct {
|
||||
// Global constants.
|
||||
const (
|
||||
libraryName = "minio-go"
|
||||
libraryVersion = "v6.0.40"
|
||||
libraryVersion = "v6.0.45"
|
||||
)
|
||||
|
||||
// User Agent should always following the below style.
|
||||
@@ -560,6 +560,13 @@ func (c Client) executeMethod(ctx context.Context, method string, metadata reque
|
||||
var bodySeeker io.Seeker // Extracted seeker from io.Reader.
|
||||
var reqRetry = MaxRetry // Indicates how many times we can retry the request
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// close idle connections before returning, upon error.
|
||||
c.httpClient.CloseIdleConnections()
|
||||
}
|
||||
}()
|
||||
|
||||
if metadata.contentBody != nil {
|
||||
// Check if body is seekable then it is retryable.
|
||||
bodySeeker, isRetryable = metadata.contentBody.(io.Seeker)
|
||||
@@ -620,12 +627,7 @@ func (c Client) executeMethod(ctx context.Context, method string, metadata reque
|
||||
// Initiate the request.
|
||||
res, err = c.do(req)
|
||||
if err != nil {
|
||||
// For supported http requests errors verify.
|
||||
if isHTTPReqErrorRetryable(err) {
|
||||
continue // Retry.
|
||||
}
|
||||
// For other errors, return here no need to retry.
|
||||
return nil, err
|
||||
continue
|
||||
}
|
||||
|
||||
// For any known successful http status, return quickly.
|
||||
@@ -822,7 +824,7 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R
|
||||
case signerType.IsV2():
|
||||
// Add signature version '2' authorization header.
|
||||
req = s3signer.SignV2(*req, accessKeyID, secretAccessKey, isVirtualHost)
|
||||
case metadata.objectName != "" && method == "PUT" && metadata.customHeader.Get("X-Amz-Copy-Source") == "" && !c.secure:
|
||||
case metadata.objectName != "" && metadata.queryValues == nil && method == "PUT" && metadata.customHeader.Get("X-Amz-Copy-Source") == "" && !c.secure:
|
||||
// Streaming signature is used by default for a PUT object request. Additionally we also
|
||||
// look if the initialized client is secure, if yes then we don't need to perform
|
||||
// streaming signature.
|
||||
|
||||
4
vendor/github.com/minio/minio-go/v6/bucket-cache.go
сгенерированный
поставляемый
4
vendor/github.com/minio/minio-go/v6/bucket-cache.go
сгенерированный
поставляемый
@@ -125,6 +125,10 @@ func processBucketLocationResponse(resp *http.Response, bucketName string) (buck
|
||||
// request. Move forward and let the top level callers
|
||||
// succeed if possible based on their policy.
|
||||
switch errResp.Code {
|
||||
case "NotImplemented":
|
||||
if errResp.Server == "AmazonSnowball" {
|
||||
return "snowball", nil
|
||||
}
|
||||
case "AuthorizationHeaderMalformed":
|
||||
fallthrough
|
||||
case "InvalidRegion":
|
||||
|
||||
5
vendor/github.com/minio/minio-go/v6/constants.go
сгенерированный
поставляемый
5
vendor/github.com/minio/minio-go/v6/constants.go
сгенерированный
поставляемый
@@ -60,3 +60,8 @@ const amzStorageClass = "X-Amz-Storage-Class"
|
||||
|
||||
// Website redirect location header constant
|
||||
const amzWebsiteRedirectLocation = "X-Amz-Website-Redirect-Location"
|
||||
|
||||
// Tagging header constants
|
||||
const amzTaggingHeader = "X-Amz-Tagging"
|
||||
const amzTaggingHeaderDirective = "X-Amz-Tagging-Directive"
|
||||
const amzTaggingHeaderCount = "X-Amz-Tagging-Count"
|
||||
|
||||
10
vendor/github.com/minio/minio-go/v6/core.go
сгенерированный
поставляемый
10
vendor/github.com/minio/minio-go/v6/core.go
сгенерированный
поставляемый
@@ -53,7 +53,7 @@ func (c Core) ListObjects(bucket, prefix, marker, delimiter string, maxKeys int)
|
||||
// ListObjectsV2 - Lists all the objects at a prefix, similar to ListObjects() but uses
|
||||
// continuationToken instead of marker to support iteration over the results.
|
||||
func (c Core) ListObjectsV2(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int, startAfter string) (ListBucketV2Result, error) {
|
||||
return c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, maxkeys, startAfter)
|
||||
return c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, false, delimiter, maxkeys, startAfter)
|
||||
}
|
||||
|
||||
// CopyObjectWithContext - copies an object from source object to destination object on server side.
|
||||
@@ -171,7 +171,13 @@ func (c Core) GetBucketPolicy(bucket string) (string, error) {
|
||||
|
||||
// PutBucketPolicy - applies a new bucket access policy for a given bucket.
|
||||
func (c Core) PutBucketPolicy(bucket, bucketPolicy string) error {
|
||||
return c.putBucketPolicy(bucket, bucketPolicy)
|
||||
return c.PutBucketPolicyWithContext(context.Background(), bucket, bucketPolicy)
|
||||
}
|
||||
|
||||
// PutBucketPolicyWithContext - applies a new bucket access policy for a given bucket with a context to control
|
||||
// cancellations and timeouts.
|
||||
func (c Core) PutBucketPolicyWithContext(ctx context.Context, bucket, bucketPolicy string) error {
|
||||
return c.putBucketPolicy(ctx, bucket, bucketPolicy)
|
||||
}
|
||||
|
||||
// GetObjectWithContext is a lower level API implemented to support reading
|
||||
|
||||
95
vendor/github.com/minio/minio-go/v6/pkg/credentials/iam_aws.go
сгенерированный
поставляемый
95
vendor/github.com/minio/minio-go/v6/pkg/credentials/iam_aws.go
сгенерированный
поставляемый
@@ -22,6 +22,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -53,20 +55,10 @@ type IAM struct {
|
||||
const (
|
||||
defaultIAMRoleEndpoint = "http://169.254.169.254"
|
||||
defaultECSRoleEndpoint = "http://169.254.170.2"
|
||||
defaultSTSRoleEndpoint = "https://sts.amazonaws.com"
|
||||
defaultIAMSecurityCredsPath = "/latest/meta-data/iam/security-credentials/"
|
||||
)
|
||||
|
||||
// https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html
|
||||
func getEndpoint(endpoint string) (string, bool) {
|
||||
if endpoint != "" {
|
||||
return endpoint, os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI") != ""
|
||||
}
|
||||
if ecsURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"); ecsURI != "" {
|
||||
return fmt.Sprintf("%s%s", defaultECSRoleEndpoint, ecsURI), true
|
||||
}
|
||||
return defaultIAMRoleEndpoint, false
|
||||
}
|
||||
|
||||
// NewIAM returns a pointer to a new Credentials object wrapping the IAM.
|
||||
func NewIAM(endpoint string) *Credentials {
|
||||
p := &IAM{
|
||||
@@ -82,14 +74,64 @@ func NewIAM(endpoint string) *Credentials {
|
||||
// Error will be returned if the request fails, or unable to extract
|
||||
// the desired
|
||||
func (m *IAM) Retrieve() (Value, error) {
|
||||
endpoint, isEcsTask := getEndpoint(m.endpoint)
|
||||
var roleCreds ec2RoleCredRespBody
|
||||
var err error
|
||||
if isEcsTask {
|
||||
|
||||
endpoint := m.endpoint
|
||||
switch {
|
||||
case len(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")) > 0:
|
||||
if len(endpoint) == 0 {
|
||||
if len(os.Getenv("AWS_REGION")) > 0 {
|
||||
endpoint = "sts." + os.Getenv("AWS_REGION") + ".amazonaws.com"
|
||||
} else {
|
||||
endpoint = defaultSTSRoleEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
creds := &STSWebIdentity{
|
||||
Client: m.Client,
|
||||
stsEndpoint: endpoint,
|
||||
roleARN: os.Getenv("AWS_ROLE_ARN"),
|
||||
roleSessionName: os.Getenv("AWS_ROLE_SESSION_NAME"),
|
||||
getWebIDTokenExpiry: func() (*WebIdentityToken, error) {
|
||||
token, err := ioutil.ReadFile(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WebIdentityToken{Token: string(token)}, nil
|
||||
},
|
||||
}
|
||||
|
||||
return creds.Retrieve()
|
||||
|
||||
case len(os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")) > 0:
|
||||
if len(endpoint) == 0 {
|
||||
endpoint = fmt.Sprintf("%s%s", defaultECSRoleEndpoint,
|
||||
os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"))
|
||||
}
|
||||
|
||||
roleCreds, err = getEcsTaskCredentials(m.Client, endpoint)
|
||||
} else {
|
||||
|
||||
case len(os.Getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI")) > 0:
|
||||
if len(endpoint) == 0 {
|
||||
endpoint = os.Getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI")
|
||||
|
||||
var ok bool
|
||||
if ok, err = isLoopback(endpoint); !ok {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("uri host is not a loopback address: %s", endpoint)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
roleCreds, err = getEcsTaskCredentials(m.Client, endpoint)
|
||||
|
||||
default:
|
||||
roleCreds, err = getCredentials(m.Client, endpoint)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
@@ -248,3 +290,28 @@ func getCredentials(client *http.Client, endpoint string) (ec2RoleCredRespBody,
|
||||
|
||||
return respCreds, nil
|
||||
}
|
||||
|
||||
// isLoopback identifies if a uri's host is on a loopback address
|
||||
func isLoopback(uri string) (bool, error) {
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
host := u.Hostname()
|
||||
if len(host) == 0 {
|
||||
return false, fmt.Errorf("can't parse host from uri: %s", uri)
|
||||
}
|
||||
|
||||
ips, err := net.LookupHost(host)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, ip := range ips {
|
||||
if !net.ParseIP(ip).IsLoopback() {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
24
vendor/github.com/minio/minio-go/v6/pkg/credentials/sts_web_identity.go
сгенерированный
поставляемый
24
vendor/github.com/minio/minio-go/v6/pkg/credentials/sts_web_identity.go
сгенерированный
поставляемый
@@ -23,6 +23,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -75,6 +76,13 @@ type STSWebIdentity struct {
|
||||
// this token.
|
||||
// This is a customer provided function and is mandatory.
|
||||
getWebIDTokenExpiry func() (*WebIdentityToken, error)
|
||||
|
||||
// roleARN is the Amazon Resource Name (ARN) of the role that the caller is
|
||||
// assuming.
|
||||
roleARN string
|
||||
|
||||
// roleSessionName is the identifier for the assumed role session.
|
||||
roleSessionName string
|
||||
}
|
||||
|
||||
// NewSTSWebIdentity returns a pointer to a new
|
||||
@@ -95,7 +103,7 @@ func NewSTSWebIdentity(stsEndpoint string, getWebIDTokenExpiry func() (*WebIdent
|
||||
}), nil
|
||||
}
|
||||
|
||||
func getWebIdentityCredentials(clnt *http.Client, endpoint string,
|
||||
func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSessionName string,
|
||||
getWebIDTokenExpiry func() (*WebIdentityToken, error)) (AssumeRoleWithWebIdentityResponse, error) {
|
||||
idToken, err := getWebIDTokenExpiry()
|
||||
if err != nil {
|
||||
@@ -104,8 +112,18 @@ func getWebIdentityCredentials(clnt *http.Client, endpoint string,
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("Action", "AssumeRoleWithWebIdentity")
|
||||
if len(roleARN) > 0 {
|
||||
v.Set("RoleArn", roleARN)
|
||||
|
||||
if len(roleSessionName) == 0 {
|
||||
roleSessionName = strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
}
|
||||
v.Set("RoleSessionName", roleSessionName)
|
||||
}
|
||||
v.Set("WebIdentityToken", idToken.Token)
|
||||
v.Set("DurationSeconds", fmt.Sprintf("%d", idToken.Expiry))
|
||||
if idToken.Expiry > 0 {
|
||||
v.Set("DurationSeconds", fmt.Sprintf("%d", idToken.Expiry))
|
||||
}
|
||||
v.Set("Version", "2011-06-15")
|
||||
|
||||
u, err := url.Parse(endpoint)
|
||||
@@ -141,7 +159,7 @@ func getWebIdentityCredentials(clnt *http.Client, endpoint string,
|
||||
// Retrieve retrieves credentials from the MinIO service.
|
||||
// Error will be returned if the request fails.
|
||||
func (m *STSWebIdentity) Retrieve() (Value, error) {
|
||||
a, err := getWebIdentityCredentials(m.Client, m.stsEndpoint, m.getWebIDTokenExpiry)
|
||||
a, err := getWebIdentityCredentials(m.Client, m.stsEndpoint, m.roleARN, m.roleSessionName, m.getWebIDTokenExpiry)
|
||||
if err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/minio/minio-go/v6/pkg/encrypt/server-side.go
сгенерированный
поставляемый
4
vendor/github.com/minio/minio-go/v6/pkg/encrypt/server-side.go
сгенерированный
поставляемый
@@ -188,7 +188,9 @@ func (s kms) Type() Type { return KMS }
|
||||
|
||||
func (s kms) Marshal(h http.Header) {
|
||||
h.Set(sseGenericHeader, "aws:kms")
|
||||
h.Set(sseKmsKeyID, s.key)
|
||||
if s.key != "" {
|
||||
h.Set(sseKmsKeyID, s.key)
|
||||
}
|
||||
if s.hasContext {
|
||||
h.Set(sseEncryptionContext, base64.StdEncoding.EncodeToString(s.context))
|
||||
}
|
||||
|
||||
25
vendor/github.com/minio/minio-go/v6/pkg/s3utils/utils.go
сгенерированный
поставляемый
25
vendor/github.com/minio/minio-go/v6/pkg/s3utils/utils.go
сгенерированный
поставляемый
@@ -219,6 +219,31 @@ func QueryEncode(v url.Values) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// TagEncode - encodes tag values in their URL encoded form. In
|
||||
// addition to the percent encoding performed by urlEncodePath() used
|
||||
// here, it also percent encodes '/' (forward slash)
|
||||
func TagEncode(tags map[string]string) string {
|
||||
if tags == nil {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, 0, len(tags))
|
||||
for k := range tags {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
v := tags[k]
|
||||
prefix := percentEncodeSlash(EncodePath(k)) + "="
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteByte('&')
|
||||
}
|
||||
buf.WriteString(prefix)
|
||||
buf.WriteString(percentEncodeSlash(EncodePath(v)))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// if object matches reserved string, no need to encode them
|
||||
var reservedObjectNames = regexp.MustCompile("^[a-zA-Z0-9-_.~/]+$")
|
||||
|
||||
|
||||
21
vendor/github.com/minio/minio-go/v6/post-policy.go
сгенерированный
поставляемый
21
vendor/github.com/minio/minio-go/v6/post-policy.go
сгенерированный
поставляемый
@@ -131,6 +131,27 @@ func (p *PostPolicy) SetBucket(bucketName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCondition - Sets condition for credentials, date and algorithm
|
||||
func (p *PostPolicy) SetCondition(matchType, condition, value string) error {
|
||||
if strings.TrimSpace(value) == "" || value == "" {
|
||||
return ErrInvalidArgument("No value specified for condition")
|
||||
}
|
||||
|
||||
policyCond := policyCondition{
|
||||
matchType: matchType,
|
||||
condition: "$" + condition,
|
||||
value: value,
|
||||
}
|
||||
if condition == "X-Amz-Credential" || condition == "X-Amz-Date" || condition == "X-Amz-Algorithm" {
|
||||
if err := p.addNewPolicy(policyCond); err != nil {
|
||||
return err
|
||||
}
|
||||
p.formData[condition] = value
|
||||
return nil
|
||||
}
|
||||
return ErrInvalidArgument("Invalid condition in policy")
|
||||
}
|
||||
|
||||
// SetContentType - Sets content-type of the object for this policy
|
||||
// based upload.
|
||||
func (p *PostPolicy) SetContentType(contentType string) error {
|
||||
|
||||
37
vendor/github.com/minio/minio-go/v6/retry.go
сгенерированный
поставляемый
37
vendor/github.com/minio/minio-go/v6/retry.go
сгенерированный
поставляемый
@@ -18,10 +18,7 @@
|
||||
package minio
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -85,40 +82,6 @@ func (c Client) newRetryTimer(maxRetry int, unit time.Duration, cap time.Duratio
|
||||
return attemptCh
|
||||
}
|
||||
|
||||
// isHTTPReqErrorRetryable - is http requests error retryable, such
|
||||
// as i/o timeout, connection broken etc..
|
||||
func isHTTPReqErrorRetryable(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
switch e := err.(type) {
|
||||
case *url.Error:
|
||||
switch e.Err.(type) {
|
||||
case *net.DNSError, *net.OpError, net.UnknownNetworkError:
|
||||
return true
|
||||
}
|
||||
if strings.Contains(err.Error(), "Connection closed by foreign host") {
|
||||
return true
|
||||
} else if strings.Contains(err.Error(), "net/http: TLS handshake timeout") {
|
||||
// If error is - tlsHandshakeTimeoutError, retry.
|
||||
return true
|
||||
} else if strings.Contains(err.Error(), "i/o timeout") {
|
||||
// If error is - tcp timeoutError, retry.
|
||||
return true
|
||||
} else if strings.Contains(err.Error(), "connection timed out") {
|
||||
// If err is a net.Dial timeout, retry.
|
||||
return true
|
||||
} else if strings.Contains(err.Error(), "net/http: HTTP/1.x transport connection broken") {
|
||||
// If error is transport connection broken, retry.
|
||||
return true
|
||||
} else if strings.Contains(err.Error(), "net/http: timeout awaiting response headers") {
|
||||
// Retry errors due to server not sending the response before timeout
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// List of AWS S3 error codes which are retryable.
|
||||
var retryableS3Codes = map[string]struct{}{
|
||||
"RequestError": {},
|
||||
|
||||
22
vendor/github.com/minio/minio-go/v6/transport.go
сгенерированный
поставляемый
22
vendor/github.com/minio/minio-go/v6/transport.go
сгенерированный
поставляемый
@@ -21,12 +21,9 @@ package minio
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
// DefaultTransport - this default transport is similar to
|
||||
@@ -54,29 +51,12 @@ var DefaultTransport = func(secure bool) (http.RoundTripper, error) {
|
||||
}
|
||||
|
||||
if secure {
|
||||
rootCAs, _ := x509.SystemCertPool()
|
||||
if rootCAs == nil {
|
||||
// In some systems (like Windows) system cert pool is
|
||||
// not supported or no certificates are present on the
|
||||
// system - so we create a new cert pool.
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
|
||||
// Keep TLS config.
|
||||
tlsConfig := &tls.Config{
|
||||
RootCAs: rootCAs,
|
||||
tr.TLSClientConfig = &tls.Config{
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
tr.TLSClientConfig = tlsConfig
|
||||
|
||||
// Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.
|
||||
// See https://github.com/golang/go/issues/14275
|
||||
if err := http2.ConfigureTransport(tr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return tr, nil
|
||||
}
|
||||
|
||||
7
vendor/github.com/minio/minio-go/v6/utils.go
сгенерированный
поставляемый
7
vendor/github.com/minio/minio-go/v6/utils.go
сгенерированный
поставляемый
@@ -36,6 +36,11 @@ import (
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
)
|
||||
|
||||
func trimEtag(etag string) string {
|
||||
etag = strings.TrimPrefix(etag, "\"")
|
||||
return strings.TrimSuffix(etag, "\"")
|
||||
}
|
||||
|
||||
// xmlDecoder provide decoded value in xml.
|
||||
func xmlDecoder(body io.Reader, v interface{}) error {
|
||||
d := xml.NewDecoder(body)
|
||||
@@ -224,6 +229,8 @@ var supportedHeaders = []string{
|
||||
"content-disposition",
|
||||
"content-language",
|
||||
"x-amz-website-redirect-location",
|
||||
"x-amz-object-lock-mode",
|
||||
"x-amz-object-lock-retain-until-date",
|
||||
"expires",
|
||||
// Add more supported headers here.
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user