Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add natsProtoErr that can be used with errors.Is #1082

Merged
merged 1 commit into from Sep 15, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions nats.go
Expand Up @@ -2323,6 +2323,19 @@ func normalizeErr(line string) string {
return s
}

// natsProtoErr represents an -ERR protocol message sent by the server.
type natsProtoErr struct {
description string
}

func (nerr *natsProtoErr) Error() string {
return fmt.Sprintf("nats: %s", nerr.description)
}

func (nerr *natsProtoErr) Is(err error) bool {
return strings.ToLower(nerr.Error()) == err.Error()
}

// Send a connect protocol message to the server, issue user/password if
// applicable. Will wait for a flush to return from the server for error
// processing.
Expand Down Expand Up @@ -2377,8 +2390,7 @@ func (nc *Conn) sendConnect() error {
// in doReconnect()).
nc.processAuthError(authErr)
}

return errors.New("nats: " + proto)
return &natsProtoErr{proto}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but have you tried adding a return authErr in the "if" statement above? Does that work? Point is that we may not need to do any conversions for the known errors handled in checkAuthError. Your changes is still valid I guess for all other cases?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by "does it work", I mean the user code could then do if err == nats.ErrAuthorization without even have to use the errors.Is().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does work but then I saw that we also tested for uppercase literal error in other tests like: https://github.com/nats-io/nats.go/blob/main/test/cluster_test.go#L192-L194
and recommendation from Go team is to start using errors.Is anyway instead of checking directly to check for wrapped errors as well.

}

// Notify that we got an unexpected protocol.
Expand Down
5 changes: 5 additions & 0 deletions test/auth_test.go
Expand Up @@ -14,6 +14,7 @@
package test

import (
"errors"
"fmt"
"strings"
"sync/atomic"
Expand Down Expand Up @@ -44,6 +45,10 @@ func TestAuth(t *testing.T) {
t.Fatalf("Expected error '%v', got '%v'", nats.ErrAuthorization, err)
}

if !errors.Is(err, nats.ErrAuthorization) {
t.Fatalf("Expected error '%v', got '%v'", nats.ErrAuthorization, err)
}

nc, err := nats.Connect("nats://derek:foo@127.0.0.1:8232")
if err != nil {
t.Fatal("Should have connected successfully with a token")
Expand Down
5 changes: 5 additions & 0 deletions test/cluster_test.go
Expand Up @@ -14,6 +14,7 @@
package test

import (
"errors"
"fmt"
"math"
"net"
Expand Down Expand Up @@ -193,6 +194,10 @@ func TestAuthServers(t *testing.T) {
t.Fatalf("Wrong error, wanted Auth failure, got '%s'\n", err)
}

if !errors.Is(err, nats.ErrAuthorization) {
t.Fatalf("Expected error '%v', got '%v'", nats.ErrAuthorization, err)
}

// Test that we can connect to a subsequent correct server.
var authServers = []string{
"nats://127.0.0.1:1222",
Expand Down