Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion api.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,31 @@ func redirectHeaders(req *http.Request, via []*http.Request) error {
return nil
}

// 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"
}
parts := s3utils.AmazonS3Host.FindStringSubmatch(u.Host)
if len(parts) > 1 {
region = parts[1]
}
return region
}

func privateNew(endpoint string, creds *credentials.Credentials, secure bool, region string) (*Client, error) {
// construct endpoint.
endpointURL, err := getEndpointURL(endpoint, secure)
Expand All @@ -216,6 +241,9 @@ func privateNew(endpoint string, creds *credentials.Credentials, secure bool, re
}

// Sets custom region, if region is empty bucket location cache is used automatically.
if region == "" {
region = getRegionFromURL(clnt.endpointURL)
}
clnt.region = region

// Instantiate bucket location cache.
Expand Down Expand Up @@ -494,7 +522,7 @@ func (c Client) executeMethod(method string, metadata requestMetadata) (res *htt
// Blank indentifier is kept here on purpose since 'range' without
// blank identifiers is only supported since go1.4
// https://golang.org/doc/go1.4#forrange.
for _ = range c.newRetryTimer(MaxRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter, doneCh) {
for range c.newRetryTimer(MaxRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter, doneCh) {
// Retry executes the following function body if request has an
// error until maxRetries have been exhausted, retry attempts are
// performed after waiting for a given period of time in a
Expand Down
44 changes: 44 additions & 0 deletions api_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,50 @@ func TestGetReaderSize(t *testing.T) {
}
}

// 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 {
Expand Down
14 changes: 0 additions & 14 deletions bucket-cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,6 @@ func (c Client) getBucketLocation(bucketName string) (string, error) {
return c.region, nil
}

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
// China region.
return "cn-north-1", nil
} else if s3utils.IsAmazonGovCloudEndpoint(c.endpointURL) {
// 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", nil
}

if location, ok := c.bucketLocCache.Get(bucketName); ok {
return location, nil
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/s3utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ 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$")

// IsAmazonEndpoint - Match if it is exactly Amazon S3 endpoint.
func IsAmazonEndpoint(endpointURL url.URL) bool {
if IsAmazonChinaEndpoint(endpointURL) {
Expand All @@ -88,7 +91,7 @@ func IsAmazonEndpoint(endpointURL url.URL) bool {
if IsAmazonGovCloudEndpoint(endpointURL) {
return true
}
return endpointURL.Host == "s3.amazonaws.com"
return AmazonS3Host.MatchString(endpointURL.Host)
}

// IsAmazonGovCloudEndpoint - Match if it is exactly Amazon S3 GovCloud endpoint.
Expand Down