Update dependencies
Among others, this updates minio-go, so that the new "eu-west-3" zone for AWS is supported.
This commit is contained in:
parent
b63de7c798
commit
2b39f9f4b2
3435 changed files with 1318042 additions and 315692 deletions
8
vendor/github.com/minio/minio-go/Makefile
generated
vendored
8
vendor/github.com/minio/minio-go/Makefile
generated
vendored
|
@ -1,13 +1,11 @@
|
|||
all: checks
|
||||
|
||||
checks:
|
||||
@go get -u github.com/go-ini/ini/...
|
||||
@go get -u github.com/minio/go-homedir/...
|
||||
@go get -u github.com/cheggaaa/pb/...
|
||||
@go get -u github.com/sirupsen/logrus/...
|
||||
@go get -u github.com/dustin/go-humanize/...
|
||||
@go get -t ./...
|
||||
@go vet ./...
|
||||
@SERVER_ENDPOINT=play.minio.io:9000 ACCESS_KEY=Q3AM3UQ867SPQQA43P2F SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG ENABLE_HTTPS=1 go test -race -v ./...
|
||||
@go get github.com/dustin/go-humanize/...
|
||||
@go get github.com/sirupsen/logrus/...
|
||||
@SERVER_ENDPOINT=play.minio.io:9000 ACCESS_KEY=Q3AM3UQ867SPQQA43P2F SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG ENABLE_HTTPS=1 go run functional_tests.go
|
||||
@mkdir -p /tmp/examples && for i in $(echo examples/s3/*); do go build -o /tmp/examples/$(basename ${i:0:-3}) ${i}; done
|
||||
@go get -u github.com/a8m/mark/...
|
||||
|
|
246
vendor/github.com/minio/minio-go/README_zh_CN.md
generated
vendored
Normal file
246
vendor/github.com/minio/minio-go/README_zh_CN.md
generated
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
# 适用于与Amazon S3兼容云存储的Minio Go SDK [](https://slack.minio.io) [](https://sourcegraph.com/github.com/minio/minio-go?badge)
|
||||
|
||||
Minio Go Client SDK提供了简单的API来访问任何与Amazon S3兼容的对象存储服务。
|
||||
|
||||
**支持的云存储:**
|
||||
|
||||
- AWS Signature Version 4
|
||||
- Amazon S3
|
||||
- Minio
|
||||
|
||||
- AWS Signature Version 2
|
||||
- Google Cloud Storage (兼容模式)
|
||||
- Openstack Swift + Swift3 middleware
|
||||
- Ceph Object Gateway
|
||||
- Riak CS
|
||||
|
||||
本文我们将学习如何安装Minio client SDK,连接到Minio,并提供一下文件上传的示例。对于完整的API以及示例,请参考[Go Client API Reference](https://docs.minio.io/docs/golang-client-api-reference)。
|
||||
|
||||
本文假设你已经有 [Go开发环境](https://docs.minio.io/docs/how-to-install-golang)。
|
||||
|
||||
## 从Github下载
|
||||
```sh
|
||||
go get -u github.com/minio/minio-go
|
||||
```
|
||||
|
||||
## 初始化Minio Client
|
||||
Minio client需要以下4个参数来连接与Amazon S3兼容的对象存储。
|
||||
|
||||
| 参数 | 描述|
|
||||
| :--- | :--- |
|
||||
| endpoint | 对象存储服务的URL |
|
||||
| accessKeyID | Access key是唯一标识你的账户的用户ID。 |
|
||||
| secretAccessKey | Secret key是你账户的密码。 |
|
||||
| secure | true代表使用HTTPS |
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/minio/minio-go"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
endpoint := "play.minio.io:9000"
|
||||
accessKeyID := "Q3AM3UQ867SPQQA43P2F"
|
||||
secretAccessKey := "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"
|
||||
useSSL := true
|
||||
|
||||
// 初使化 minio client对象。
|
||||
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
log.Printf("%#v\n", minioClient) // minioClient初使化成功
|
||||
}
|
||||
```
|
||||
|
||||
## 示例-文件上传
|
||||
本示例连接到一个对象存储服务,创建一个存储桶并上传一个文件到存储桶中。
|
||||
|
||||
我们在本示例中使用运行在 [https://play.minio.io:9000](https://play.minio.io:9000) 上的Minio服务,你可以用这个服务来开发和测试。示例中的访问凭据是公开的。
|
||||
|
||||
### FileUploader.go
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/minio/minio-go"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
endpoint := "play.minio.io:9000"
|
||||
accessKeyID := "Q3AM3UQ867SPQQA43P2F"
|
||||
secretAccessKey := "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"
|
||||
useSSL := true
|
||||
|
||||
// 初使化minio client对象。
|
||||
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// 创建一个叫mymusic的存储桶。
|
||||
bucketName := "mymusic"
|
||||
location := "us-east-1"
|
||||
|
||||
err = minioClient.MakeBucket(bucketName, location)
|
||||
if err != nil {
|
||||
// 检查存储桶是否已经存在。
|
||||
exists, err := minioClient.BucketExists(bucketName)
|
||||
if err == nil && exists {
|
||||
log.Printf("We already own %s\n", bucketName)
|
||||
} else {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
log.Printf("Successfully created %s\n", bucketName)
|
||||
|
||||
// 上传一个zip文件。
|
||||
objectName := "golden-oldies.zip"
|
||||
filePath := "/tmp/golden-oldies.zip"
|
||||
contentType := "application/zip"
|
||||
|
||||
// 使用FPutObject上传一个zip文件。
|
||||
n, err := minioClient.FPutObject(bucketName, objectName, filePath, minio.PutObjectOptions{ContentType:contentType})
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
log.Printf("Successfully uploaded %s of size %d\n", objectName, n)
|
||||
}
|
||||
```
|
||||
|
||||
### 运行FileUploader
|
||||
```sh
|
||||
go run file-uploader.go
|
||||
2016/08/13 17:03:28 Successfully created mymusic
|
||||
2016/08/13 17:03:40 Successfully uploaded golden-oldies.zip of size 16253413
|
||||
|
||||
mc ls play/mymusic/
|
||||
[2016-05-27 16:02:16 PDT] 17MiB golden-oldies.zip
|
||||
```
|
||||
|
||||
## API文档
|
||||
完整的API文档在这里。
|
||||
* [完整API文档](https://docs.minio.io/docs/golang-client-api-reference)
|
||||
|
||||
### API文档 : 操作存储桶
|
||||
* [`MakeBucket`](https://docs.minio.io/docs/golang-client-api-reference#MakeBucket)
|
||||
* [`ListBuckets`](https://docs.minio.io/docs/golang-client-api-reference#ListBuckets)
|
||||
* [`BucketExists`](https://docs.minio.io/docs/golang-client-api-reference#BucketExists)
|
||||
* [`RemoveBucket`](https://docs.minio.io/docs/golang-client-api-reference#RemoveBucket)
|
||||
* [`ListObjects`](https://docs.minio.io/docs/golang-client-api-reference#ListObjects)
|
||||
* [`ListObjectsV2`](https://docs.minio.io/docs/golang-client-api-reference#ListObjectsV2)
|
||||
* [`ListIncompleteUploads`](https://docs.minio.io/docs/golang-client-api-reference#ListIncompleteUploads)
|
||||
|
||||
### API文档 : 存储桶策略
|
||||
* [`SetBucketPolicy`](https://docs.minio.io/docs/golang-client-api-reference#SetBucketPolicy)
|
||||
* [`GetBucketPolicy`](https://docs.minio.io/docs/golang-client-api-reference#GetBucketPolicy)
|
||||
* [`ListBucketPolicies`](https://docs.minio.io/docs/golang-client-api-reference#ListBucketPolicies)
|
||||
|
||||
### API文档 : 存储桶通知
|
||||
* [`SetBucketNotification`](https://docs.minio.io/docs/golang-client-api-reference#SetBucketNotification)
|
||||
* [`GetBucketNotification`](https://docs.minio.io/docs/golang-client-api-reference#GetBucketNotification)
|
||||
* [`RemoveAllBucketNotification`](https://docs.minio.io/docs/golang-client-api-reference#RemoveAllBucketNotification)
|
||||
* [`ListenBucketNotification`](https://docs.minio.io/docs/golang-client-api-reference#ListenBucketNotification) (Minio Extension)
|
||||
|
||||
### API文档 : 操作文件对象
|
||||
* [`FPutObject`](https://docs.minio.io/docs/golang-client-api-reference#FPutObject)
|
||||
* [`FGetObject`](https://docs.minio.io/docs/golang-client-api-reference#FPutObject)
|
||||
* [`FPutObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FPutObjectWithContext)
|
||||
* [`FGetObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FGetObjectWithContext)
|
||||
|
||||
### API文档 : 操作对象
|
||||
* [`GetObject`](https://docs.minio.io/docs/golang-client-api-reference#GetObject)
|
||||
* [`PutObject`](https://docs.minio.io/docs/golang-client-api-reference#PutObject)
|
||||
* [`GetObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#GetObjectWithContext)
|
||||
* [`PutObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#PutObjectWithContext)
|
||||
* [`PutObjectStreaming`](https://docs.minio.io/docs/golang-client-api-reference#PutObjectStreaming)
|
||||
* [`StatObject`](https://docs.minio.io/docs/golang-client-api-reference#StatObject)
|
||||
* [`CopyObject`](https://docs.minio.io/docs/golang-client-api-reference#CopyObject)
|
||||
* [`RemoveObject`](https://docs.minio.io/docs/golang-client-api-reference#RemoveObject)
|
||||
* [`RemoveObjects`](https://docs.minio.io/docs/golang-client-api-reference#RemoveObjects)
|
||||
* [`RemoveIncompleteUpload`](https://docs.minio.io/docs/golang-client-api-reference#RemoveIncompleteUpload)
|
||||
|
||||
### API文档: 操作加密对象
|
||||
* [`GetEncryptedObject`](https://docs.minio.io/docs/golang-client-api-reference#GetEncryptedObject)
|
||||
* [`PutEncryptedObject`](https://docs.minio.io/docs/golang-client-api-reference#PutEncryptedObject)
|
||||
|
||||
### API文档 : Presigned操作
|
||||
* [`PresignedGetObject`](https://docs.minio.io/docs/golang-client-api-reference#PresignedGetObject)
|
||||
* [`PresignedPutObject`](https://docs.minio.io/docs/golang-client-api-reference#PresignedPutObject)
|
||||
* [`PresignedHeadObject`](https://docs.minio.io/docs/golang-client-api-reference#PresignedHeadObject)
|
||||
* [`PresignedPostPolicy`](https://docs.minio.io/docs/golang-client-api-reference#PresignedPostPolicy)
|
||||
|
||||
### API文档 : 客户端自定义设置
|
||||
* [`SetAppInfo`](http://docs.minio.io/docs/golang-client-api-reference#SetAppInfo)
|
||||
* [`SetCustomTransport`](http://docs.minio.io/docs/golang-client-api-reference#SetCustomTransport)
|
||||
* [`TraceOn`](http://docs.minio.io/docs/golang-client-api-reference#TraceOn)
|
||||
* [`TraceOff`](http://docs.minio.io/docs/golang-client-api-reference#TraceOff)
|
||||
|
||||
## 完整示例
|
||||
|
||||
### 完整示例 : 操作存储桶
|
||||
* [makebucket.go](https://github.com/minio/minio-go/blob/master/examples/s3/makebucket.go)
|
||||
* [listbuckets.go](https://github.com/minio/minio-go/blob/master/examples/s3/listbuckets.go)
|
||||
* [bucketexists.go](https://github.com/minio/minio-go/blob/master/examples/s3/bucketexists.go)
|
||||
* [removebucket.go](https://github.com/minio/minio-go/blob/master/examples/s3/removebucket.go)
|
||||
* [listobjects.go](https://github.com/minio/minio-go/blob/master/examples/s3/listobjects.go)
|
||||
* [listobjectsV2.go](https://github.com/minio/minio-go/blob/master/examples/s3/listobjectsV2.go)
|
||||
* [listincompleteuploads.go](https://github.com/minio/minio-go/blob/master/examples/s3/listincompleteuploads.go)
|
||||
|
||||
### 完整示例 : 存储桶策略
|
||||
* [setbucketpolicy.go](https://github.com/minio/minio-go/blob/master/examples/s3/setbucketpolicy.go)
|
||||
* [getbucketpolicy.go](https://github.com/minio/minio-go/blob/master/examples/s3/getbucketpolicy.go)
|
||||
* [listbucketpolicies.go](https://github.com/minio/minio-go/blob/master/examples/s3/listbucketpolicies.go)
|
||||
|
||||
### 完整示例 : 存储桶通知
|
||||
* [setbucketnotification.go](https://github.com/minio/minio-go/blob/master/examples/s3/setbucketnotification.go)
|
||||
* [getbucketnotification.go](https://github.com/minio/minio-go/blob/master/examples/s3/getbucketnotification.go)
|
||||
* [removeallbucketnotification.go](https://github.com/minio/minio-go/blob/master/examples/s3/removeallbucketnotification.go)
|
||||
* [listenbucketnotification.go](https://github.com/minio/minio-go/blob/master/examples/minio/listenbucketnotification.go) (Minio扩展)
|
||||
|
||||
### 完整示例 : 操作文件对象
|
||||
* [fputobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/fputobject.go)
|
||||
* [fgetobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/fgetobject.go)
|
||||
* [fputobject-context.go](https://github.com/minio/minio-go/blob/master/examples/s3/fputobject-context.go)
|
||||
* [fgetobject-context.go](https://github.com/minio/minio-go/blob/master/examples/s3/fgetobject-context.go)
|
||||
|
||||
### 完整示例 : 操作对象
|
||||
* [putobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/putobject.go)
|
||||
* [getobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/getobject.go)
|
||||
* [putobject-context.go](https://github.com/minio/minio-go/blob/master/examples/s3/putobject-context.go)
|
||||
* [getobject-context.go](https://github.com/minio/minio-go/blob/master/examples/s3/getobject-context.go)
|
||||
* [statobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/statobject.go)
|
||||
* [copyobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/copyobject.go)
|
||||
* [removeobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/removeobject.go)
|
||||
* [removeincompleteupload.go](https://github.com/minio/minio-go/blob/master/examples/s3/removeincompleteupload.go)
|
||||
* [removeobjects.go](https://github.com/minio/minio-go/blob/master/examples/s3/removeobjects.go)
|
||||
|
||||
### 完整示例 : 操作加密对象
|
||||
* [put-encrypted-object.go](https://github.com/minio/minio-go/blob/master/examples/s3/put-encrypted-object.go)
|
||||
* [get-encrypted-object.go](https://github.com/minio/minio-go/blob/master/examples/s3/get-encrypted-object.go)
|
||||
* [fput-encrypted-object.go](https://github.com/minio/minio-go/blob/master/examples/s3/fputencrypted-object.go)
|
||||
|
||||
### 完整示例 : Presigned操作
|
||||
* [presignedgetobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/presignedgetobject.go)
|
||||
* [presignedputobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/presignedputobject.go)
|
||||
* [presignedheadobject.go](https://github.com/minio/minio-go/blob/master/examples/s3/presignedheadobject.go)
|
||||
* [presignedpostpolicy.go](https://github.com/minio/minio-go/blob/master/examples/s3/presignedpostpolicy.go)
|
||||
|
||||
## 了解更多
|
||||
* [完整文档](https://docs.minio.io)
|
||||
* [Minio Go Client SDK API文档](https://docs.minio.io/docs/golang-client-api-reference)
|
||||
* [Go 音乐播放器完整示例](https://docs.minio.io/docs/go-music-player-app)
|
||||
|
||||
## 贡献
|
||||
[贡献指南](https://github.com/minio/minio-go/blob/master/docs/zh_CN/CONTRIBUTING.md)
|
||||
|
||||
[](https://travis-ci.org/minio/minio-go)
|
||||
[](https://ci.appveyor.com/project/harshavardhana/minio-go)
|
||||
|
52
vendor/github.com/minio/minio-go/api-compose-object.go
generated
vendored
52
vendor/github.com/minio/minio-go/api-compose-object.go
generated
vendored
|
@ -249,7 +249,7 @@ func (s *SourceInfo) getProps(c Client) (size int64, etag string, userMeta map[s
|
|||
for k, v := range s.decryptKey.getSSEHeaders(false) {
|
||||
opts.Set(k, v)
|
||||
}
|
||||
objInfo, err = c.statObject(s.bucket, s.object, opts)
|
||||
objInfo, err = c.statObject(context.Background(), s.bucket, s.object, opts)
|
||||
if err != nil {
|
||||
err = ErrInvalidArgument(fmt.Sprintf("Could not stat object - %s/%s: %v", s.bucket, s.object, err))
|
||||
} else {
|
||||
|
@ -312,6 +312,56 @@ func (c Client) copyObjectDo(ctx context.Context, srcBucket, srcObject, destBuck
|
|||
return objInfo, nil
|
||||
}
|
||||
|
||||
func (c Client) copyObjectPartDo(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string,
|
||||
partID int, startOffset int64, length int64, metadata map[string]string) (p CompletePart, err error) {
|
||||
|
||||
headers := make(http.Header)
|
||||
|
||||
// Set source
|
||||
headers.Set("x-amz-copy-source", s3utils.EncodePath(srcBucket+"/"+srcObject))
|
||||
|
||||
if startOffset < 0 {
|
||||
return p, ErrInvalidArgument("startOffset must be non-negative")
|
||||
}
|
||||
|
||||
if length >= 0 {
|
||||
headers.Set("x-amz-copy-source-range", fmt.Sprintf("bytes=%d-%d", startOffset, startOffset+length-1))
|
||||
}
|
||||
|
||||
for k, v := range metadata {
|
||||
headers.Set(k, v)
|
||||
}
|
||||
|
||||
queryValues := make(url.Values)
|
||||
queryValues.Set("partNumber", strconv.Itoa(partID))
|
||||
queryValues.Set("uploadId", uploadID)
|
||||
|
||||
resp, err := c.executeMethod(ctx, "PUT", requestMetadata{
|
||||
bucketName: destBucket,
|
||||
objectName: destObject,
|
||||
customHeader: headers,
|
||||
queryValues: queryValues,
|
||||
})
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if we got an error response.
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return p, httpRespToErrorResponse(resp, destBucket, destObject)
|
||||
}
|
||||
|
||||
// Decode copy-part response on success.
|
||||
cpObjRes := copyObjectResult{}
|
||||
err = xmlDecoder(resp.Body, &cpObjRes)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
p.PartNumber, p.ETag = partID, cpObjRes.ETag
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// uploadPartCopy - helper function to create a part in a multipart
|
||||
// upload via an upload-part-copy request
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html
|
||||
|
|
2
vendor/github.com/minio/minio-go/api-datatypes.go
generated
vendored
2
vendor/github.com/minio/minio-go/api-datatypes.go
generated
vendored
|
@ -44,7 +44,7 @@ type ObjectInfo struct {
|
|||
|
||||
// Collection of additional metadata on the object.
|
||||
// eg: x-amz-meta-*, content-encoding etc.
|
||||
Metadata http.Header `json:"metadata"`
|
||||
Metadata http.Header `json:"metadata" xml:"-"`
|
||||
|
||||
// Owner name.
|
||||
Owner struct {
|
||||
|
|
4
vendor/github.com/minio/minio-go/api-get-object.go
generated
vendored
4
vendor/github.com/minio/minio-go/api-get-object.go
generated
vendored
|
@ -127,7 +127,7 @@ func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName
|
|||
} else {
|
||||
// First request is a Stat or Seek call.
|
||||
// Only need to run a StatObject until an actual Read or ReadAt request comes through.
|
||||
objectInfo, err = c.statObject(bucketName, objectName, StatObjectOptions{opts})
|
||||
objectInfo, err = c.statObject(ctx, bucketName, objectName, StatObjectOptions{opts})
|
||||
if err != nil {
|
||||
resCh <- getResponse{
|
||||
Error: err,
|
||||
|
@ -145,7 +145,7 @@ func (c Client) getObjectWithContext(ctx context.Context, bucketName, objectName
|
|||
if etag != "" {
|
||||
opts.SetMatchETag(etag)
|
||||
}
|
||||
objectInfo, err := c.statObject(bucketName, objectName, StatObjectOptions{opts})
|
||||
objectInfo, err := c.statObject(ctx, bucketName, objectName, StatObjectOptions{opts})
|
||||
if err != nil {
|
||||
resCh <- getResponse{
|
||||
Error: err,
|
||||
|
|
2
vendor/github.com/minio/minio-go/api-notification.go
generated
vendored
2
vendor/github.com/minio/minio-go/api-notification.go
generated
vendored
|
@ -150,7 +150,7 @@ func (c Client) ListenBucketNotification(bucketName, prefix, suffix string, even
|
|||
}
|
||||
|
||||
// Check ARN partition to verify if listening bucket is supported
|
||||
if s3utils.IsAmazonEndpoint(c.endpointURL) || s3utils.IsGoogleEndpoint(c.endpointURL) {
|
||||
if s3utils.IsAmazonEndpoint(*c.endpointURL) || s3utils.IsGoogleEndpoint(*c.endpointURL) {
|
||||
notificationInfoCh <- NotificationInfo{
|
||||
Err: ErrAPINotSupported("Listening for bucket notification is specific only to `minio` server endpoints"),
|
||||
}
|
||||
|
|
2
vendor/github.com/minio/minio-go/api-presigned.go
generated
vendored
2
vendor/github.com/minio/minio-go/api-presigned.go
generated
vendored
|
@ -148,7 +148,7 @@ func (c Client) PresignedPostPolicy(p *PostPolicy) (u *url.URL, formData map[str
|
|||
policyBase64 := p.base64()
|
||||
p.formData["policy"] = policyBase64
|
||||
// For Google endpoint set this value to be 'GoogleAccessId'.
|
||||
if s3utils.IsGoogleEndpoint(c.endpointURL) {
|
||||
if s3utils.IsGoogleEndpoint(*c.endpointURL) {
|
||||
p.formData["GoogleAccessId"] = accessKeyID
|
||||
} else {
|
||||
// For all other endpoints set this value to be 'AWSAccessKeyId'.
|
||||
|
|
2
vendor/github.com/minio/minio-go/api-put-object-streaming.go
generated
vendored
2
vendor/github.com/minio/minio-go/api-put-object-streaming.go
generated
vendored
|
@ -339,7 +339,7 @@ func (c Client) putObjectNoChecksum(ctx context.Context, bucketName, objectName
|
|||
|
||||
// Size -1 is only supported on Google Cloud Storage, we error
|
||||
// out in all other situations.
|
||||
if size < 0 && !s3utils.IsGoogleEndpoint(c.endpointURL) {
|
||||
if size < 0 && !s3utils.IsGoogleEndpoint(*c.endpointURL) {
|
||||
return 0, ErrEntityTooSmall(size, bucketName, objectName)
|
||||
}
|
||||
if size > 0 {
|
||||
|
|
18
vendor/github.com/minio/minio-go/api-put-object.go
generated
vendored
18
vendor/github.com/minio/minio-go/api-put-object.go
generated
vendored
|
@ -28,6 +28,7 @@ import (
|
|||
|
||||
"github.com/minio/minio-go/pkg/encrypt"
|
||||
"github.com/minio/minio-go/pkg/s3utils"
|
||||
"golang.org/x/net/lex/httplex"
|
||||
)
|
||||
|
||||
// PutObjectOptions represents options specified by user for PutObject call
|
||||
|
@ -40,6 +41,7 @@ type PutObjectOptions struct {
|
|||
CacheControl string
|
||||
EncryptMaterials encrypt.Materials
|
||||
NumThreads uint
|
||||
StorageClass string
|
||||
}
|
||||
|
||||
// getNumThreads - gets the number of threads to be used in the multipart
|
||||
|
@ -77,8 +79,11 @@ func (opts PutObjectOptions) Header() (header http.Header) {
|
|||
header[amzHeaderKey] = []string{opts.EncryptMaterials.GetKey()}
|
||||
header[amzHeaderMatDesc] = []string{opts.EncryptMaterials.GetDesc()}
|
||||
}
|
||||
if opts.StorageClass != "" {
|
||||
header[amzStorageClass] = []string{opts.StorageClass}
|
||||
}
|
||||
for k, v := range opts.UserMetadata {
|
||||
if !isAmzHeader(k) && !isStandardHeader(k) && !isSSEHeader(k) {
|
||||
if !isAmzHeader(k) && !isStandardHeader(k) && !isSSEHeader(k) && !isStorageClassHeader(k) {
|
||||
header["X-Amz-Meta-"+k] = []string{v}
|
||||
} else {
|
||||
header[k] = []string{v}
|
||||
|
@ -90,9 +95,12 @@ func (opts PutObjectOptions) Header() (header http.Header) {
|
|||
// validate() checks if the UserMetadata map has standard headers or client side
|
||||
// encryption headers and raises an error if so.
|
||||
func (opts PutObjectOptions) validate() (err error) {
|
||||
for k := range opts.UserMetadata {
|
||||
if isStandardHeader(k) || isCSEHeader(k) {
|
||||
return ErrInvalidArgument(k + " unsupported request parameter for user defined metadata")
|
||||
for k, v := range opts.UserMetadata {
|
||||
if !httplex.ValidHeaderFieldName(k) || isStandardHeader(k) || isCSEHeader(k) || isStorageClassHeader(k) {
|
||||
return ErrInvalidArgument(k + " unsupported user defined metadata name")
|
||||
}
|
||||
if !httplex.ValidHeaderFieldValue(v) {
|
||||
return ErrInvalidArgument(v + " unsupported user defined metadata value")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -129,7 +137,7 @@ func (c Client) putObjectCommon(ctx context.Context, bucketName, objectName stri
|
|||
}
|
||||
|
||||
// NOTE: Streaming signature is not supported by GCS.
|
||||
if s3utils.IsGoogleEndpoint(c.endpointURL) {
|
||||
if s3utils.IsGoogleEndpoint(*c.endpointURL) {
|
||||
// Do not compute MD5 for Google Cloud Storage.
|
||||
return c.putObjectNoChecksum(ctx, bucketName, objectName, reader, size, opts)
|
||||
}
|
||||
|
|
53
vendor/github.com/minio/minio-go/api-put-object_test.go
generated
vendored
53
vendor/github.com/minio/minio-go/api-put-object_test.go
generated
vendored
|
@ -22,32 +22,41 @@ import (
|
|||
|
||||
func TestPutObjectOptionsValidate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
metadata map[string]string
|
||||
shouldPass bool
|
||||
name, value string
|
||||
shouldPass bool
|
||||
}{
|
||||
{map[string]string{"Content-Type": "custom/content-type"}, false},
|
||||
{map[string]string{"content-type": "custom/content-type"}, false},
|
||||
{map[string]string{"Content-Encoding": "gzip"}, false},
|
||||
{map[string]string{"Cache-Control": "blah"}, false},
|
||||
{map[string]string{"Content-Disposition": "something"}, false},
|
||||
{map[string]string{"my-custom-header": "blah"}, true},
|
||||
{map[string]string{"X-Amz-Iv": "blah"}, false},
|
||||
{map[string]string{"X-Amz-Key": "blah"}, false},
|
||||
{map[string]string{"X-Amz-Key-prefixed-header": "blah"}, false},
|
||||
{map[string]string{"custom-X-Amz-Key-middle": "blah"}, true},
|
||||
{map[string]string{"my-custom-header-X-Amz-Key": "blah"}, true},
|
||||
{map[string]string{"X-Amz-Matdesc": "blah"}, false},
|
||||
{map[string]string{"blah-X-Amz-Matdesc": "blah"}, true},
|
||||
{map[string]string{"X-Amz-MatDesc-suffix": "blah"}, true},
|
||||
{map[string]string{"x-amz-meta-X-Amz-Iv": "blah"}, false},
|
||||
{map[string]string{"x-amz-meta-X-Amz-Key": "blah"}, false},
|
||||
{map[string]string{"x-amz-meta-X-Amz-Matdesc": "blah"}, false},
|
||||
// Invalid cases.
|
||||
{"X-Amz-Matdesc", "blah", false},
|
||||
{"x-amz-meta-X-Amz-Iv", "blah", false},
|
||||
{"x-amz-meta-X-Amz-Key", "blah", false},
|
||||
{"x-amz-meta-X-Amz-Matdesc", "blah", false},
|
||||
{"It has spaces", "v", false},
|
||||
{"It,has@illegal=characters", "v", false},
|
||||
{"X-Amz-Iv", "blah", false},
|
||||
{"X-Amz-Key", "blah", false},
|
||||
{"X-Amz-Key-prefixed-header", "blah", false},
|
||||
{"Content-Type", "custom/content-type", false},
|
||||
{"content-type", "custom/content-type", false},
|
||||
{"Content-Encoding", "gzip", false},
|
||||
{"Cache-Control", "blah", false},
|
||||
{"Content-Disposition", "something", false},
|
||||
|
||||
// Valid metadata names.
|
||||
{"my-custom-header", "blah", true},
|
||||
{"custom-X-Amz-Key-middle", "blah", true},
|
||||
{"my-custom-header-X-Amz-Key", "blah", true},
|
||||
{"blah-X-Amz-Matdesc", "blah", true},
|
||||
{"X-Amz-MatDesc-suffix", "blah", true},
|
||||
{"It-Is-Fine", "v", true},
|
||||
{"Numbers-098987987-Should-Work", "v", true},
|
||||
{"Crazy-!#$%&'*+-.^_`|~-Should-193832-Be-Fine", "v", true},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
err := PutObjectOptions{UserMetadata: testCase.metadata}.validate()
|
||||
|
||||
err := PutObjectOptions{UserMetadata: map[string]string{
|
||||
testCase.name: testCase.value,
|
||||
}}.validate()
|
||||
if testCase.shouldPass && err != nil {
|
||||
t.Errorf("Test %d - output did not match with reference results", i+1)
|
||||
t.Errorf("Test %d - output did not match with reference results, %s", i+1, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
6
vendor/github.com/minio/minio-go/api-stat.go
generated
vendored
6
vendor/github.com/minio/minio-go/api-stat.go
generated
vendored
|
@ -90,11 +90,11 @@ func (c Client) StatObject(bucketName, objectName string, opts StatObjectOptions
|
|||
if err := s3utils.CheckValidObjectName(objectName); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
}
|
||||
return c.statObject(bucketName, objectName, opts)
|
||||
return c.statObject(context.Background(), bucketName, objectName, opts)
|
||||
}
|
||||
|
||||
// Lower level API for statObject supporting pre-conditions and range headers.
|
||||
func (c Client) statObject(bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) {
|
||||
func (c Client) statObject(ctx context.Context, bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) {
|
||||
// Input validation.
|
||||
if err := s3utils.CheckValidBucketName(bucketName); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
|
@ -104,7 +104,7 @@ func (c Client) statObject(bucketName, objectName string, opts StatObjectOptions
|
|||
}
|
||||
|
||||
// Execute HEAD on objectName.
|
||||
resp, err := c.executeMethod(context.Background(), "HEAD", requestMetadata{
|
||||
resp, err := c.executeMethod(ctx, "HEAD", requestMetadata{
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
contentSHA256Hex: emptySHA256Hex,
|
||||
|
|
144
vendor/github.com/minio/minio-go/api.go
generated
vendored
144
vendor/github.com/minio/minio-go/api.go
generated
vendored
|
@ -48,7 +48,7 @@ type Client struct {
|
|||
/// Standard options.
|
||||
|
||||
// Parsed endpoint url provided by the user.
|
||||
endpointURL url.URL
|
||||
endpointURL *url.URL
|
||||
|
||||
// Holds various credential providers.
|
||||
credsProvider *credentials.Credentials
|
||||
|
@ -86,7 +86,7 @@ type Client struct {
|
|||
// Global constants.
|
||||
const (
|
||||
libraryName = "minio-go"
|
||||
libraryVersion = "4.0.3"
|
||||
libraryVersion = "4.0.6"
|
||||
)
|
||||
|
||||
// User Agent should always following the below style.
|
||||
|
@ -130,11 +130,11 @@ func New(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Client, e
|
|||
return nil, err
|
||||
}
|
||||
// Google cloud storage should be set to signature V2, force it if not.
|
||||
if s3utils.IsGoogleEndpoint(clnt.endpointURL) {
|
||||
if s3utils.IsGoogleEndpoint(*clnt.endpointURL) {
|
||||
clnt.overrideSignerType = credentials.SignatureV2
|
||||
}
|
||||
// If Amazon S3 set to signature v4.
|
||||
if s3utils.IsAmazonEndpoint(clnt.endpointURL) {
|
||||
if s3utils.IsAmazonEndpoint(*clnt.endpointURL) {
|
||||
clnt.overrideSignerType = credentials.SignatureV4
|
||||
}
|
||||
return clnt, nil
|
||||
|
@ -177,29 +177,66 @@ func (r *lockedRandSource) Seed(seed int64) {
|
|||
r.lk.Unlock()
|
||||
}
|
||||
|
||||
// getRegionFromURL - parse region from URL if present.
|
||||
func getRegionFromURL(u url.URL) (region string) {
|
||||
region = ""
|
||||
if s3utils.IsGoogleEndpoint(u) {
|
||||
return
|
||||
} else if s3utils.IsAmazonChinaEndpoint(u) {
|
||||
// For china specifically we need to set everything to
|
||||
// cn-north-1 for now, there is no easier way until AWS S3
|
||||
// provides a cleaner compatible API across "us-east-1" and
|
||||
// China region.
|
||||
return "cn-north-1"
|
||||
} else if s3utils.IsAmazonGovCloudEndpoint(u) {
|
||||
// For us-gov specifically we need to set everything to
|
||||
// us-gov-west-1 for now, there is no easier way until AWS S3
|
||||
// provides a cleaner compatible API across "us-east-1" and
|
||||
// Gov cloud region.
|
||||
return "us-gov-west-1"
|
||||
// Redirect requests by re signing the request.
|
||||
func (c *Client) redirectHeaders(req *http.Request, via []*http.Request) error {
|
||||
if len(via) >= 5 {
|
||||
return errors.New("stopped after 5 redirects")
|
||||
}
|
||||
parts := s3utils.AmazonS3Host.FindStringSubmatch(u.Host)
|
||||
if len(parts) > 1 {
|
||||
region = parts[1]
|
||||
if len(via) == 0 {
|
||||
return nil
|
||||
}
|
||||
return region
|
||||
lastRequest := via[len(via)-1]
|
||||
var reAuth bool
|
||||
for attr, val := range lastRequest.Header {
|
||||
// if hosts do not match do not copy Authorization header
|
||||
if attr == "Authorization" && req.Host != lastRequest.Host {
|
||||
reAuth = true
|
||||
continue
|
||||
}
|
||||
if _, ok := req.Header[attr]; !ok {
|
||||
req.Header[attr] = val
|
||||
}
|
||||
}
|
||||
|
||||
*c.endpointURL = *req.URL
|
||||
|
||||
value, err := c.credsProvider.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
signerType = value.SignerType
|
||||
accessKeyID = value.AccessKeyID
|
||||
secretAccessKey = value.SecretAccessKey
|
||||
sessionToken = value.SessionToken
|
||||
region = c.region
|
||||
)
|
||||
|
||||
// Custom signer set then override the behavior.
|
||||
if c.overrideSignerType != credentials.SignatureDefault {
|
||||
signerType = c.overrideSignerType
|
||||
}
|
||||
|
||||
// If signerType returned by credentials helper is anonymous,
|
||||
// then do not sign regardless of signerType override.
|
||||
if value.SignerType == credentials.SignatureAnonymous {
|
||||
signerType = credentials.SignatureAnonymous
|
||||
}
|
||||
|
||||
if reAuth {
|
||||
// Check if there is no region override, if not get it from the URL if possible.
|
||||
if region == "" {
|
||||
region = s3utils.GetRegionFromURL(*c.endpointURL)
|
||||
}
|
||||
switch {
|
||||
case signerType.IsV2():
|
||||
// Add signature version '2' authorization header.
|
||||
req = s3signer.SignV2(*req, accessKeyID, secretAccessKey)
|
||||
case signerType.IsV4():
|
||||
req = s3signer.SignV4(*req, accessKeyID, secretAccessKey, sessionToken, getDefaultLocation(*c.endpointURL, region))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func privateNew(endpoint string, creds *credentials.Credentials, secure bool, region string) (*Client, error) {
|
||||
|
@ -219,16 +256,17 @@ func privateNew(endpoint string, creds *credentials.Credentials, secure bool, re
|
|||
clnt.secure = secure
|
||||
|
||||
// Save endpoint URL, user agent for future uses.
|
||||
clnt.endpointURL = *endpointURL
|
||||
clnt.endpointURL = endpointURL
|
||||
|
||||
// Instantiate http client and bucket location cache.
|
||||
clnt.httpClient = &http.Client{
|
||||
Transport: defaultMinioTransport,
|
||||
Transport: defaultMinioTransport,
|
||||
CheckRedirect: clnt.redirectHeaders,
|
||||
}
|
||||
|
||||
// Sets custom region, if region is empty bucket location cache is used automatically.
|
||||
if region == "" {
|
||||
region = getRegionFromURL(clnt.endpointURL)
|
||||
region = s3utils.GetRegionFromURL(*clnt.endpointURL)
|
||||
}
|
||||
clnt.region = region
|
||||
|
||||
|
@ -301,7 +339,7 @@ func (c *Client) TraceOff() {
|
|||
// please vist -
|
||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
||||
func (c *Client) SetS3TransferAccelerate(accelerateEndpoint string) {
|
||||
if s3utils.IsAmazonEndpoint(c.endpointURL) {
|
||||
if s3utils.IsAmazonEndpoint(*c.endpointURL) {
|
||||
c.s3AccelerateEndpoint = accelerateEndpoint
|
||||
}
|
||||
}
|
||||
|
@ -405,6 +443,7 @@ func (c Client) dumpHTTP(req *http.Request, resp *http.Response) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write response to trace output.
|
||||
_, err = fmt.Fprint(c.traceOutput, strings.TrimSuffix(string(respTrace), "\r\n"))
|
||||
if err != nil {
|
||||
|
@ -423,38 +462,22 @@ func (c Client) dumpHTTP(req *http.Request, resp *http.Response) error {
|
|||
|
||||
// do - execute http request.
|
||||
func (c Client) do(req *http.Request) (*http.Response, error) {
|
||||
var resp *http.Response
|
||||
var err error
|
||||
// Do the request in a loop in case of 307 http is met since golang still doesn't
|
||||
// handle properly this situation (https://github.com/golang/go/issues/7912)
|
||||
for {
|
||||
resp, err = c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
// Handle this specifically for now until future Golang
|
||||
// versions fix this issue properly.
|
||||
urlErr, ok := err.(*url.Error)
|
||||
if ok && strings.Contains(urlErr.Err.Error(), "EOF") {
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
// Handle this specifically for now until future Golang versions fix this issue properly.
|
||||
if urlErr, ok := err.(*url.Error); ok {
|
||||
if strings.Contains(urlErr.Err.Error(), "EOF") {
|
||||
return nil, &url.Error{
|
||||
Op: urlErr.Op,
|
||||
URL: urlErr.URL,
|
||||
Err: errors.New("Connection closed by foreign host " + urlErr.URL + ". Retry again."),
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
// Redo the request with the new redirect url if http 307 is returned, quit the loop otherwise
|
||||
if resp != nil && resp.StatusCode == http.StatusTemporaryRedirect {
|
||||
newURL, err := url.Parse(resp.Header.Get("Location"))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
req.URL = newURL
|
||||
} else {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Response cannot be non-nil, report if its the case.
|
||||
// Response cannot be non-nil, report error if thats the case.
|
||||
if resp == nil {
|
||||
msg := "Response is empty. " + reportIssue
|
||||
return nil, ErrInvalidArgument(msg)
|
||||
|
@ -467,6 +490,7 @@ func (c Client) do(req *http.Request) (*http.Response, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
@ -538,6 +562,7 @@ func (c Client) executeMethod(ctx context.Context, method string, metadata reque
|
|||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add context to request
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
|
@ -634,7 +659,7 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R
|
|||
// happen when GetBucketLocation() is disabled using IAM policies.
|
||||
}
|
||||
if location == "" {
|
||||
location = getDefaultLocation(c.endpointURL, c.region)
|
||||
location = getDefaultLocation(*c.endpointURL, c.region)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +787,7 @@ func (c Client) setUserAgent(req *http.Request) {
|
|||
func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, queryValues url.Values) (*url.URL, error) {
|
||||
host := c.endpointURL.Host
|
||||
// For Amazon S3 endpoint, try to fetch location based endpoint.
|
||||
if s3utils.IsAmazonEndpoint(c.endpointURL) {
|
||||
if s3utils.IsAmazonEndpoint(*c.endpointURL) {
|
||||
if c.s3AccelerateEndpoint != "" && bucketName != "" {
|
||||
// http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
|
||||
// Disable transfer acceleration for non-compliant bucket names.
|
||||
|
@ -775,7 +800,7 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
|
|||
host = c.s3AccelerateEndpoint
|
||||
} else {
|
||||
// Do not change the host if the endpoint URL is a FIPS S3 endpoint.
|
||||
if !s3utils.IsAmazonFIPSGovCloudEndpoint(c.endpointURL) {
|
||||
if !s3utils.IsAmazonFIPSGovCloudEndpoint(*c.endpointURL) {
|
||||
// Fetch new host based on the bucket location.
|
||||
host = getS3Endpoint(bucketLocation)
|
||||
}
|
||||
|
@ -799,7 +824,7 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
|
|||
// endpoint URL.
|
||||
if bucketName != "" {
|
||||
// Save if target url will have buckets which suppport virtual host.
|
||||
isVirtualHostStyle := s3utils.IsVirtualHostSupported(c.endpointURL, bucketName)
|
||||
isVirtualHostStyle := s3utils.IsVirtualHostSupported(*c.endpointURL, bucketName)
|
||||
|
||||
// If endpoint supports virtual host style use that always.
|
||||
// Currently only S3 and Google Cloud Storage would support
|
||||
|
@ -823,10 +848,5 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que
|
|||
urlStr = urlStr + "?" + s3utils.QueryEncode(queryValues)
|
||||
}
|
||||
|
||||
u, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return url.Parse(urlStr)
|
||||
}
|
||||
|
|
44
vendor/github.com/minio/minio-go/api_unit_test.go
generated
vendored
44
vendor/github.com/minio/minio-go/api_unit_test.go
generated
vendored
|
@ -36,50 +36,6 @@ func (c *customReader) Size() (n int64) {
|
|||
return 10
|
||||
}
|
||||
|
||||
// Tests get region from host URL.
|
||||
func TestGetRegionFromURL(t *testing.T) {
|
||||
testCases := []struct {
|
||||
u url.URL
|
||||
expectedRegion string
|
||||
}{
|
||||
{
|
||||
u: url.URL{Host: "storage.googleapis.com"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.cn-north-1.amazonaws.com.cn"},
|
||||
expectedRegion: "cn-north-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-fips-us-gov-west-1.amazonaws.com"},
|
||||
expectedRegion: "us-gov-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-us-gov-west-1.amazonaws.com"},
|
||||
expectedRegion: "us-gov-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "192.168.1.1"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-eu-west-1.amazonaws.com"},
|
||||
expectedRegion: "eu-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.amazonaws.com"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
region := getRegionFromURL(testCase.u)
|
||||
if testCase.expectedRegion != region {
|
||||
t.Errorf("Test %d: Expected region %s, got %s", i+1, testCase.expectedRegion, region)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests valid hosts for location.
|
||||
func TestValidBucketLocation(t *testing.T) {
|
||||
s3Hosts := []struct {
|
||||
|
|
4
vendor/github.com/minio/minio-go/appveyor.yml
generated
vendored
4
vendor/github.com/minio/minio-go/appveyor.yml
generated
vendored
|
@ -17,11 +17,9 @@ install:
|
|||
- go version
|
||||
- go env
|
||||
- go get -u github.com/golang/lint/golint
|
||||
- go get -u github.com/go-ini/ini
|
||||
- go get -u github.com/minio/go-homedir
|
||||
- go get -u github.com/remyoudompheng/go-misc/deadcode
|
||||
- go get -u github.com/gordonklaus/ineffassign
|
||||
- go get -u github.com/dustin/go-humanize
|
||||
- go get -t ./...
|
||||
|
||||
# to run your custom scripts instead of automatic MSBuild
|
||||
build_script:
|
||||
|
|
3
vendor/github.com/minio/minio-go/constants.go
generated
vendored
3
vendor/github.com/minio/minio-go/constants.go
generated
vendored
|
@ -65,3 +65,6 @@ const (
|
|||
amzHeaderKey = "X-Amz-Meta-X-Amz-Key"
|
||||
amzHeaderMatDesc = "X-Amz-Meta-X-Amz-Matdesc"
|
||||
)
|
||||
|
||||
// Storage class header constant.
|
||||
const amzStorageClass = "X-Amz-Storage-Class"
|
||||
|
|
11
vendor/github.com/minio/minio-go/core.go
generated
vendored
11
vendor/github.com/minio/minio-go/core.go
generated
vendored
|
@ -60,6 +60,15 @@ func (c Core) CopyObject(sourceBucket, sourceObject, destBucket, destObject stri
|
|||
return c.copyObjectDo(context.Background(), sourceBucket, sourceObject, destBucket, destObject, metadata)
|
||||
}
|
||||
|
||||
// CopyObjectPart - creates a part in a multipart upload by copying (a
|
||||
// part of) an existing object.
|
||||
func (c Core) CopyObjectPart(srcBucket, srcObject, destBucket, destObject string, uploadID string,
|
||||
partID int, startOffset, length int64, metadata map[string]string) (p CompletePart, err error) {
|
||||
|
||||
return c.copyObjectPartDo(context.Background(), srcBucket, srcObject, destBucket, destObject, uploadID,
|
||||
partID, startOffset, length, metadata)
|
||||
}
|
||||
|
||||
// PutObject - Upload object. Uploads using single PUT call.
|
||||
func (c Core) PutObject(bucket, object string, data io.Reader, size int64, md5Base64, sha256Hex string, metadata map[string]string) (ObjectInfo, error) {
|
||||
opts := PutObjectOptions{}
|
||||
|
@ -141,5 +150,5 @@ func (c Core) GetObject(bucketName, objectName string, opts GetObjectOptions) (i
|
|||
// StatObject is a lower level API implemented to support special
|
||||
// conditions matching etag, modtime on a request.
|
||||
func (c Core) StatObject(bucketName, objectName string, opts StatObjectOptions) (ObjectInfo, error) {
|
||||
return c.statObject(bucketName, objectName, opts)
|
||||
return c.statObject(context.Background(), bucketName, objectName, opts)
|
||||
}
|
||||
|
|
145
vendor/github.com/minio/minio-go/core_test.go
generated
vendored
145
vendor/github.com/minio/minio-go/core_test.go
generated
vendored
|
@ -484,6 +484,151 @@ func TestCoreCopyObject(t *testing.T) {
|
|||
// Do not need to remove destBucketName its same as bucketName.
|
||||
}
|
||||
|
||||
// Test Core CopyObjectPart implementation
|
||||
func TestCoreCopyObjectPart(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping functional tests for short runs")
|
||||
}
|
||||
|
||||
// Seed random based on current time.
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
// Instantiate new minio client object.
|
||||
c, err := NewCore(
|
||||
os.Getenv(serverEndpoint),
|
||||
os.Getenv(accessKey),
|
||||
os.Getenv(secretKey),
|
||||
mustParseBool(os.Getenv(enableSecurity)),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err)
|
||||
}
|
||||
|
||||
// Enable tracing, write to stderr.
|
||||
// c.TraceOn(os.Stderr)
|
||||
|
||||
// Set user agent.
|
||||
c.SetAppInfo("Minio-go-FunctionalTest", "0.1.0")
|
||||
|
||||
// Generate a new random bucket name.
|
||||
bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test")
|
||||
|
||||
// Make a new bucket.
|
||||
err = c.MakeBucket(bucketName, "us-east-1")
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, bucketName)
|
||||
}
|
||||
|
||||
// Make a buffer with 5MB of data
|
||||
buf := bytes.Repeat([]byte("abcde"), 1024*1024)
|
||||
|
||||
// Save the data
|
||||
objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "")
|
||||
objInfo, err := c.PutObject(bucketName, objectName, bytes.NewReader(buf), int64(len(buf)), "", "", map[string]string{
|
||||
"Content-Type": "binary/octet-stream",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, bucketName, objectName)
|
||||
}
|
||||
|
||||
if objInfo.Size != int64(len(buf)) {
|
||||
t.Fatalf("Error: number of bytes does not match, want %v, got %v\n", len(buf), objInfo.Size)
|
||||
}
|
||||
|
||||
destBucketName := bucketName
|
||||
destObjectName := objectName + "-dest"
|
||||
|
||||
uploadID, err := c.NewMultipartUpload(destBucketName, destObjectName, PutObjectOptions{})
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, bucketName, objectName)
|
||||
}
|
||||
|
||||
// Content of the destination object will be two copies of
|
||||
// `objectName` concatenated, followed by first byte of
|
||||
// `objectName`.
|
||||
|
||||
// First of three parts
|
||||
fstPart, err := c.CopyObjectPart(bucketName, objectName, destBucketName, destObjectName, uploadID, 1, 0, -1, nil)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
|
||||
// Second of three parts
|
||||
sndPart, err := c.CopyObjectPart(bucketName, objectName, destBucketName, destObjectName, uploadID, 2, 0, -1, nil)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
|
||||
// Last of three parts
|
||||
lstPart, err := c.CopyObjectPart(bucketName, objectName, destBucketName, destObjectName, uploadID, 3, 0, 1, nil)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
|
||||
// Complete the multipart upload
|
||||
err = c.CompleteMultipartUpload(destBucketName, destObjectName, uploadID, []CompletePart{fstPart, sndPart, lstPart})
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
|
||||
// Stat the object and check its length matches
|
||||
objInfo, err = c.StatObject(destBucketName, destObjectName, StatObjectOptions{})
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
|
||||
if objInfo.Size != (5*1024*1024)*2+1 {
|
||||
t.Fatal("Destination object has incorrect size!")
|
||||
}
|
||||
|
||||
// Now we read the data back
|
||||
getOpts := GetObjectOptions{}
|
||||
getOpts.SetRange(0, 5*1024*1024-1)
|
||||
r, _, err := c.GetObject(destBucketName, destObjectName, getOpts)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
getBuf := make([]byte, 5*1024*1024)
|
||||
_, err = io.ReadFull(r, getBuf)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
if !bytes.Equal(getBuf, buf) {
|
||||
t.Fatal("Got unexpected data in first 5MB")
|
||||
}
|
||||
|
||||
getOpts.SetRange(5*1024*1024, 0)
|
||||
r, _, err = c.GetObject(destBucketName, destObjectName, getOpts)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
getBuf = make([]byte, 5*1024*1024+1)
|
||||
_, err = io.ReadFull(r, getBuf)
|
||||
if err != nil {
|
||||
t.Fatal("Error:", err, destBucketName, destObjectName)
|
||||
}
|
||||
if !bytes.Equal(getBuf[:5*1024*1024], buf) {
|
||||
t.Fatal("Got unexpected data in second 5MB")
|
||||
}
|
||||
if getBuf[5*1024*1024] != buf[0] {
|
||||
t.Fatal("Got unexpected data in last byte of copied object!")
|
||||
}
|
||||
|
||||
if err := c.RemoveObject(destBucketName, destObjectName); err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
|
||||
if err := c.RemoveObject(bucketName, objectName); err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
|
||||
if err := c.RemoveBucket(bucketName); err != nil {
|
||||
t.Fatal("Error: ", err)
|
||||
}
|
||||
|
||||
// Do not need to remove destBucketName its same as bucketName.
|
||||
}
|
||||
|
||||
// Test Core PutObject.
|
||||
func TestCorePutObject(t *testing.T) {
|
||||
if testing.Short() {
|
||||
|
|
2
vendor/github.com/minio/minio-go/docs/API.md
generated
vendored
2
vendor/github.com/minio/minio-go/docs/API.md
generated
vendored
|
@ -575,7 +575,7 @@ __minio.PutObjectOptions__
|
|||
| `opts.ContentDisposition` | _string_ | Content disposition of object, "inline" |
|
||||
| `opts.CacheControl` | _string_ | Used to specify directives for caching mechanisms in both requests and responses e.g "max-age=600"|
|
||||
| `opts.EncryptMaterials` | _encrypt.Materials_ | Interface provided by `encrypt` package to encrypt a stream of data (For more information see https://godoc.org/github.com/minio/minio-go) |
|
||||
|
||||
| `opts.StorageClass` | _string_ | Specify storage class for the object. Supported values for Minio server are `REDUCED_REDUNDANCY` and `STANDARD` |
|
||||
|
||||
__Example__
|
||||
|
||||
|
|
1820
vendor/github.com/minio/minio-go/docs/zh_CN/API.md
generated
vendored
Normal file
1820
vendor/github.com/minio/minio-go/docs/zh_CN/API.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
22
vendor/github.com/minio/minio-go/docs/zh_CN/CONTRIBUTING.md
generated
vendored
Normal file
22
vendor/github.com/minio/minio-go/docs/zh_CN/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
### 开发者指南
|
||||
|
||||
``minio-go``欢迎你的贡献。为了让大家配合更加默契,我们做出如下约定:
|
||||
|
||||
* fork项目并修改,我们鼓励大家使用pull requests进行代码相关的讨论。
|
||||
- Fork项目
|
||||
- 创建你的特性分支 (git checkout -b my-new-feature)
|
||||
- Commit你的修改(git commit -am 'Add some feature')
|
||||
- Push到远程分支(git push origin my-new-feature)
|
||||
- 创建一个Pull Request
|
||||
|
||||
* 当你准备创建pull request时,请确保:
|
||||
- 写单元测试,如果你有什么疑问,请在pull request中提出来。
|
||||
- 运行`go fmt`
|
||||
- 将你的多个提交合并成一个提交: `git rebase -i`。你可以强制update你的pull request。
|
||||
- 确保`go test -race ./...`和`go build`完成。
|
||||
注意:go test会进行功能测试,这需要你有一个AWS S3账号。将账户信息设为``ACCESS_KEY``和``SECRET_KEY``环境变量。如果想运行简版测试,请使用``go test -short -race ./...``。
|
||||
|
||||
* 请阅读 [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments)
|
||||
- `minio-go`项目严格符合Golang风格
|
||||
- 如果您看到代码有问题,请随时发一个pull request
|
2170
vendor/github.com/minio/minio-go/functional_tests.go
generated
vendored
2170
vendor/github.com/minio/minio-go/functional_tests.go
generated
vendored
File diff suppressed because it is too large
Load diff
32
vendor/github.com/minio/minio-go/pkg/credentials/chain.go
generated
vendored
32
vendor/github.com/minio/minio-go/pkg/credentials/chain.go
generated
vendored
|
@ -17,8 +17,6 @@
|
|||
|
||||
package credentials
|
||||
|
||||
import "fmt"
|
||||
|
||||
// A Chain will search for a provider which returns credentials
|
||||
// and cache that provider until Retrieve is called again.
|
||||
//
|
||||
|
@ -27,11 +25,11 @@ import "fmt"
|
|||
// Providers in the list.
|
||||
//
|
||||
// If none of the Providers retrieve valid credentials Value, ChainProvider's
|
||||
// Retrieve() will return the error, collecting all errors from all providers.
|
||||
// Retrieve() will return the no credentials value.
|
||||
//
|
||||
// If a Provider is found which returns valid credentials Value ChainProvider
|
||||
// will cache that Provider for all calls to IsExpired(), until Retrieve is
|
||||
// called again.
|
||||
// called again after IsExpired() is true.
|
||||
//
|
||||
// creds := credentials.NewChainCredentials(
|
||||
// []credentials.Provider{
|
||||
|
@ -58,28 +56,30 @@ func NewChainCredentials(providers []Provider) *Credentials {
|
|||
})
|
||||
}
|
||||
|
||||
// Retrieve returns the credentials value or error if no provider returned
|
||||
// without error.
|
||||
// Retrieve returns the credentials value, returns no credentials(anonymous)
|
||||
// if no credentials provider returned any value.
|
||||
//
|
||||
// If a provider is found it will be cached and any calls to IsExpired()
|
||||
// will return the expired state of the cached provider.
|
||||
// If a provider is found with credentials, it will be cached and any calls
|
||||
// to IsExpired() will return the expired state of the cached provider.
|
||||
func (c *Chain) Retrieve() (Value, error) {
|
||||
var errs []error
|
||||
for _, p := range c.Providers {
|
||||
creds, err := p.Retrieve()
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
creds, _ := p.Retrieve()
|
||||
// Always prioritize non-anonymous providers, if any.
|
||||
if creds.AccessKeyID == "" && creds.SecretAccessKey == "" {
|
||||
continue
|
||||
} // Success.
|
||||
}
|
||||
c.curr = p
|
||||
return creds, nil
|
||||
}
|
||||
c.curr = nil
|
||||
return Value{}, fmt.Errorf("No valid providers found %v", errs)
|
||||
// At this point we have exhausted all the providers and
|
||||
// are left without any credentials return anonymous.
|
||||
return Value{
|
||||
SignerType: SignatureAnonymous,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsExpired will returned the expired state of the currently cached provider
|
||||
// if there is one. If there is no current provider, true will be returned.
|
||||
// if there is one. If there is no current provider, true will be returned.
|
||||
func (c *Chain) IsExpired() bool {
|
||||
if c.curr != nil {
|
||||
return c.curr.IsExpired()
|
||||
|
|
9
vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go
generated
vendored
9
vendor/github.com/minio/minio-go/pkg/credentials/chain_test.go
generated
vendored
|
@ -76,7 +76,14 @@ func TestChainGet(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestChainIsExpired(t *testing.T) {
|
||||
credProvider := &credProvider{expired: true}
|
||||
credProvider := &credProvider{
|
||||
creds: Value{
|
||||
AccessKeyID: "UXHW",
|
||||
SecretAccessKey: "MYSECRET",
|
||||
SessionToken: "",
|
||||
},
|
||||
expired: true,
|
||||
}
|
||||
p := &Chain{
|
||||
Providers: []Provider{
|
||||
credProvider,
|
||||
|
|
2
vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go
generated
vendored
2
vendor/github.com/minio/minio-go/pkg/credentials/file_aws_credentials.go
generated
vendored
|
@ -22,7 +22,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/go-ini/ini"
|
||||
homedir "github.com/minio/go-homedir"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// A FileAWSCredentials retrieves credentials from the current user's home
|
||||
|
|
2
vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go
generated
vendored
2
vendor/github.com/minio/minio-go/pkg/credentials/file_minio_client.go
generated
vendored
|
@ -24,7 +24,7 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
homedir "github.com/minio/go-homedir"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// A FileMinioClient retrieves credentials from the current user's home
|
||||
|
|
4
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-streaming_test.go
generated
vendored
4
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-streaming_test.go
generated
vendored
|
@ -33,7 +33,7 @@ func TestGetSeedSignature(t *testing.T) {
|
|||
|
||||
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", body)
|
||||
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
||||
req.URL.Host = "s3.amazonaws.com"
|
||||
req.Host = "s3.amazonaws.com"
|
||||
|
||||
reqTime, err := time.Parse("20060102T150405Z", "20130524T000000Z")
|
||||
if err != nil {
|
||||
|
@ -69,6 +69,7 @@ func TestSetStreamingAuthorization(t *testing.T) {
|
|||
|
||||
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", nil)
|
||||
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
||||
req.Host = ""
|
||||
req.URL.Host = "s3.amazonaws.com"
|
||||
|
||||
dataLen := int64(65 * 1024)
|
||||
|
@ -93,6 +94,7 @@ func TestStreamingReader(t *testing.T) {
|
|||
req := NewRequest("PUT", "/examplebucket/chunkObject.txt", nil)
|
||||
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
||||
req.ContentLength = 65 * 1024
|
||||
req.Host = ""
|
||||
req.URL.Host = "s3.amazonaws.com"
|
||||
|
||||
baseReader := ioutil.NopCloser(bytes.NewReader(bytes.Repeat([]byte("a"), 65*1024)))
|
||||
|
|
21
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v2.go
generated
vendored
21
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v2.go
generated
vendored
|
@ -40,22 +40,23 @@ const (
|
|||
)
|
||||
|
||||
// Encode input URL path to URL encoded path.
|
||||
func encodeURL2Path(u *url.URL) (path string) {
|
||||
func encodeURL2Path(req *http.Request) (path string) {
|
||||
reqHost := getHostAddr(req)
|
||||
// Encode URL path.
|
||||
if isS3, _ := filepath.Match("*.s3*.amazonaws.com", u.Host); isS3 {
|
||||
bucketName := u.Host[:strings.LastIndex(u.Host, ".s3")]
|
||||
if isS3, _ := filepath.Match("*.s3*.amazonaws.com", reqHost); isS3 {
|
||||
bucketName := reqHost[:strings.LastIndex(reqHost, ".s3")]
|
||||
path = "/" + bucketName
|
||||
path += u.Path
|
||||
path += req.URL.Path
|
||||
path = s3utils.EncodePath(path)
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(u.Host, ".storage.googleapis.com") {
|
||||
path = "/" + strings.TrimSuffix(u.Host, ".storage.googleapis.com")
|
||||
path += u.Path
|
||||
if strings.HasSuffix(reqHost, ".storage.googleapis.com") {
|
||||
path = "/" + strings.TrimSuffix(reqHost, ".storage.googleapis.com")
|
||||
path += req.URL.Path
|
||||
path = s3utils.EncodePath(path)
|
||||
return
|
||||
}
|
||||
path = s3utils.EncodePath(u.Path)
|
||||
path = s3utils.EncodePath(req.URL.Path)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -86,7 +87,7 @@ func PreSignV2(req http.Request, accessKeyID, secretAccessKey string, expires in
|
|||
|
||||
query := req.URL.Query()
|
||||
// Handle specially for Google Cloud Storage.
|
||||
if strings.Contains(req.URL.Host, ".storage.googleapis.com") {
|
||||
if strings.Contains(getHostAddr(&req), ".storage.googleapis.com") {
|
||||
query.Set("GoogleAccessId", accessKeyID)
|
||||
} else {
|
||||
query.Set("AWSAccessKeyId", accessKeyID)
|
||||
|
@ -291,7 +292,7 @@ func writeCanonicalizedResource(buf *bytes.Buffer, req http.Request) {
|
|||
// Save request URL.
|
||||
requestURL := req.URL
|
||||
// Get encoded URL path.
|
||||
buf.WriteString(encodeURL2Path(requestURL))
|
||||
buf.WriteString(encodeURL2Path(&req))
|
||||
if requestURL.RawQuery != "" {
|
||||
var n int
|
||||
vals, _ := url.ParseQuery(requestURL.RawQuery)
|
||||
|
|
2
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v4.go
generated
vendored
2
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v4.go
generated
vendored
|
@ -144,7 +144,7 @@ func getCanonicalHeaders(req http.Request, ignoredHeaders map[string]bool) strin
|
|||
buf.WriteByte(':')
|
||||
switch {
|
||||
case k == "host":
|
||||
buf.WriteString(req.URL.Host)
|
||||
buf.WriteString(getHostAddr(&req))
|
||||
fallthrough
|
||||
default:
|
||||
for idx, v := range vals[k] {
|
||||
|
|
50
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v4_test.go
generated
vendored
Normal file
50
vendor/github.com/minio/minio-go/pkg/s3signer/request-signature-v4_test.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Minio Go Library for Amazon S3 Compatible Cloud Storage
|
||||
* Copyright 2015-2017 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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 s3signer
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRequestHost(t *testing.T) {
|
||||
req, _ := buildRequest("dynamodb", "us-east-1", "{}")
|
||||
req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a"
|
||||
req.Host = "myhost"
|
||||
canonicalHeaders := getCanonicalHeaders(*req, v4IgnoredHeaders)
|
||||
|
||||
if !strings.Contains(canonicalHeaders, "host:"+req.Host) {
|
||||
t.Errorf("canonical host header invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func buildRequest(serviceName, region, body string) (*http.Request, io.ReadSeeker) {
|
||||
endpoint := "https://" + serviceName + "." + region + ".amazonaws.com"
|
||||
reader := strings.NewReader(body)
|
||||
req, _ := http.NewRequest("POST", endpoint, reader)
|
||||
req.URL.Opaque = "//example.org/bucket/key-._~,!@#$%^&*()"
|
||||
req.Header.Add("X-Amz-Target", "prefix.Operation")
|
||||
req.Header.Add("Content-Type", "application/x-amz-json-1.0")
|
||||
req.Header.Add("Content-Length", string(len(body)))
|
||||
req.Header.Add("X-Amz-Meta-Other-Header", "some-value=!@#$%^&* (+)")
|
||||
req.Header.Add("X-Amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
|
||||
req.Header.Add("X-amz-Meta-Other-Header_With_Underscore", "some-value=!@#$%^&* (+)")
|
||||
return req, reader
|
||||
}
|
9
vendor/github.com/minio/minio-go/pkg/s3signer/utils.go
generated
vendored
9
vendor/github.com/minio/minio-go/pkg/s3signer/utils.go
generated
vendored
|
@ -20,6 +20,7 @@ package s3signer
|
|||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// unsignedPayload - value to be set to X-Amz-Content-Sha256 header when
|
||||
|
@ -38,3 +39,11 @@ func sumHMAC(key []byte, data []byte) []byte {
|
|||
hash.Write(data)
|
||||
return hash.Sum(nil)
|
||||
}
|
||||
|
||||
// getHostAddr returns host header if available, otherwise returns host from URL
|
||||
func getHostAddr(req *http.Request) string {
|
||||
if req.Host != "" {
|
||||
return req.Host
|
||||
}
|
||||
return req.URL.Host
|
||||
}
|
||||
|
|
3
vendor/github.com/minio/minio-go/pkg/s3signer/utils_test.go
generated
vendored
3
vendor/github.com/minio/minio-go/pkg/s3signer/utils_test.go
generated
vendored
|
@ -19,6 +19,7 @@ package s3signer
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
@ -66,7 +67,7 @@ func TestEncodeURL2Path(t *testing.T) {
|
|||
t.Fatal("Error:", err)
|
||||
}
|
||||
urlPath := "/" + bucketName + "/" + o.encodedObjName
|
||||
if urlPath != encodeURL2Path(u) {
|
||||
if urlPath != encodeURL2Path(&http.Request{URL: u}) {
|
||||
t.Fatal("Error")
|
||||
}
|
||||
}
|
||||
|
|
65
vendor/github.com/minio/minio-go/pkg/s3utils/utils.go
generated
vendored
65
vendor/github.com/minio/minio-go/pkg/s3utils/utils.go
generated
vendored
|
@ -81,18 +81,56 @@ func IsVirtualHostSupported(endpointURL url.URL, bucketName string) bool {
|
|||
return IsAmazonEndpoint(endpointURL) || IsGoogleEndpoint(endpointURL)
|
||||
}
|
||||
|
||||
// AmazonS3Host - regular expression used to determine if an arg is s3 host.
|
||||
var AmazonS3Host = regexp.MustCompile("^s3[.-]?(.*?)\\.amazonaws\\.com$")
|
||||
// Refer for region styles - https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
|
||||
|
||||
// amazonS3HostHyphen - regular expression used to determine if an arg is s3 host in hyphenated style.
|
||||
var amazonS3HostHyphen = regexp.MustCompile(`^s3-(.*?)\.amazonaws\.com$`)
|
||||
|
||||
// amazonS3HostDualStack - regular expression used to determine if an arg is s3 host dualstack.
|
||||
var amazonS3HostDualStack = regexp.MustCompile(`^s3\.dualstack\.(.*?)\.amazonaws\.com$`)
|
||||
|
||||
// amazonS3HostDot - regular expression used to determine if an arg is s3 host in . style.
|
||||
var amazonS3HostDot = regexp.MustCompile(`^s3\.(.*?)\.amazonaws\.com$`)
|
||||
|
||||
// amazonS3ChinaHost - regular expression used to determine if the arg is s3 china host.
|
||||
var amazonS3ChinaHost = regexp.MustCompile(`^s3\.(cn.*?)\.amazonaws\.com\.cn$`)
|
||||
|
||||
// GetRegionFromURL - returns a region from url host.
|
||||
func GetRegionFromURL(endpointURL url.URL) string {
|
||||
if endpointURL == sentinelURL {
|
||||
return ""
|
||||
}
|
||||
if endpointURL.Host == "s3-external-1.amazonaws.com" {
|
||||
return ""
|
||||
}
|
||||
if IsAmazonGovCloudEndpoint(endpointURL) {
|
||||
return "us-gov-west-1"
|
||||
}
|
||||
parts := amazonS3HostDualStack.FindStringSubmatch(endpointURL.Host)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
parts = amazonS3HostHyphen.FindStringSubmatch(endpointURL.Host)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
parts = amazonS3ChinaHost.FindStringSubmatch(endpointURL.Host)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
parts = amazonS3HostDot.FindStringSubmatch(endpointURL.Host)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsAmazonEndpoint - Match if it is exactly Amazon S3 endpoint.
|
||||
func IsAmazonEndpoint(endpointURL url.URL) bool {
|
||||
if IsAmazonChinaEndpoint(endpointURL) {
|
||||
if endpointURL.Host == "s3-external-1.amazonaws.com" || endpointURL.Host == "s3.amazonaws.com" {
|
||||
return true
|
||||
}
|
||||
if IsAmazonGovCloudEndpoint(endpointURL) {
|
||||
return true
|
||||
}
|
||||
return AmazonS3Host.MatchString(endpointURL.Host)
|
||||
return GetRegionFromURL(endpointURL) != ""
|
||||
}
|
||||
|
||||
// IsAmazonGovCloudEndpoint - Match if it is exactly Amazon S3 GovCloud endpoint.
|
||||
|
@ -112,19 +150,6 @@ func IsAmazonFIPSGovCloudEndpoint(endpointURL url.URL) bool {
|
|||
return endpointURL.Host == "s3-fips-us-gov-west-1.amazonaws.com"
|
||||
}
|
||||
|
||||
// IsAmazonChinaEndpoint - Match if it is exactly Amazon S3 China endpoint.
|
||||
// Customers who wish to use the new Beijing Region are required
|
||||
// to sign up for a separate set of account credentials unique to
|
||||
// the China (Beijing) Region. Customers with existing AWS credentials
|
||||
// will not be able to access resources in the new Region, and vice versa.
|
||||
// For more info https://aws.amazon.com/about-aws/whats-new/2013/12/18/announcing-the-aws-china-beijing-region/
|
||||
func IsAmazonChinaEndpoint(endpointURL url.URL) bool {
|
||||
if endpointURL == sentinelURL {
|
||||
return false
|
||||
}
|
||||
return endpointURL.Host == "s3.cn-north-1.amazonaws.com.cn"
|
||||
}
|
||||
|
||||
// IsGoogleEndpoint - Match if it is exactly Google cloud storage endpoint.
|
||||
func IsGoogleEndpoint(endpointURL url.URL) bool {
|
||||
if endpointURL == sentinelURL {
|
||||
|
|
104
vendor/github.com/minio/minio-go/pkg/s3utils/utils_test.go
generated
vendored
104
vendor/github.com/minio/minio-go/pkg/s3utils/utils_test.go
generated
vendored
|
@ -23,6 +23,66 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
// Tests get region from host URL.
|
||||
func TestGetRegionFromURL(t *testing.T) {
|
||||
testCases := []struct {
|
||||
u url.URL
|
||||
expectedRegion string
|
||||
}{
|
||||
{
|
||||
u: url.URL{Host: "storage.googleapis.com"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.cn-north-1.amazonaws.com.cn"},
|
||||
expectedRegion: "cn-north-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.cn-northwest-1.amazonaws.com.cn"},
|
||||
expectedRegion: "cn-northwest-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-fips-us-gov-west-1.amazonaws.com"},
|
||||
expectedRegion: "us-gov-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-us-gov-west-1.amazonaws.com"},
|
||||
expectedRegion: "us-gov-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "192.168.1.1"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-eu-west-1.amazonaws.com"},
|
||||
expectedRegion: "eu-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.eu-west-1.amazonaws.com"},
|
||||
expectedRegion: "eu-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.dualstack.eu-west-1.amazonaws.com"},
|
||||
expectedRegion: "eu-west-1",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3.amazonaws.com"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
{
|
||||
u: url.URL{Host: "s3-external-1.amazonaws.com"},
|
||||
expectedRegion: "",
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
region := GetRegionFromURL(testCase.u)
|
||||
if testCase.expectedRegion != region {
|
||||
t.Errorf("Test %d: Expected region %s, got %s", i+1, testCase.expectedRegion, region)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for 'isValidDomain(host string) bool'.
|
||||
func TestIsValidDomain(t *testing.T) {
|
||||
testCases := []struct {
|
||||
|
@ -33,6 +93,7 @@ func TestIsValidDomain(t *testing.T) {
|
|||
}{
|
||||
{"s3.amazonaws.com", true},
|
||||
{"s3.cn-north-1.amazonaws.com.cn", true},
|
||||
{"s3.cn-northwest-1.amazonaws.com.cn", true},
|
||||
{"s3.amazonaws.com_", false},
|
||||
{"%$$$", false},
|
||||
{"s3.amz.test.com", true},
|
||||
|
@ -120,9 +181,17 @@ func TestIsAmazonEndpoint(t *testing.T) {
|
|||
{"https://amazons3.amazonaws.com", false},
|
||||
{"-192.168.1.1", false},
|
||||
{"260.192.1.1", false},
|
||||
{"https://s3-.amazonaws.com", false},
|
||||
{"https://s3..amazonaws.com", false},
|
||||
{"https://s3.dualstack.us-west-1.amazonaws.com.cn", false},
|
||||
{"https://s3..us-west-1.amazonaws.com.cn", false},
|
||||
// valid inputs.
|
||||
{"https://s3.amazonaws.com", true},
|
||||
{"https://s3-external-1.amazonaws.com", true},
|
||||
{"https://s3.cn-north-1.amazonaws.com.cn", true},
|
||||
{"https://s3-us-west-1.amazonaws.com", true},
|
||||
{"https://s3.us-west-1.amazonaws.com", true},
|
||||
{"https://s3.dualstack.us-west-1.amazonaws.com", true},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -138,41 +207,6 @@ func TestIsAmazonEndpoint(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
// Tests validate Amazon S3 China endpoint validator.
|
||||
func TestIsAmazonChinaEndpoint(t *testing.T) {
|
||||
testCases := []struct {
|
||||
url string
|
||||
// Expected result.
|
||||
result bool
|
||||
}{
|
||||
{"https://192.168.1.1", false},
|
||||
{"192.168.1.1", false},
|
||||
{"http://storage.googleapis.com", false},
|
||||
{"https://storage.googleapis.com", false},
|
||||
{"storage.googleapis.com", false},
|
||||
{"s3.amazonaws.com", false},
|
||||
{"https://amazons3.amazonaws.com", false},
|
||||
{"-192.168.1.1", false},
|
||||
{"260.192.1.1", false},
|
||||
// s3.amazonaws.com is not a valid Amazon S3 China end point.
|
||||
{"https://s3.amazonaws.com", false},
|
||||
// valid input.
|
||||
{"https://s3.cn-north-1.amazonaws.com.cn", true},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
u, err := url.Parse(testCase.url)
|
||||
if err != nil {
|
||||
t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err)
|
||||
}
|
||||
result := IsAmazonChinaEndpoint(*u)
|
||||
if testCase.result != result {
|
||||
t.Errorf("Test %d: Expected isAmazonEndpoint to be '%v' for input \"%s\", but found it to be '%v' instead", i+1, testCase.result, testCase.url, result)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Tests validate Google Cloud end point validator.
|
||||
func TestIsGoogleEndpoint(t *testing.T) {
|
||||
testCases := []struct {
|
||||
|
|
2
vendor/github.com/minio/minio-go/retry.go
generated
vendored
2
vendor/github.com/minio/minio-go/retry.go
generated
vendored
|
@ -26,7 +26,7 @@ import (
|
|||
)
|
||||
|
||||
// MaxRetry is the maximum number of retries before stopping.
|
||||
var MaxRetry = 5
|
||||
var MaxRetry = 10
|
||||
|
||||
// MaxJitter will randomize over the full exponential backoff time
|
||||
const MaxJitter = 1.0
|
||||
|
|
5
vendor/github.com/minio/minio-go/s3-endpoints.go
generated
vendored
5
vendor/github.com/minio/minio-go/s3-endpoints.go
generated
vendored
|
@ -18,15 +18,15 @@
|
|||
package minio
|
||||
|
||||
// awsS3EndpointMap Amazon S3 endpoint map.
|
||||
// "cn-north-1" adds support for AWS China.
|
||||
var awsS3EndpointMap = map[string]string{
|
||||
"us-east-1": "s3.amazonaws.com",
|
||||
"us-east-2": "s3-us-east-2.amazonaws.com",
|
||||
"us-west-2": "s3-us-west-2.amazonaws.com",
|
||||
"us-west-1": "s3-us-west-1.amazonaws.com",
|
||||
"ca-central-1": "s3.ca-central-1.amazonaws.com",
|
||||
"ca-central-1": "s3-ca-central-1.amazonaws.com",
|
||||
"eu-west-1": "s3-eu-west-1.amazonaws.com",
|
||||
"eu-west-2": "s3-eu-west-2.amazonaws.com",
|
||||
"eu-west-3": "s3-eu-west-3.amazonaws.com",
|
||||
"eu-central-1": "s3-eu-central-1.amazonaws.com",
|
||||
"ap-south-1": "s3-ap-south-1.amazonaws.com",
|
||||
"ap-southeast-1": "s3-ap-southeast-1.amazonaws.com",
|
||||
|
@ -36,6 +36,7 @@ var awsS3EndpointMap = map[string]string{
|
|||
"sa-east-1": "s3-sa-east-1.amazonaws.com",
|
||||
"us-gov-west-1": "s3-us-gov-west-1.amazonaws.com",
|
||||
"cn-north-1": "s3.cn-north-1.amazonaws.com.cn",
|
||||
"cn-northwest-1": "s3.cn-northwest-1.amazonaws.com.cn",
|
||||
}
|
||||
|
||||
// getS3Endpoint get Amazon S3 endpoint based on the bucket location.
|
||||
|
|
16
vendor/github.com/minio/minio-go/utils.go
generated
vendored
16
vendor/github.com/minio/minio-go/utils.go
generated
vendored
|
@ -209,14 +209,11 @@ func getDefaultLocation(u url.URL, regionOverride string) (location string) {
|
|||
if regionOverride != "" {
|
||||
return regionOverride
|
||||
}
|
||||
if s3utils.IsAmazonChinaEndpoint(u) {
|
||||
return "cn-north-1"
|
||||
region := s3utils.GetRegionFromURL(u)
|
||||
if region == "" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
if s3utils.IsAmazonGovCloudEndpoint(u) {
|
||||
return "us-gov-west-1"
|
||||
}
|
||||
// Default to location to 'us-east-1'.
|
||||
return "us-east-1"
|
||||
return region
|
||||
}
|
||||
|
||||
var supportedHeaders = []string{
|
||||
|
@ -234,6 +231,11 @@ var cseHeaders = []string{
|
|||
"X-Amz-Matdesc",
|
||||
}
|
||||
|
||||
// isStorageClassHeader returns true if the header is a supported storage class header
|
||||
func isStorageClassHeader(headerKey string) bool {
|
||||
return strings.ToLower(amzStorageClass) == strings.ToLower(headerKey)
|
||||
}
|
||||
|
||||
// isStandardHeader returns true if header is a supported header and not a custom header
|
||||
func isStandardHeader(headerKey string) bool {
|
||||
key := strings.ToLower(headerKey)
|
||||
|
|
10
vendor/github.com/minio/minio-go/utils_test.go
generated
vendored
10
vendor/github.com/minio/minio-go/utils_test.go
generated
vendored
|
@ -82,8 +82,10 @@ func TestGetEndpointURL(t *testing.T) {
|
|||
}{
|
||||
{"s3.amazonaws.com", true, "https://s3.amazonaws.com", nil, true},
|
||||
{"s3.cn-north-1.amazonaws.com.cn", true, "https://s3.cn-north-1.amazonaws.com.cn", nil, true},
|
||||
{"s3.cn-northwest-1.amazonaws.com.cn", true, "https://s3.cn-northwest-1.amazonaws.com.cn", nil, true},
|
||||
{"s3.amazonaws.com", false, "http://s3.amazonaws.com", nil, true},
|
||||
{"s3.cn-north-1.amazonaws.com.cn", false, "http://s3.cn-north-1.amazonaws.com.cn", nil, true},
|
||||
{"s3.cn-northwest-1.amazonaws.com.cn", false, "http://s3.cn-northwest-1.amazonaws.com.cn", nil, true},
|
||||
{"192.168.1.1:9000", false, "http://192.168.1.1:9000", nil, true},
|
||||
{"192.168.1.1:9000", true, "https://192.168.1.1:9000", nil, true},
|
||||
{"s3.amazonaws.com:443", true, "https://s3.amazonaws.com:443", nil, true},
|
||||
|
@ -200,7 +202,13 @@ func TestDefaultBucketLocation(t *testing.T) {
|
|||
regionOverride: "",
|
||||
expectedLocation: "cn-north-1",
|
||||
},
|
||||
// No region provided, no standard region strings provided as well. - Test 5.
|
||||
// China region should be honored, region override not provided. - Test 5.
|
||||
{
|
||||
endpointURL: url.URL{Host: "s3.cn-northwest-1.amazonaws.com.cn"},
|
||||
regionOverride: "",
|
||||
expectedLocation: "cn-northwest-1",
|
||||
},
|
||||
// No region provided, no standard region strings provided as well. - Test 6.
|
||||
{
|
||||
endpointURL: url.URL{Host: "s3.amazonaws.com"},
|
||||
regionOverride: "",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue