diff options
author | Christopher Speller <crspeller@gmail.com> | 2017-02-02 09:32:00 -0500 |
---|---|---|
committer | Harrison Healey <harrisonmhealey@gmail.com> | 2017-02-02 09:32:00 -0500 |
commit | 701d1ab638b23c24877fc41824add66232446676 (patch) | |
tree | ec120c88d38ac9d38d9eabdd3270b52bb6ac9d96 /vendor/github.com/minio/minio-go/api.go | |
parent | ca3211bc04f6dea34e8168217182637d1419f998 (diff) | |
download | chat-701d1ab638b23c24877fc41824add66232446676.tar.gz chat-701d1ab638b23c24877fc41824add66232446676.tar.bz2 chat-701d1ab638b23c24877fc41824add66232446676.zip |
Updating server dependancies (#5249)
Diffstat (limited to 'vendor/github.com/minio/minio-go/api.go')
-rw-r--r-- | vendor/github.com/minio/minio-go/api.go | 113 |
1 files changed, 73 insertions, 40 deletions
diff --git a/vendor/github.com/minio/minio-go/api.go b/vendor/github.com/minio/minio-go/api.go index 954927084..98829cd2c 100644 --- a/vendor/github.com/minio/minio-go/api.go +++ b/vendor/github.com/minio/minio-go/api.go @@ -33,12 +33,18 @@ import ( "strings" "sync" "time" + + "github.com/minio/minio-go/pkg/s3signer" + "github.com/minio/minio-go/pkg/s3utils" ) // Client implements Amazon S3 compatible methods. type Client struct { /// Standard options. + // Parsed endpoint url provided by the user. + endpointURL url.URL + // AccessKeyID required for authorized requests. accessKeyID string // SecretAccessKey required for authorized requests. @@ -53,7 +59,6 @@ type Client struct { appName string appVersion string } - endpointURL string // Indicate whether we are using https or not secure bool @@ -73,7 +78,7 @@ type Client struct { // Global constants. const ( libraryName = "minio-go" - libraryVersion = "2.0.2" + libraryVersion = "2.0.3" ) // User Agent should always following the below style. @@ -116,13 +121,12 @@ func New(endpoint string, accessKeyID, secretAccessKey string, secure bool) (*Cl if err != nil { return nil, err } - // Google cloud storage should be set to signature V2, force it if - // not. - if isGoogleEndpoint(clnt.endpointURL) { + // Google cloud storage should be set to signature V2, force it if not. + if s3utils.IsGoogleEndpoint(clnt.endpointURL) { clnt.signature = SignatureV2 } // If Amazon S3 set to signature v2.n - if isAmazonEndpoint(clnt.endpointURL) { + if s3utils.IsAmazonEndpoint(clnt.endpointURL) { clnt.signature = SignatureV4 } return clnt, nil @@ -151,6 +155,18 @@ func (r *lockedRandSource) Seed(seed int64) { r.lk.Unlock() } +// redirectHeaders copies all headers when following a redirect URL. +// This won't be needed anymore from go 1.8 (https://github.com/golang/go/issues/4800) +func redirectHeaders(req *http.Request, via []*http.Request) error { + if len(via) == 0 { + return nil + } + for key, val := range via[0].Header { + req.Header[key] = val + } + return nil +} + func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Client, error) { // construct endpoint. endpointURL, err := getEndpointURL(endpoint, secure) @@ -170,11 +186,12 @@ func privateNew(endpoint, accessKeyID, secretAccessKey string, secure bool) (*Cl clnt.secure = secure // Save endpoint URL, user agent for future uses. - clnt.endpointURL = endpointURL.String() + clnt.endpointURL = *endpointURL // Instantiate http client and bucket location cache. clnt.httpClient = &http.Client{ - Transport: http.DefaultTransport, + Transport: http.DefaultTransport, + CheckRedirect: redirectHeaders, } // Instantiae bucket location cache. @@ -262,6 +279,12 @@ type requestMetadata struct { contentMD5Bytes []byte } +// regCred matches credential string in HTTP header +var regCred = regexp.MustCompile("Credential=([A-Z0-9]+)/") + +// regCred matches signature string in HTTP header +var regSign = regexp.MustCompile("Signature=([[0-9a-f]+)") + // Filter out signature value from Authorization header. func (c Client) filterSignature(req *http.Request) { // For anonymous requests, no need to filter. @@ -281,11 +304,9 @@ func (c Client) filterSignature(req *http.Request) { origAuth := req.Header.Get("Authorization") // Strip out accessKeyID from: // Credential=<access-key-id>/<date>/<aws-region>/<aws-service>/aws4_request - regCred := regexp.MustCompile("Credential=([A-Z0-9]+)/") newAuth := regCred.ReplaceAllString(origAuth, "Credential=**REDACTED**/") // Strip out 256-bit signature from: Signature=<256-bit signature> - regSign := regexp.MustCompile("Signature=([[0-9a-f]+)") newAuth = regSign.ReplaceAllString(newAuth, "Signature=**REDACTED**") // Set a temporary redacted auth @@ -364,20 +385,35 @@ 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) { - // do the request. - 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") { - return nil, &url.Error{ - Op: urlErr.Op, - URL: urlErr.URL, - Err: fmt.Errorf("Connection closed by foreign host %s. Retry again.", urlErr.URL), + 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") { + return nil, &url.Error{ + Op: urlErr.Op, + URL: urlErr.URL, + Err: fmt.Errorf("Connection closed by foreign host %s. Retry again.", urlErr.URL), + } } + 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. @@ -467,6 +503,8 @@ func (c Client) executeMethod(method string, metadata requestMetadata) (res *htt // Read the body to be saved later. errBodyBytes, err := ioutil.ReadAll(res.Body) + // res.Body should be closed + closeResponse(res) if err != nil { return nil, err } @@ -512,7 +550,7 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R // Default all requests to "us-east-1" or "cn-north-1" (china region) location := "us-east-1" - if isAmazonChinaEndpoint(c.endpointURL) { + if s3utils.IsAmazonChinaEndpoint(c.endpointURL) { // 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 @@ -550,10 +588,10 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R } if c.signature.isV2() { // Presign URL with signature v2. - req = preSignV2(*req, c.accessKeyID, c.secretAccessKey, metadata.expires) + req = s3signer.PreSignV2(*req, c.accessKeyID, c.secretAccessKey, metadata.expires) } else { // Presign URL with signature v4. - req = preSignV4(*req, c.accessKeyID, c.secretAccessKey, location, metadata.expires) + req = s3signer.PreSignV4(*req, c.accessKeyID, c.secretAccessKey, location, metadata.expires) } return req, nil } @@ -566,7 +604,7 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R // FIXEM: Enable this when Google Cloud Storage properly supports 100-continue. // Skip setting 'expect' header for Google Cloud Storage, there // are some known issues - https://github.com/restic/restic/issues/520 - if !isGoogleEndpoint(c.endpointURL) { + if !s3utils.IsGoogleEndpoint(c.endpointURL) { // Set 'Expect' header for the request. req.Header.Set("Expect", "100-continue") } @@ -610,10 +648,10 @@ func (c Client) newRequest(method string, metadata requestMetadata) (req *http.R if !c.anonymous { if c.signature.isV2() { // Add signature version '2' authorization header. - req = signV2(*req, c.accessKeyID, c.secretAccessKey) + req = s3signer.SignV2(*req, c.accessKeyID, c.secretAccessKey) } else if c.signature.isV4() { // Add signature version '4' authorization header. - req = signV4(*req, c.accessKeyID, c.secretAccessKey, location) + req = s3signer.SignV4(*req, c.accessKeyID, c.secretAccessKey, location) } } @@ -631,26 +669,21 @@ func (c Client) setUserAgent(req *http.Request) { // makeTargetURL make a new target url. func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, queryValues url.Values) (*url.URL, error) { - // Save host. - url, err := url.Parse(c.endpointURL) - if err != nil { - return nil, err - } - host := url.Host + host := c.endpointURL.Host // For Amazon S3 endpoint, try to fetch location based endpoint. - if isAmazonEndpoint(c.endpointURL) { + if s3utils.IsAmazonEndpoint(c.endpointURL) { // Fetch new host based on the bucket location. host = getS3Endpoint(bucketLocation) } // Save scheme. - scheme := url.Scheme + scheme := c.endpointURL.Scheme urlStr := scheme + "://" + host + "/" // Make URL only if bucketName is available, otherwise use the // endpoint URL. if bucketName != "" { // Save if target url will have buckets which suppport virtual host. - isVirtualHostStyle := 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 @@ -658,19 +691,19 @@ func (c Client) makeTargetURL(bucketName, objectName, bucketLocation string, que if isVirtualHostStyle { urlStr = scheme + "://" + bucketName + "." + host + "/" if objectName != "" { - urlStr = urlStr + urlEncodePath(objectName) + urlStr = urlStr + s3utils.EncodePath(objectName) } } else { // If not fall back to using path style. urlStr = urlStr + bucketName + "/" if objectName != "" { - urlStr = urlStr + urlEncodePath(objectName) + urlStr = urlStr + s3utils.EncodePath(objectName) } } } // If there are any query values, add them to the end. if len(queryValues) > 0 { - urlStr = urlStr + "?" + queryEncode(queryValues) + urlStr = urlStr + "?" + s3utils.QueryEncode(queryValues) } u, err := url.Parse(urlStr) if err != nil { |