1
0
mirror of https://github.com/minio/mc.git synced 2025-11-13 12:22:45 +03:00
Files
mc/pkg/client/s3/client.go

179 lines
4.8 KiB
Go

// Original license //
// ---------------- //
/*
Copyright 2011 Google 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.
*/
// All other modifications and improvements //
// ---------------------------------------- //
/*
* Minimalist Object Storage, (C) 2015 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 s3
import (
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"
"encoding/xml"
"github.com/minio-io/mc/pkg/client"
"github.com/minio-io/minio/pkg/iodine"
)
type listBucketResults struct {
Contents []*client.Item
IsTruncated bool
MaxKeys int
Name string // bucket name
Marker string
Delimiter string
Prefix string
CommonPrefixes []*client.Prefix
}
// Meta holds Amazon S3 client credentials and flags.
type Meta struct {
*Auth
Transport http.RoundTripper // or nil for the default behavior
}
// Auth - see http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
type Auth struct {
AccessKeyID string
SecretAccessKey string
// Used for SSL transport layer
CertPEM string
KeyPEM string
}
// TLSConfig - TLS cert and key configuration
type TLSConfig struct {
CertPEMBlock []byte
KeyPEMBlock []byte
}
type s3Client struct {
*Meta
// Supports URL in following formats
// - http://<ipaddress>/<bucketname>/<object>
// - http://<bucketname>.<domain>/<object>
*url.URL
}
// GetNewClient returns an initialized s3Client structure.
// if debug use a internal trace transport
func GetNewClient(hostURL string, auth *Auth, debug bool) client.Client {
u, err := url.Parse(hostURL)
if err != nil {
return nil
}
var traceTransport RoundTripTrace
var transport http.RoundTripper
if debug {
traceTransport = GetNewTraceTransport(NewTrace(false, true, nil), http.DefaultTransport)
transport = GetNewTraceTransport(s3Verify{}, traceTransport)
} else {
transport = http.DefaultTransport
}
s3c := &s3Client{
&Meta{
Auth: auth,
Transport: transport,
}, u,
}
return s3c
}
// bucketURL constructs a URL (with a trailing slash) for a given
// bucket. URL is appropriately encoded based on the host's object
// storage implementation.
func (c *s3Client) bucketURL(bucket string) string {
var url string
// TODO: Bucket names can contain ".". This second check should be removed.
// when minio server supports buckets with "."
if client.IsValidBucketName(bucket) && !strings.Contains(bucket, ".") {
// if localhost use PathStyle
if strings.Contains(c.Host, "localhost") || strings.Contains(c.Host, "127.0.0.1") {
return fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket)
}
// Verify if its ip address, use PathStyle
host, _, _ := net.SplitHostPort(c.Host)
if net.ParseIP(host) != nil {
return fmt.Sprintf("%s://%s/%s", c.Scheme, c.Host, bucket)
}
// For DNS hostname or amazonaws.com use subdomain style
url = fmt.Sprintf("%s://%s.%s/", c.Scheme, bucket, c.Host)
}
return url
}
// keyURL constructs a URL using bucket and object key
func (c *s3Client) keyURL(bucket, key string) string {
url := c.bucketURL(bucket)
if strings.Contains(c.Host, "localhost") || strings.Contains(c.Host, "127.0.0.1") {
return url + "/" + key
}
host, _, _ := net.SplitHostPort(c.Host)
if net.ParseIP(host) != nil {
return url + "/" + key
}
return url + key
}
func newReq(url string) *http.Request {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
// TODO: never exit from inside a package. Let the
// caller handle errors gracefully.
panic(fmt.Sprintf("s3 client; invalid URL: %v", err))
}
req.Header.Set("User-Agent", "Minio s3Client")
return req
}
func listAllMyBuckets(r io.Reader) ([]*client.Bucket, error) {
type allMyBuckets struct {
Buckets struct {
Bucket []*client.Bucket
}
}
var res allMyBuckets
if err := xml.NewDecoder(r).Decode(&res); err != nil {
return nil, iodine.New(err, nil)
}
return res.Buckets.Bucket, nil
}