gqlgen: Could not connect to websocket

Could not connect to websocket endpoint wss://127.0.0.1:4000/api/query. Please check if the endpoint url is correct.

Im using mux.

resolver.go

var TicketSub struct {
	sync.RWMutex
	Subscribers map[string]chan *gqlapi.TicketStatusChangePayload
}

func (r *subscriptionRootResolver) TicketStatusChanged(ctx context.Context) (<-chan *gqlapi.TicketStatusChangePayload, error) {
	user := &models.User{
		UUID: "e70e78bb-9d08-405d-a0ed-266ec703de19",
	}
	events := make(chan *gqlapi.TicketStatusChangePayload, 1)

	go func() {
		<-ctx.Done()
		TicketSub.Lock()
		delete(TicketSub.Subscribers, user.UUID)
		TicketSub.Unlock()
	}()

	TicketSub.Lock()
	TicketSub.Subscribers[user.UUID] = events
	TicketSub.Unlock()

	return events, nil
}

func (r *queryRootResolver) SubscriptionTest(ctx context.Context) (err error) {
	id := uuid.New().String()
	notifyTicketStatusChange("e70e78bb-9d08-405d-a0ed-266ec703de19", id, fmt.Sprintf("Ticket (uuid=%s) status changed.", id))
	return
}

main.go

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	Start(ctx)

	// Wait for interrupt signal to gracefully shutdown the server with
	// a timeout of 10 seconds.
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs,
		os.Kill,
		os.Interrupt,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)
	<-sigs

	defer func() {
		cancel()
	}()

}

func Start(ctx context.Context) {
	go start(ctx)
}

func start(ctx context.Context) {
	cfg := gqlapi.Config{
		Resolvers: &resolvers.Resolver{},
		Directives: gqlapi.DirectiveRoot{
			Auth:    directives.Auth,
		},
	}
	r := mux.NewRouter()
	r.HandleFunc("/", handler.Playground("GraphQL playground", "/api/query"))

	upgrader := websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
		EnableCompression: true,
	}

	options := []handler.Option{
		handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
			// notify bug tracker...
			return fmt.Errorf("Internel server error.")
		}),
		handler.WebsocketUpgrader(upgrader),
	}

	r.HandleFunc("/api/query", handler.GraphQL(
		gqlapi.NewExecutableSchema(cfg),
		options...,
	))
	srv := &http.Server{
		Handler: r,              //
		Addr:    "0.0.0.0:4000", //
	}
	srv.SetKeepAlivesEnabled(true)
	log.Fatal(srv.ListenAndServeTLS("cert.pem", "key.pem"))
}

Screenshot from 2019-03-19 18 56 02

I can push message via websocket tunnel as you can see on the attached screenshot, but it closed after about 10-15 seconds.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 11
  • Comments: 24

Most upvoted comments

I solved the issue by lowering down the keepalive interval to 10s handler.WebsocketKeepAliveDuration(10*time.Second). The option name is a bit confusing. Probably, we should name it as WebsocketKeepAlivePingInterval instead?

Could you please add a recipe in https://gqlgen.com/ on how to use with Gin and gqlgen for subscriptions

This can be solved by setting WebsocketKeepAliveDuration = 0 .It works fine with local.

     queryHandler := corsAccess(handler.GraphQL(graph.NewExecutableSchema(
	 handler.WebsocketKeepAliveDuration(0),
	 handler.WebsocketUpgrader(websocket.Upgrader{
         CheckOrigin: func(request *http.Request) bool {
			return true
		},
		HandshakeTimeout: 5 * time.Second,
	}),
          ...
     )).

Still, get the issue in secure connection(i.e. Not work in wss://connection-URL)

I’m on 0.10.2 and I still need the option handler.WebsocketKeepAliveDuration(10*time.Second) to get subscriptions to not die after a few seconds (using Playground). Can we re-open this?

Seems like its still happening.

Testing with the chat example (not Gin), anything higher than handler.WebsocketKeepAliveDuration(19*time.Second) leads to the websocket connection being dropped in the GraphQL Playground.

Testing with my own app (Gin), I have the same experience.

It seems you need handler.WebsocketKeepAliveDuration() to be passed something less than 20 seconds in order to keep the websocket connection alive. Does gqlgen have to implement its own websocket ping/pong logic? I’m surprised this hasn’t caused lots of issues for anyone trying to do subscriptions? Do others have the same experience I report above?

Same issue! Is there a way to fix it? I have tried many different timeouts, none work.

Same issue here. I’ve tried a few of the above solutions, and what worked for me was handler.WebsocketKeepAliveDuration(10*time.Second).

Would probably be a good idea to update this.