Skip to content

Commit

Permalink
Merge pull request #1075 from adrian-thurston/return-random-port
Browse files Browse the repository at this point in the history
[ADDED] ClientURL() API and expose an OS-assigned server port via the NATS server options
  • Loading branch information
kozlovic committed Sep 25, 2020
2 parents 18cff06 + 85a8092 commit 8f0eb07
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
22 changes: 22 additions & 0 deletions server/server.go
Expand Up @@ -756,6 +756,9 @@ type StanServer struct {
// cause races when running more than 1 server in a program or test.
pingResponseOKBytes []byte
pingResponseInvalidClientBytes []byte

// If using an external server, capture the URL that was given for return in ClientURL().
providedServerURL string
}

type subsSentAndAckReplication struct {
Expand Down Expand Up @@ -1442,6 +1445,9 @@ func (s *StanServer) buildServerURLs() ([]string, error) {
}
// Use net.Join to support IPV6 addresses.
hostport = net.JoinHostPort(host, port)

// Capture for ClientURL()
s.providedServerURL = natsURL
} else {
// We embed the server, so it is local. If host is "any",
// use 127.0.0.1 or ::1 for host address (important for
Expand Down Expand Up @@ -1763,6 +1769,9 @@ func RunServerWithOpts(stanOpts *Options, natsOpts *server.Options) (newServer *
if err := s.startNATSServer(); err != nil {
return nil, err
}
if natsOpts != nil && natsOpts.Port == server.RANDOM_PORT {
natsOpts.Port = nOpts.Port
}
}
// Check for monitoring
if nOpts.HTTPPort != 0 || nOpts.HTTPSPort != 0 {
Expand Down Expand Up @@ -1805,6 +1814,19 @@ func RunServerWithOpts(stanOpts *Options, natsOpts *server.Options) (newServer *
return &s, nil
}

// ClientURL returns the basic URL string representation suitable for a client to use to connect
func (s *StanServer) ClientURL() string {
s.mu.Lock()
defer s.mu.Unlock()
if s.providedServerURL != "" {
return s.providedServerURL
} else if s.natsServer != nil {
return s.natsServer.ClientURL()
} else {
return ""
}
}

// Logging in STAN
//
// The STAN logger is an instance of a NATS logger, (basically duplicated
Expand Down
73 changes: 73 additions & 0 deletions server/server_test.go
Expand Up @@ -20,14 +20,17 @@ import (
"io/ioutil"
"os"
"reflect"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"testing"
"time"

natsd "github.com/nats-io/nats-server/v2/server"
natsdTest "github.com/nats-io/nats-server/v2/test"
"github.com/nats-io/nats-streaming-server/logger"
"github.com/nats-io/nats-streaming-server/stores"
"github.com/nats-io/nats-streaming-server/test"
Expand Down Expand Up @@ -1370,3 +1373,73 @@ func TestAckProcessedBeforeClose(t *testing.T) {
dur.Unsubscribe()
}
}

func TestServerRandomPort(t *testing.T) {
natsOpts := natsdTest.DefaultTestOptions
natsOpts.Port = natsd.RANDOM_PORT
opts := GetDefaultOptions()
s := runServerWithOpts(t, opts, &natsOpts)
defer s.Shutdown()

if natsOpts.Port == natsd.RANDOM_PORT {
t.Fatal("port was not updated")
}
s.Shutdown()

// Try with no nats options provided to make sure we don't
// access natsOpts without checking that it is not nil
s = runServerWithOpts(t, opts, nil)
s.Shutdown()
}

func TestServerRandomClientURL(t *testing.T) {
// Try with an embedded server.
natsOpts := natsdTest.DefaultTestOptions
natsOpts.Port = natsd.RANDOM_PORT
opts := GetDefaultOptions()
s := runServerWithOpts(t, opts, &natsOpts)
clientURL := s.ClientURL()
defer s.Shutdown()

re := regexp.MustCompile(":[0-9]+$")
portString := re.FindString(clientURL)
if len(portString) == 3 {
t.Fatal("could not locate port in clientURL")
}

urlPort, err := strconv.Atoi(portString[1:])
if err != nil {
t.Fatal("failed to convert clientURL to integer")
}

if natsOpts.Port != urlPort {
t.Fatal("options port did not match clientURL port")
}
s.Shutdown()

// Try with remote server
natsOpts = natsdTest.DefaultTestOptions
natsOpts.Port = natsd.RANDOM_PORT
ns := natsdTest.RunServer(&natsOpts)
defer ns.Shutdown()
print(ns.ClientURL())

opts.NATSServerURL = fmt.Sprintf("nats://%s:%d", natsOpts.Host, natsOpts.Port)
s = runServerWithOpts(t, opts, nil)
defer s.Shutdown()

clientURL = s.ClientURL()
portString = re.FindString(clientURL)
if len(portString) == 3 {
t.Fatal("could not locate port in clientURL")
}

urlPort, err = strconv.Atoi(portString[1:])
if err != nil {
t.Fatal("failed to convert clientURL to integer")
}

if natsOpts.Port != urlPort {
t.Fatal("options port did not match clientURL port")
}
}

0 comments on commit 8f0eb07

Please sign in to comment.