Repository: nats-io/nats.go (go)

Issue:
NATS client connecting to local server due to stray comma in connect string
## Defect

Make sure that these boxes are checked before submitting your issue -- thank you!

 - [x] Included nats.go version
 - [x] Included a [Minimal, Complete, and Verifiable example] (https://stackoverflow.com/help/mcve)

#### Versions of `nats.go` and the `nats-server` if one was involved:
HEAD of main (currently: [0797ed6](https://github.com/nats-io/nats.go/commit/0797ed6e297f31f154d0c904b8aa360675693691))

#### OS/Container environment:
N/R

#### Steps or code to reproduce the issue:
```
connectURL="nats://hostname1:4222,nats://hostname2:4222,nats://hostname3:4222,"
nats.Connect(connectURL)
```

#### Expected result:
Connect to any of the 3 server URLs in the connect string.

#### Actual result:
There's a (random) chance that the client will try to connect to `nats://localhost:4222`, a server not present in the connect string!

This can be quite confusing from a user perspective. Suddenly (as a result of reconnect) streams are gone, authentication fails, etc.

The reason is the trailing comma in the connect string. 
It gets automatically expanded to `nats://:4222`, and this gets added to the list of servers to connect to.


#### Misc:

To see this happening, add the following in `func (nc *Conn) connect()`

```
	for i := 0; i < len(nc.srvPool); i++ {
		fmt.Printf("👁 nc.srvPool[%d].url: %v\n", i, nc.srvPool[i].url)
	}
```

If the connect string contains a trailing comma (also commas in other places), it will show something like this:
```
👁 nc.srvPool[0].url: nats://127.0.0.1:61110
👁 nc.srvPool[1].url: nats://127.0.0.1:61103
👁 nc.srvPool[2].url: nats://:4222
👁 nc.srvPool[3].url: nats://127.0.0.1:61119
```


Pull request description:
[FIXED] Trailing comma at end of URL lists should be ignored
Resolves #1056

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>

Patch:
diff --git a/nats.go b/nats.go
index 3143b9a..24256b0 100644
--- a/nats.go
+++ b/nats.go
@@ -1268,10 +1268,15 @@ func (nc *Conn) SetErrorHandler(cb ErrHandler) {
 // Return an array of urls, even if only one.
 func processUrlString(url string) []string {
 	urls := strings.Split(url, ",")
-	for i, s := range urls {
-		urls[i] = strings.TrimSpace(s)
+	var j int
+	for _, s := range urls {
+		u := strings.TrimSpace(s)
+		if len(u) > 0 {
+			urls[j] = u
+			j++
+		}
 	}
-	return urls
+	return urls[:j]
 }
 
 // Connect will attempt to connect to a NATS server with multiple options.


Test patch:
diff --git a/nats_test.go b/nats_test.go
index 176f6d0..6700167 100644
--- a/nats_test.go
+++ b/nats_test.go
@@ -2920,3 +2920,23 @@ func TestInProcessConn(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestServerListWithTrailingComma(t *testing.T) {
+	s := RunServerOnPort(-1)
+	defer s.Shutdown()
+
+	// Notice the comma at the end of the "list"
+	nc, err := Connect(fmt.Sprintf("%s,", s.ClientURL()))
+	if err != nil {
+		t.Fatalf("Unable to connect: %v", err)
+	}
+	defer nc.Close()
+
+	// Now check server pool
+	nc.mu.Lock()
+	l := len(nc.srvPool)
+	nc.mu.Unlock()
+	if l != 1 {
+		t.Fatalf("There should be only 1 URL in the list, got %v", l)
+	}
+}