44 "context"
55 "encoding/json"
66 "fmt"
7+ "io"
78 "net/http"
89 "net/url"
910 "strings"
@@ -33,12 +34,14 @@ type Message struct {
3334 Timestamp time.Time `json:"timestamp"`
3435}
3536
36- // Config holds subscription manager configuration
37- type Config struct {
37+ // ManagerConfig holds subscription manager configuration
38+ type ManagerConfig struct {
3839 ServerURL string
3940 ReplicaPath string
4041 AuthToken string
4142 ReplicaID string
43+ WsID string // websocket ID for client identification
44+ ClientVersion string // version of the client software
4245 Logger * zap.Logger
4346 MaxReconnectAttempts int // Maximum number of reconnect attempts (0 = infinite)
4447 InitialReconnectDelay time.Duration // Initial delay before first reconnect
@@ -53,7 +56,7 @@ type Config struct {
5356// MaxReconnectDelay is reached. Reconnection attempts continue indefinitely unless
5457// MaxReconnectAttempts is set to a positive value.
5558type Manager struct {
56- config * Config
59+ config * ManagerConfig
5760 logger * zap.Logger
5861 conn * websocket.Conn
5962 ctx context.Context
@@ -72,7 +75,7 @@ type Manager struct {
7275}
7376
7477// NewManager creates a new subscription manager
75- func NewManager (config * Config ) * Manager {
78+ func NewManager (config * ManagerConfig ) * Manager {
7679 ctx , cancel := context .WithCancel (context .Background ())
7780
7881 // Set default reconnection parameters if not provided
@@ -201,15 +204,69 @@ func (m *Manager) doConnect() error {
201204 headers .Set ("X-ReplicaID" , m .config .ReplicaID )
202205 }
203206
207+ headers .Set ("X-ClientVersion" , m .config .ClientVersion )
208+ headers .Set ("X-ClientID" , m .config .WsID )
209+
204210 dialer := websocket.Dialer {
205211 HandshakeTimeout : 10 * time .Second ,
206212 }
207213
208214 m .logger .Debug ("Dialing WebSocket" , zap .String ("url" , u .String ()))
209215
210- conn , _ , err := dialer .DialContext (m .ctx , u .String (), headers )
216+ conn , response , err := dialer .DialContext (m .ctx , u .String (), headers )
211217 if err != nil {
212- return fmt .Errorf ("failed to connect to subscription service: %w" , err )
218+ if response != nil {
219+ // Extract detailed error information from the response
220+ statusCode := response .StatusCode
221+ statusText := response .Status
222+
223+ var respBodyStr string
224+ if response .Body != nil {
225+ respBytes , readErr := io .ReadAll (response .Body )
226+ response .Body .Close ()
227+ if readErr == nil {
228+ respBodyStr = strings .TrimSpace (string (respBytes ))
229+ }
230+ }
231+
232+ // Create a clean error message
233+ var errorMsg strings.Builder
234+ errorMsg .WriteString (fmt .Sprintf ("HTTP %d (%s)" , statusCode , statusText ))
235+
236+ if respBodyStr != "" {
237+ errorMsg .WriteString (fmt .Sprintf (": %s" , respBodyStr ))
238+ }
239+
240+ return fmt .Errorf ("%s" , errorMsg .String ())
241+ }
242+
243+ // Handle cases where response is nil (e.g., network errors, bad handshake)
244+ var errorMsg strings.Builder
245+ errorMsg .WriteString ("Failed to connect to subscription service" )
246+
247+ // Analyze the error type and provide helpful context
248+ errorStr := err .Error ()
249+ if strings .Contains (errorStr , "bad handshake" ) {
250+ errorMsg .WriteString (" - WebSocket handshake failed" )
251+ errorMsg .WriteString ("\n This could be due to:" )
252+ errorMsg .WriteString ("\n • Invalid server URL or endpoint" )
253+ errorMsg .WriteString ("\n • Server not supporting WebSocket connections" )
254+ errorMsg .WriteString ("\n • Network connectivity issues" )
255+ errorMsg .WriteString ("\n • Authentication problems" )
256+ } else if strings .Contains (errorStr , "timeout" ) {
257+ errorMsg .WriteString (" - Connection timeout" )
258+ errorMsg .WriteString ("\n The server may be overloaded or unreachable" )
259+ } else if strings .Contains (errorStr , "refused" ) {
260+ errorMsg .WriteString (" - Connection refused" )
261+ errorMsg .WriteString ("\n The server may be down or the port may be blocked" )
262+ } else if strings .Contains (errorStr , "no such host" ) {
263+ errorMsg .WriteString (" - DNS resolution failed" )
264+ errorMsg .WriteString ("\n Check the server hostname in your configuration" )
265+ }
266+
267+ errorMsg .WriteString (fmt .Sprintf ("\n Original error: %v" , err ))
268+
269+ return fmt .Errorf ("%s" , errorMsg .String ())
213270 }
214271
215272 m .mu .Lock ()
0 commit comments