Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Could not connect to websocket #640

Closed
mia0x75 opened this issue Mar 19, 2019 · 24 comments
Closed

Could not connect to websocket #640

mia0x75 opened this issue Mar 19, 2019 · 24 comments
Labels

Comments

@mia0x75
Copy link

mia0x75 commented Mar 19, 2019

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.

@JonnyWalker81
Copy link

I am seeing the same issue. Has there been any update about this issue?

@JulienBreux
Copy link

Hmm, and if you play with WebsocketKeepAliveDuration option? (Just by curiosity)

https://github.com/99designs/gqlgen/pull/529/files

@JonnyWalker81
Copy link

I tried playing with that function, but it seems to have the same behavior no matter what I set as the duration. I tried 40 then 100 (seconds) and got the same result: after about 30 seconds it would lose the connection after sending a 'ka' message (I saw the 'ka' in the messages section in the inspector for the request).

@ghost
Copy link

ghost commented May 15, 2019

Has anyone figured this out? I'm having the same issue. After 1 minute if no messages transmitted the error pops out:

Could not connect to websocket endpoint ws://localhost:5000/query. Please check if the endpoint url is correct.

@JonnyWalker81
Copy link

I was not able to figure it out, from the code it looks like it should work, but it seems to timeout. I had to setup my own Websocket handling code using Gorilla Websocket library, while it would have been nice to use subscriptions with the GQLGen library, using the Gorilla Websocket library is working out well so far.

@ghost
Copy link

ghost commented May 17, 2019

I've figured out that the problem with my code was having WebSocket and GraphQL handler on the same URL pattern.
My current hack is "duplicating" the ExecutableSchema on both HTTP and WS URL pattern. That works as expected. I'll probably have to refactor the code to fit this setting a bit it looks like a keeper.

My current code:

router.Handle("/", handler.Playground("GraphQL playground", "/query"))
	router.Handle("/query", handler.GraphQL(mailio.NewExecutableSchema(mailio.New(dtableSDK, awsSMTPSession, emailObserver, serverID))))
	router.Handle("/ws", handler.GraphQL(mailio.NewExecutableSchema(mailio.New(dtableSDK, awsSMTPSession, emailObserver, serverID)), handler.WebsocketUpgrader(websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	})))

I didn't dive into GqlGen code or Gorilla code but it might be Gorilla problem. Should be fairly easy to check.
In fact, I'm not even sure the same URL pattern with HTTP and WS should work by design?

@medcampus
Copy link

const DefaultConnectionKeepAlivePingInterval = 25 * time.Second

@Kichiyaki
Copy link

It's not the problem with gqlgen. I played with WebsocketKeepAliveDuration and in the case of WebsocketKeepAliveDuration greater than 20 seconds, the above error occurred. For example, for 15 seconds everything works as it should.
screen

@gurre
Copy link

gurre commented Jun 20, 2019

It's some protocol details that needs to be sorted.

I could not use github.com/alexanderGugel/wsd but curl worked fine:

curl -i --no-buffer -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost:8080" -H "Origin: http://localhost:8080" -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" -H "Sec-WebSocket-Version: 13" localhost:8080/graphql
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: qGEgH3En71di5rrssAZTmtRTyFk=
Sec-WebSocket-Protocol: graphql-ws

@guiguan
Copy link

guiguan commented Jun 27, 2019

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?

@AneriShah2610
Copy link

AneriShah2610 commented Jun 27, 2019

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)

@vektah
Copy link
Collaborator

vektah commented Aug 19, 2019

I think this was fixed by #820. Please reopen if not

@vektah vektah closed this as completed Aug 19, 2019
@vektah vektah added the v0.9.2 label Aug 19, 2019
@NickDubelman
Copy link

NickDubelman commented Aug 23, 2019

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?

@elge70
Copy link

elge70 commented Sep 24, 2019

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

@NickDubelman
Copy link

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?

@medcampus
Copy link

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

could you please update on this

@ajoseps
Copy link

ajoseps commented Apr 15, 2020

I might have a similar issue #1150. It seems like when it's time to write a message, gorilla websockets returns an error indicating websocket: close sent but the client never sent a close and I believe gqlgen didn't either.

@jay-khatri
Copy link

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.

@alan-ma-umg
Copy link

Had same issue, only the following work-around works. We need to have a better solution:

handler.GraphQL(
		generated.NewExecutableSchema(generated.Config{Resolvers: r}),
		handler.WebsocketKeepAliveDuration(10*time.Second),
	)

@voodoo-dn
Copy link

voodoo-dn commented May 31, 2020

Hi. The same problem. I have middleware which go to user service and auth user by token.
If this middleware disabled(middleware returns hardcoded user) - subscription works well.
If "time.Sleep(1 * time.Second)" added to middleware - subscription not works.

gqlgen version v0.11.3
server.AddTransport(transport.Websocket{ KeepAlivePingInterval: 10 * time.Second, })

{ "error": "Could not connect to websocket endpoint ws://localhost:9090/graphql. Please check if the endpoint url is correct." }

@Kichiyaki
Copy link

Gqlgen can't do much about it. Playground (used by gqlgen) uses a subscription client from this package. It has built-in inactivity timeout (for prisma playground it's 20 seconds).

The only way to fix it is to set KeepAlivePingInterval between 1 and 15 seconds.

@jomag
Copy link

jomag commented Dec 16, 2020

Still the same issue in 0.13.0. Only for secure (wss) connections. I'm using NewDefaultServer which sets KeepAlivePingInterval to 10 seconds. I get 3 keep-alives and then the connection is closed.

@Jmoore1127
Copy link

Still seeing this issue as well in 0.13.0. This should probably be reopened.

@RobertoOrtis
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests