Skip to content
New issue

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

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

Already on GitHub? # to your account

feat: allow to get the network address server is listening on #217

Merged
merged 2 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ type OpAMPServer interface {
// Stop accepting new connections and close all current connections. This should
// block until all connections are closed.
Stop(ctx context.Context) error

// Addr returns the network address Server is listening on. Nil if not started.
// Typically used to fetch the port when ListenEndpoint's port is specified as 0 to
// allocate an ephemeral port.
Addr() net.Addr
}
8 changes: 8 additions & 0 deletions server/serverimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type server struct {
// The listening HTTP Server after successful Start() call. Nil if Start()
// is not called or was not successful.
httpServer *http.Server

// The network address Server is listening on. Nil if not started.
addr net.Addr
}

var _ OpAMPServer = (*server)(nil)
Expand Down Expand Up @@ -118,6 +121,7 @@ func (s *server) startHttpServer(listenAddr string, serveFunc func(l net.Listene
if err != nil {
return err
}
s.addr = ln.Addr()

// Begin serving connections in the background.
go func() {
Expand All @@ -143,6 +147,10 @@ func (s *server) Stop(ctx context.Context) error {
return nil
}

func (s *server) Addr() net.Addr {
return s.addr
}

func (s *server) httpHandler(w http.ResponseWriter, req *http.Request) {
var connectionCallbacks serverTypes.ConnectionCallbacks
if s.settings.Callbacks != nil {
Expand Down
34 changes: 16 additions & 18 deletions server/serverimpl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func startServer(t *testing.T, settings *StartSettings) *server {
srv := New(&sharedinternal.NopLogger{})
require.NotNil(t, srv)
if settings.ListenEndpoint == "" {
// Find an avaiable port to listne on.
settings.ListenEndpoint = testhelpers.GetAvailableLocalAddress()
// allocate an ephemeral port to listne on.
settings.ListenEndpoint = "127.0.0.1:0"
}
if settings.ListenPath == "" {
settings.ListenPath = "/"
Expand All @@ -40,8 +40,8 @@ func startServer(t *testing.T, settings *StartSettings) *server {
return srv
}

func dialClient(serverSettings *StartSettings) (*websocket.Conn, *http.Response, error) {
srvUrl := "ws://" + serverSettings.ListenEndpoint + serverSettings.ListenPath
func dialClient(addr string, serverSettings *StartSettings) (*websocket.Conn, *http.Response, error) {
srvUrl := "ws://" + addr + serverSettings.ListenPath
dailer := websocket.DefaultDialer
dailer.EnableCompression = serverSettings.EnableCompression
return websocket.DefaultDialer.Dial(srvUrl, nil)
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestServerStartRejectConnection(t *testing.T) {
defer srv.Stop(context.Background())

// Try to connect to the Server.
conn, resp, err := dialClient(settings)
conn, resp, err := dialClient(srv.Addr().String(), settings)

// Verify that the connection is rejected and rejection data is available to the client.
assert.Nil(t, conn)
Expand Down Expand Up @@ -113,7 +113,7 @@ func TestServerStartAcceptConnection(t *testing.T) {
defer srv.Stop(context.Background())

// Connect to the Server.
conn, resp, err := dialClient(settings)
conn, resp, err := dialClient(srv.Addr().String(), settings)

// Verify that the connection is successful.
assert.NoError(t, err)
Expand Down Expand Up @@ -158,7 +158,7 @@ func TestDisconnectWSConnection(t *testing.T) {
defer srv.Stop(context.Background())

// Connect to the Server.
conn, _, err := dialClient(settings)
conn, _, err := dialClient(srv.Addr().String(), settings)

// Verify that the connection is successful.
assert.NoError(t, err)
Expand Down Expand Up @@ -204,7 +204,7 @@ func TestServerReceiveSendMessage(t *testing.T) {
defer srv.Stop(context.Background())

// Connect using a WebSocket client.
conn, _, _ := dialClient(settings)
conn, _, _ := dialClient(srv.Addr().String(), settings)
require.NotNil(t, conn)
defer conn.Close()

Expand Down Expand Up @@ -279,13 +279,11 @@ func TestServerReceiveSendMessageWithCompression(t *testing.T) {

// We use a transparent TCP proxy to be able to count the actual bytes transferred so that
// we can test the number of actual bytes vs number of expected bytes with and without compression.
proxy := testhelpers.NewProxy(settings.ListenEndpoint)
proxy := testhelpers.NewProxy(srv.Addr().String())
assert.NoError(t, proxy.Start())

serverSettings := *settings
serverSettings.ListenEndpoint = proxy.IncomingEndpoint()
// Connect using a WebSocket client.
conn, _, _ := dialClient(&serverSettings)
conn, _, _ := dialClient(proxy.IncomingEndpoint(), settings)
require.NotNil(t, conn)
defer conn.Close()

Expand Down Expand Up @@ -380,7 +378,7 @@ func TestServerReceiveSendMessagePlainHTTP(t *testing.T) {
}
b, err := proto.Marshal(&sendMsg)
require.NoError(t, err)
resp, err := http.Post("http://"+settings.ListenEndpoint+settings.ListenPath, contentTypeProtobuf, bytes.NewReader(b))
resp, err := http.Post("http://"+srv.Addr().String()+settings.ListenPath, contentTypeProtobuf, bytes.NewReader(b))
require.NoError(t, err)

// Wait until Server receives the message.
Expand Down Expand Up @@ -585,7 +583,7 @@ func TestServerHonoursClientRequestContentEncoding(t *testing.T) {
b, err = compressGzip(b)
require.NoError(t, err)

req, err := http.NewRequest("POST", "http://"+settings.ListenEndpoint+settings.ListenPath, bytes.NewReader(b))
req, err := http.NewRequest("POST", "http://"+srv.Addr().String()+settings.ListenPath, bytes.NewReader(b))
req.Header.Set(headerContentType, contentTypeProtobuf)
req.Header.Set(headerContentEncoding, contentEncodingGzip)
resp, err := hc.Do(req)
Expand Down Expand Up @@ -657,7 +655,7 @@ func TestServerHonoursAcceptEncoding(t *testing.T) {
}
b, err := proto.Marshal(&sendMsg)
require.NoError(t, err)
req, err := http.NewRequest("POST", "http://"+settings.ListenEndpoint+settings.ListenPath, bytes.NewReader(b))
req, err := http.NewRequest("POST", "http://"+srv.Addr().String()+settings.ListenPath, bytes.NewReader(b))
req.Header.Set(headerContentType, contentTypeProtobuf)
req.Header.Set(headerAcceptEncoding, contentEncodingGzip)
resp, err := hc.Do(req)
Expand Down Expand Up @@ -743,7 +741,7 @@ func TestConnectionAllowsConcurrentWrites(t *testing.T) {
defer srv.Stop(context.Background())

// Connect to the Server.
conn, _, err := dialClient(settings)
conn, _, err := dialClient(srv.Addr().String(), settings)

// Verify that the connection is successful.
assert.NoError(t, err)
Expand Down Expand Up @@ -797,7 +795,7 @@ func BenchmarkSendToClient(b *testing.B) {
// Start a Server.
settings := &StartSettings{
Settings: Settings{Callbacks: callbacks},
ListenEndpoint: testhelpers.GetAvailableLocalAddress(),
ListenEndpoint: "127.0.0.1:0",
ListenPath: "/",
}
srv := New(&sharedinternal.NopLogger{})
Expand All @@ -810,7 +808,7 @@ func BenchmarkSendToClient(b *testing.B) {
defer srv.Stop(context.Background())

for i := 0; i < b.N; i++ {
conn, resp, err := dialClient(settings)
conn, resp, err := dialClient(srv.Addr().String(), settings)

if err != nil || resp == nil || conn == nil {
b.Error("Could not establish connection:", err)
Expand Down