diff --git a/cmd/rpc/server.go b/cmd/rpc/server.go index 47d181e5f5..137c13c7cb 100644 --- a/cmd/rpc/server.go +++ b/cmd/rpc/server.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/fs" + "net" "net/http" "os" "path" @@ -78,11 +79,11 @@ func NewServer(controller *controller.Controller, config lib.Config, logger lib. // Start initializes the Canopy RPC servers func (s *Server) Start() { - hostport := strings.Split(s.config.ListenAddress, ":") + host := listenHost(s.config.ListenAddress) // Start the Query and Admin RPC servers concurrently - go s.startRPC(createRouter(s), hostport[0], s.config.RPCPort) - go s.startRPC(createAdminRouter(s), hostport[0], s.config.AdminPort) - go s.startRPC(createDebugRouter(), hostport[0], s.config.ProfilingPort) + go s.startRPC(createRouter(s), host, s.config.RPCPort) + go s.startRPC(createAdminRouter(s), host, s.config.AdminPort) + go s.startRPC(createDebugRouter(), host, s.config.ProfilingPort) // Start tasks to update poll results and poll root chain information go s.updatePollResults() @@ -164,14 +165,22 @@ func (s *Server) updatePollResults() { // startStaticFileServers starts a file server for the wallet and explorer func (s *Server) startStaticFileServers() { - hostport := strings.Split(s.config.ListenAddress, ":") - s.logger.Infof("Starting Web Wallet 🔑 http://%s:%s ⬅️", hostport[0], s.config.WalletPort) + host := listenHost(s.config.ListenAddress) + s.logger.Infof("Starting Web Wallet 🔑 http://%s:%s ⬅️", host, s.config.WalletPort) s.runStaticFileServer(walletFS, walletStaticDir, s.config.WalletPort, s.config) - s.logger.Infof("Starting Block Explorer 🔍️ http://%s:%s ⬅️", hostport[0], s.config.ExplorerPort) + s.logger.Infof("Starting Block Explorer 🔍️ http://%s:%s ⬅️", host, s.config.ExplorerPort) s.runStaticFileServer(explorerFS, explorerStaticDir, s.config.ExplorerPort, s.config) } +func listenHost(address string) string { + host, _, err := net.SplitHostPort(address) + if err == nil { + return host + } + return strings.Split(address, colon)[0] +} + // startHeapProfiler writes periodic heap profiles to the data directory // Warning: This calls runtime.GC() which causes pauses and may affect RPC latency func (s *Server) startHeapProfiler() { diff --git a/cmd/rpc/server_test.go b/cmd/rpc/server_test.go new file mode 100644 index 0000000000..659cb5b48a --- /dev/null +++ b/cmd/rpc/server_test.go @@ -0,0 +1,24 @@ +package rpc + +import "testing" + +func TestListenHost(t *testing.T) { + tests := []struct { + name string + address string + want string + }{ + {name: "ipv4", address: "0.0.0.0:9001", want: "0.0.0.0"}, + {name: "wildcard", address: ":9001", want: ""}, + {name: "ipv6", address: "[::]:9001", want: "::"}, + {name: "host_without_port", address: "localhost", want: "localhost"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := listenHost(tt.address); got != tt.want { + t.Fatalf("listenHost(%q) = %q, want %q", tt.address, got, tt.want) + } + }) + } +}