Skip to content

Commit

Permalink
[ADDED] IgnoreAuthErrorAbort option on Connect (#1141)
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrpio authored Nov 22, 2022
1 parent 8499836 commit 398a1ec
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
17 changes: 15 additions & 2 deletions nats.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,10 @@ type Options struct {

// InboxPrefix allows the default _INBOX prefix to be customized
InboxPrefix string

// IgnoreAuthErrorAbort - if set to true, client opts out of the default connect behavior of aborting
// subsequent reconnect attempts if server returns the same auth error twice (regardless of reconnect policy).
IgnoreAuthErrorAbort bool
}

const (
Expand Down Expand Up @@ -1249,6 +1253,15 @@ func CustomInboxPrefix(p string) Option {
}
}

// IgnoreAuthErrorAbort opts out of the default connect behavior of aborting
// subsequent reconnect attempts if server returns the same auth error twice.
func IgnoreAuthErrorAbort() Option {
return func(o *Options) error {
o.IgnoreAuthErrorAbort = true
return nil
}
}

// Handler processing

// SetDisconnectHandler will set the disconnect event handler.
Expand Down Expand Up @@ -3153,8 +3166,8 @@ func (nc *Conn) processAuthError(err error) bool {
nc.ach.push(func() { nc.Opts.AsyncErrorCB(nc, nil, err) })
}
// We should give up if we tried twice on this server and got the
// same error.
if nc.current.lastErr == err {
// same error. This behavior can be modified using IgnoreAuthErrorAbort.
if nc.current.lastErr == err && !nc.Opts.IgnoreAuthErrorAbort {
nc.ar = true
} else {
nc.current.lastErr = err
Expand Down
42 changes: 35 additions & 7 deletions nats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1610,10 +1610,14 @@ func TestExpiredAuthentication(t *testing.T) {
name string
expectedProto string
expectedErr error
ignoreAbort bool
}{
{"expired users credentials", AUTHENTICATION_EXPIRED_ERR, ErrAuthExpired},
{"revoked users credentials", AUTHENTICATION_REVOKED_ERR, ErrAuthRevoked},
{"expired account", ACCOUNT_AUTHENTICATION_EXPIRED_ERR, ErrAccountAuthExpired},
{"expired users credentials", AUTHENTICATION_EXPIRED_ERR, ErrAuthExpired, false},
{"revoked users credentials", AUTHENTICATION_REVOKED_ERR, ErrAuthRevoked, false},
{"expired account", ACCOUNT_AUTHENTICATION_EXPIRED_ERR, ErrAccountAuthExpired, false},
{"expired users credentials", AUTHENTICATION_EXPIRED_ERR, ErrAuthExpired, true},
{"revoked users credentials", AUTHENTICATION_REVOKED_ERR, ErrAuthRevoked, true},
{"expired account", ACCOUNT_AUTHENTICATION_EXPIRED_ERR, ErrAccountAuthExpired, true},
} {
t.Run(test.name, func(t *testing.T) {
l, e := net.Listen("tcp", "127.0.0.1:0")
Expand Down Expand Up @@ -1661,8 +1665,8 @@ func TestExpiredAuthentication(t *testing.T) {
errCh := make(chan error, 10)

url := fmt.Sprintf("nats://127.0.0.1:%d", addr.Port)
nc, err := Connect(url,
ReconnectWait(25*time.Millisecond),
opts := []Option{
ReconnectWait(25 * time.Millisecond),
ReconnectJitter(0, 0),
MaxReconnects(-1),
ErrorHandler(func(_ *Conn, _ *Subscription, e error) {
Expand All @@ -1674,12 +1678,36 @@ func TestExpiredAuthentication(t *testing.T) {
ClosedHandler(func(nc *Conn) {
ch <- true
}),
)
}
if test.ignoreAbort {
opts = append(opts, IgnoreAuthErrorAbort())
}
nc, err := Connect(url, opts...)
if err != nil {
t.Fatalf("Expected to connect, got %v", err)
}
defer nc.Close()

if test.ignoreAbort {
// We expect more than 3 errors, as the connect attempt should not be aborted after 2 failed attempts.
for i := 0; i < 4; i++ {
select {
case e := <-errCh:
if i == 0 && e != test.expectedErr {
t.Fatalf("Expected error %q, got %q", test.expectedErr, e)
} else if i > 0 && e != ErrAuthorization {
t.Fatalf("Expected error %q, got %q", ErrAuthorization, e)
}
case <-time.After(time.Second):
if i == 0 {
t.Fatalf("Missing %q error", test.expectedErr)
} else {
t.Fatalf("Missing %q error", ErrAuthorization)
}
}
}
return
}
// We should give up since we get the same error on both tries.
if err := WaitTime(ch, 2*time.Second); err != nil {
t.Fatal("Should have closed after multiple failed attempts.")
Expand Down Expand Up @@ -1795,7 +1823,7 @@ func TestNkeyAuth(t *testing.T) {

sopts := natsserver.DefaultTestOptions
sopts.Port = TEST_PORT
sopts.Nkeys = []*server.NkeyUser{&server.NkeyUser{Nkey: string(pub)}}
sopts.Nkeys = []*server.NkeyUser{{Nkey: string(pub)}}
ts := RunServerWithOptions(&sopts)
defer ts.Shutdown()

Expand Down

0 comments on commit 398a1ec

Please sign in to comment.