diff --git a/.gitignore b/.gitignore index 5cdbab794..c91ea3b83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *~ *.pyc test-env* -junk/ \ No newline at end of file +junk/ +.idea \ No newline at end of file diff --git a/auth.go b/auth.go index ec56cc6ca..62dd27e61 100644 --- a/auth.go +++ b/auth.go @@ -25,6 +25,8 @@ type Authenticator interface { Token() string // The CDN url if available CdnUrl() string + // Is there a point in reattempting auth in this scheme? + ShouldReattemptAuth() bool } // Expireser is an optional interface to read the expiration time of the token @@ -130,6 +132,12 @@ func (auth *v1Auth) CdnUrl() string { return auth.Headers.Get("X-CDN-Management-Url") } +// v1 Authentication - should reattempt login +func (auth *v1Auth) ShouldReattemptAuth() bool { + // No point in reattempting the login in case of auth failure, the expected result is the same + return false +} + // ------------------------------------------------------------ // v2 Authentication @@ -261,6 +269,12 @@ func (auth *v2Auth) CdnUrl() string { return auth.endpointUrl("rax:object-cdn", EndpointTypePublic) } +// v2 Authentication - should reattempt login +func (auth *v2Auth) ShouldReattemptAuth() bool { + // As part of the Rackspace auth workaround authentication sometimes needs to be retried + return true +} + // ------------------------------------------------------------ // V2 Authentication request diff --git a/auth_v3.go b/auth_v3.go index 1c51b9ea1..6af58703d 100644 --- a/auth_v3.go +++ b/auth_v3.go @@ -301,3 +301,8 @@ func (auth *v3Auth) Expires() time.Time { func (auth *v3Auth) CdnUrl() string { return "" } + +func (auth *v3Auth) ShouldReattemptAuth() bool { + // No point in reattempting the login in case of auth failure, the expected result is the same + return false +} diff --git a/swift.go b/swift.go index 11de54407..7441f04d7 100644 --- a/swift.go +++ b/swift.go @@ -494,7 +494,8 @@ func (c *Connection) authenticate(ctx context.Context) (err error) { } } - retries := 1 + shouldReattempt := c.Auth.ShouldReattemptAuth() + again: var req *http.Request req, err = c.Auth.Request(ctx, c) @@ -519,8 +520,8 @@ again: // Try again for a limited number of times on // AuthorizationFailed or BadRequest. This allows us // to try some alternate forms of the request - if (err == AuthorizationFailed || err == BadRequest) && retries > 0 { - retries-- + if (err == AuthorizationFailed || err == BadRequest) && shouldReattempt { + shouldReattempt = false goto again } return diff --git a/swift_internal_test.go b/swift_internal_test.go index e84080084..071000183 100644 --- a/swift_internal_test.go +++ b/swift_internal_test.go @@ -335,19 +335,34 @@ func TestInternalAuthenticate(t *testing.T) { } } -func TestInternalAuthenticateDenied(t *testing.T) { +func setVersion(version int) { + c.AuthVersion = version + c.Auth = nil +} + +func TestInternalAuthenticateDeniedv2(t *testing.T) { server.AddCheck(t).Error(400, "Bad request") server.AddCheck(t).Error(401, "DENIED") defer server.Finished() + defer setVersion(c.AuthVersion) + setVersion(2) + c.UnAuthenticate() + err := c.Authenticate(context.Background()) + if err != AuthorizationFailed { + t.Fatal("Expecting AuthorizationFailed", err) + } +} + +func TestInternalAuthenticateDeniedv3(t *testing.T) { + server.AddCheck(t).Error(401, "DENIED") + defer server.Finished() + defer setVersion(c.AuthVersion) + setVersion(3) c.UnAuthenticate() err := c.Authenticate(context.Background()) if err != AuthorizationFailed { t.Fatal("Expecting AuthorizationFailed", err) } - // FIXME - // if c.Authenticated() { - // t.Fatal("Expecting not authenticated") - // } } func TestInternalAuthenticateBad(t *testing.T) {