summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/minio-go/utils.go')
-rw-r--r--vendor/github.com/minio/minio-go/utils.go226
1 files changed, 35 insertions, 191 deletions
diff --git a/vendor/github.com/minio/minio-go/utils.go b/vendor/github.com/minio/minio-go/utils.go
index 2208d3603..93cd1712f 100644
--- a/vendor/github.com/minio/minio-go/utils.go
+++ b/vendor/github.com/minio/minio-go/utils.go
@@ -17,11 +17,8 @@
package minio
import (
- "bytes"
- "crypto/hmac"
"crypto/md5"
"crypto/sha256"
- "encoding/hex"
"encoding/xml"
"io"
"io/ioutil"
@@ -29,10 +26,11 @@ import (
"net/http"
"net/url"
"regexp"
- "sort"
"strings"
"time"
"unicode/utf8"
+
+ "github.com/minio/minio-go/pkg/s3utils"
)
// xmlDecoder provide decoded value in xml.
@@ -55,13 +53,6 @@ func sumMD5(data []byte) []byte {
return hash.Sum(nil)
}
-// sumHMAC calculate hmac between two input byte array.
-func sumHMAC(key []byte, data []byte) []byte {
- hash := hmac.New(sha256.New, key)
- hash.Write(data)
- return hash.Sum(nil)
-}
-
// getEndpointURL - construct a new endpoint.
func getEndpointURL(endpoint string, secure bool) (*url.URL, error) {
if strings.Contains(endpoint, ":") {
@@ -69,12 +60,12 @@ func getEndpointURL(endpoint string, secure bool) (*url.URL, error) {
if err != nil {
return nil, err
}
- if !isValidIP(host) && !isValidDomain(host) {
+ if !s3utils.IsValidIP(host) && !s3utils.IsValidDomain(host) {
msg := "Endpoint: " + endpoint + " does not follow ip address or domain name standards."
return nil, ErrInvalidArgument(msg)
}
} else {
- if !isValidIP(endpoint) && !isValidDomain(endpoint) {
+ if !s3utils.IsValidIP(endpoint) && !s3utils.IsValidDomain(endpoint) {
msg := "Endpoint: " + endpoint + " does not follow ip address or domain name standards."
return nil, ErrInvalidArgument(msg)
}
@@ -93,45 +84,12 @@ func getEndpointURL(endpoint string, secure bool) (*url.URL, error) {
}
// Validate incoming endpoint URL.
- if err := isValidEndpointURL(endpointURL.String()); err != nil {
+ if err := isValidEndpointURL(*endpointURL); err != nil {
return nil, err
}
return endpointURL, nil
}
-// isValidDomain validates if input string is a valid domain name.
-func isValidDomain(host string) bool {
- // See RFC 1035, RFC 3696.
- host = strings.TrimSpace(host)
- if len(host) == 0 || len(host) > 255 {
- return false
- }
- // host cannot start or end with "-"
- if host[len(host)-1:] == "-" || host[:1] == "-" {
- return false
- }
- // host cannot start or end with "_"
- if host[len(host)-1:] == "_" || host[:1] == "_" {
- return false
- }
- // host cannot start or end with a "."
- if host[len(host)-1:] == "." || host[:1] == "." {
- return false
- }
- // All non alphanumeric characters are invalid.
- if strings.ContainsAny(host, "`~!@#$%^&*()+={}[]|\\\"';:><?/") {
- return false
- }
- // No need to regexp match, since the list is non-exhaustive.
- // We let it valid and fail later.
- return true
-}
-
-// isValidIP parses input string for ip address validity.
-func isValidIP(ip string) bool {
- return net.ParseIP(ip) != nil
-}
-
// closeResponse close non nil response with any response Body.
// convenient wrapper to drain any remaining data on response body.
//
@@ -152,92 +110,24 @@ func closeResponse(resp *http.Response) {
}
}
-// isVirtualHostSupported - verifies if bucketName can be part of
-// virtual host. Currently only Amazon S3 and Google Cloud Storage
-// would support this.
-func isVirtualHostSupported(endpointURL string, bucketName string) bool {
- url, err := url.Parse(endpointURL)
- if err != nil {
- return false
- }
- // bucketName can be valid but '.' in the hostname will fail SSL
- // certificate validation. So do not use host-style for such buckets.
- if url.Scheme == "https" && strings.Contains(bucketName, ".") {
- return false
- }
- // Return true for all other cases
- return isAmazonEndpoint(endpointURL) || isGoogleEndpoint(endpointURL)
-}
-
-// Match if it is exactly Amazon S3 endpoint.
-func isAmazonEndpoint(endpointURL string) bool {
- if isAmazonChinaEndpoint(endpointURL) {
- return true
- }
- url, err := url.Parse(endpointURL)
- if err != nil {
- return false
- }
- if url.Host == "s3.amazonaws.com" {
- return true
- }
- return false
-}
-
-// 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 string) bool {
- if endpointURL == "" {
- return false
- }
- url, err := url.Parse(endpointURL)
- if err != nil {
- return false
- }
- if url.Host == "s3.cn-north-1.amazonaws.com.cn" {
- return true
- }
- return false
-}
-
-// Match if it is exactly Google cloud storage endpoint.
-func isGoogleEndpoint(endpointURL string) bool {
- if endpointURL == "" {
- return false
- }
- url, err := url.Parse(endpointURL)
- if err != nil {
- return false
- }
- if url.Host == "storage.googleapis.com" {
- return true
- }
- return false
-}
+// Sentinel URL is the default url value which is invalid.
+var sentinelURL = url.URL{}
// Verify if input endpoint URL is valid.
-func isValidEndpointURL(endpointURL string) error {
- if endpointURL == "" {
+func isValidEndpointURL(endpointURL url.URL) error {
+ if endpointURL == sentinelURL {
return ErrInvalidArgument("Endpoint url cannot be empty.")
}
- url, err := url.Parse(endpointURL)
- if err != nil {
+ if endpointURL.Path != "/" && endpointURL.Path != "" {
return ErrInvalidArgument("Endpoint url cannot have fully qualified paths.")
}
- if url.Path != "/" && url.Path != "" {
- return ErrInvalidArgument("Endpoint url cannot have fully qualified paths.")
- }
- if strings.Contains(endpointURL, ".amazonaws.com") {
- if !isAmazonEndpoint(endpointURL) {
+ if strings.Contains(endpointURL.Host, ".amazonaws.com") {
+ if !s3utils.IsAmazonEndpoint(endpointURL) {
return ErrInvalidArgument("Amazon S3 endpoint should be 's3.amazonaws.com'.")
}
}
- if strings.Contains(endpointURL, ".googleapis.com") {
- if !isGoogleEndpoint(endpointURL) {
+ if strings.Contains(endpointURL.Host, ".googleapis.com") {
+ if !s3utils.IsGoogleEndpoint(endpointURL) {
return ErrInvalidArgument("Google Cloud Storage endpoint should be 'storage.googleapis.com'.")
}
}
@@ -260,6 +150,9 @@ func isValidExpiry(expires time.Duration) error {
// style requests instead for such buckets.
var validBucketName = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`)
+// Invalid bucket name with double dot.
+var invalidDotBucketName = regexp.MustCompile(`\.\.`)
+
// isValidBucketName - verify bucket name in accordance with
// - http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html
func isValidBucketName(bucketName string) error {
@@ -275,7 +168,7 @@ func isValidBucketName(bucketName string) error {
if bucketName[0] == '.' || bucketName[len(bucketName)-1] == '.' {
return ErrInvalidBucketName("Bucket name cannot start or end with a '.' dot.")
}
- if match, _ := regexp.MatchString("\\.\\.", bucketName); match {
+ if invalidDotBucketName.MatchString(bucketName) {
return ErrInvalidBucketName("Bucket name cannot have successive periods.")
}
if !validBucketName.MatchString(bucketName) {
@@ -310,74 +203,25 @@ func isValidObjectPrefix(objectPrefix string) error {
return nil
}
-//expects ascii encoded strings - from output of urlEncodePath
-func percentEncodeSlash(s string) string {
- return strings.Replace(s, "/", "%2F", -1)
-}
-
-// queryEncode - encodes query values in their URL encoded form. In
-// addition to the percent encoding performed by urlEncodePath() used
-// here, it also percent encodes '/' (forward slash)
-func queryEncode(v url.Values) string {
- if v == nil {
- return ""
- }
- var buf bytes.Buffer
- keys := make([]string, 0, len(v))
- for k := range v {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- vs := v[k]
- prefix := percentEncodeSlash(urlEncodePath(k)) + "="
- for _, v := range vs {
- if buf.Len() > 0 {
- buf.WriteByte('&')
- }
- buf.WriteString(prefix)
- buf.WriteString(percentEncodeSlash(urlEncodePath(v)))
- }
+// make a copy of http.Header
+func cloneHeader(h http.Header) http.Header {
+ h2 := make(http.Header, len(h))
+ for k, vv := range h {
+ vv2 := make([]string, len(vv))
+ copy(vv2, vv)
+ h2[k] = vv2
}
- return buf.String()
+ return h2
}
-// urlEncodePath encode the strings from UTF-8 byte representations to HTML hex escape sequences
-//
-// This is necessary since regular url.Parse() and url.Encode() functions do not support UTF-8
-// non english characters cannot be parsed due to the nature in which url.Encode() is written
-//
-// This function on the other hand is a direct replacement for url.Encode() technique to support
-// pretty much every UTF-8 character.
-func urlEncodePath(pathName string) string {
- // if object matches reserved string, no need to encode them
- reservedNames := regexp.MustCompile("^[a-zA-Z0-9-_.~/]+$")
- if reservedNames.MatchString(pathName) {
- return pathName
- }
- var encodedPathname string
- for _, s := range pathName {
- if 'A' <= s && s <= 'Z' || 'a' <= s && s <= 'z' || '0' <= s && s <= '9' { // §2.3 Unreserved characters (mark)
- encodedPathname = encodedPathname + string(s)
- continue
- }
- switch s {
- case '-', '_', '.', '~', '/': // §2.3 Unreserved characters (mark)
- encodedPathname = encodedPathname + string(s)
- continue
- default:
- len := utf8.RuneLen(s)
- if len < 0 {
- // if utf8 cannot convert return the same string as is
- return pathName
- }
- u := make([]byte, len)
- utf8.EncodeRune(u, s)
- for _, r := range u {
- hex := hex.EncodeToString([]byte{r})
- encodedPathname = encodedPathname + "%" + strings.ToUpper(hex)
- }
- }
+// Filter relevant response headers from
+// the HEAD, GET http response. The function takes
+// a list of headers which are filtered out and
+// returned as a new http header.
+func filterHeader(header http.Header, filterKeys []string) (filteredHeader http.Header) {
+ filteredHeader = cloneHeader(header)
+ for _, key := range filterKeys {
+ filteredHeader.Del(key)
}
- return encodedPathname
+ return filteredHeader
}