igm / sockjs-go

WebSocket emulation - Go server library
BSD 3-Clause "New" or "Revised" License
515 stars 100 forks source link

sockjs server not working with gorilla/websocket #47

Open ShawnMilo opened 8 years ago

ShawnMilo commented 8 years ago

I have an existing Go application which uses gorilla/websocket. I also have a test suite written in Go which uses gorilla/websocket's websocket.Dialer to connect to an instance of the application and exercise a bunch of functionality. This all works.

I replaced gorilla/websocket with sockjs in the application. Now my test client, using gorilla/websocket can no longer connect to it. I always get bad handshake. My actual handler never gets called -- I have a log statement as the first line, and it never logs anything.

I've tried these variations:

socketJSHandler := sockjs.NewHandler("/chat", sockjs.DefaultOptions, socketHandler)
socketJSHandler := sockjs.NewHandler("/", sockjs.DefaultOptions, socketHandler)
socketJSHandler := sockjs.NewHandler("/chat/", sockjs.DefaultOptions, socketHandler)

I've also tried using custom options instead of the defaults.

On the client side, I've tried to connect to:

ws://ip_address:9999/
ws://ip_address:9999/chat
ws://ip_address:9999/chat/
ws://ip_address:9999/chat/websocket
ws://ip_address:9999/chat/websocket/

http://ip_address:9999/
http://ip_address:9999/chat
http://ip_address:9999/chat/
http://ip_address:9999/chat/websocket
http://ip_address:9999/chat/websocket/

So, my socketHandler function never gets called, and gorilla/websockets gets a "bad handshake" message every time I connect to sockjs. I'm using the same version of gorilla/websockets in all places.

Am I doing something wrong, or is this possibly a bug?

igm commented 8 years ago

Could please provide a test suite you are using so that I can see exactly what is not working? However what I'd like to emphasize is that sockjs is not the same as websockets. Sockjs is not meant to be a compatible substitute for websockets. Sockjs uses it's own framing protocol (that works on top of websockets).

ShawnMilo commented 8 years ago

Wow, I never got notified of your reply. :cry: Thanks for replying so soon after.

My test suite is something I wrote using Gorilla websockets, which I see is what sockjs-go is using.

Here's what I used to do:

  1. Go server app, using Gorilla websockets.
  2. Test app written in Go, using Gorilla websockets.

Test app creates websocket connections to the server and tests functionality.

However, now that the server application uses Gorilla websockets via sockjs-go, the client Go app (using Gorilla websockets) is unable to connect. What library do I have to use to fix that? If sockjs-go is compatible with websockets if a browser supports them, then why isn't it possible to make a "normal" websocket connection to a server running sockjs-go?

Thanks again for the reply.

igm commented 8 years ago

sockjs uses various protocols to communicate between client and server (including websocket). However sockjs uses its own framing on top of it. So that's why it is not compatible with "raw websocket" clients. If you need to expose raw websocket on the server, then use one of the available websocket libraries (eg. gorilla's websocket). Exposing raw webosocket endpoint is something this library for GO does not solve (see also #11). Also you can have a look at the protocol test here https://github.com/igm/sockjs-go/blob/master/testserver/server.go to see how raw websocket can be added to the server, just add additional websocket endpoint to your server.

ShawnMilo commented 8 years ago

Thanks, @igm. I figured out I could duplicate and maintain two copies of my connection code in the app and serve on an additional port for testing. It's something I'd much rather avoid if possible, because I have to perfectly keep two code paths in sync without being able to test one of them, and on top of that, the one I can't test is the one that's going to run in production. It may come to this, but it has a smell.

I think it would be best all around if this project would just recognize a standard websocket connection. I'm willing to put in the work. Since you're the expert on the codebase, do you have any recommendations for how I should approach this? Or is there something about the architecture that you think makes it not worth the effort?