mashupbots / socko

A Scala web server powered by Netty networking and AKKA processing.
Other
255 stars 51 forks source link

Support for Websocket fallbacks #82

Closed chiappone closed 10 years ago

chiappone commented 10 years ago

Do you plan on having any support for either flash socket or long polling fallbacks for websockets with older browsers?

veebs commented 10 years ago

Unfortunately not. I haven't go the time. Pull requests are always welcomed!

simbo1905 commented 10 years ago

You don't need anything special for polling fallback for websockets. Checkout this socko app https://github.com/simbo1905/planning-poker/tree/v0.10 which uses jquery.gracefulWebSocket.js to fallback to ajax polling when the browser does not have websockets. By default the jquery.gracefulWebSockets.js looks to see if the websockets object is defined and if not creates a fake one which polls. The socko routes in ScrumPokerApp.scala takes a POST when the browser sends a message at line 122 and takes a GET when the browser is polling for new updates at line 161. This works with IE9 and Android 2.3.3 which don't support websockets so you can test that app out with firefox, safari, chrome, IE9, Android 2.3.3 playing the same game with some browsers using websockets and some falling back to ajax.

The hardest part of not having native websockets support is that you need to buffer data for the next browser poll. This means you need to create a session actor for the user which you empty in response to the next post or get. The class PollingPlayerActor does that. Polling is a real pain as you need your own form of application level session management to buffer for the next poll then to timeout that session if the browser does an unclean exit so that you dont have a leak.

The original jquery.gracefulWebSockets.js looks to see if the browser supports websockets alone. I patched that file to be able to force a fallback to ajax if the application detects that websockets are not opening due to a corporate webproxy not supporting websockets. To do this planning-poker-protocol.js at line 86 tries to be smart and work out if the websocket onclose has been called when the onopen never happened. In which case it reloads of the page specifying to use the fallback of ajax polling. This means that you can use the latest chrome or firefox behind a corporate proxy which does not handle the websockets handshake and the browser will fallback to polling.

Enjoy.

simbo1905 commented 10 years ago

Oh one more thing to watch out for. Websockets are amazingly efficient. If a load of folks leave their browser open doing nothing for days you don't pay for much bandwidth or cpu. If someone is using the fallback script and leaves a browser open all week doing nothing they they will leech your bandwidth with the GET request headers. To handle that the demo app above has an application level timeout for the entire room. When that happens it destroys the room and all the PollingPlayerActors and sends a 'close' message to the browser which causes the browser to call close on the fake websocket to stop the polling.

Well having said you don't need anything special to do fallback that was a lot of information about how to handle it properly! IMHO I don't see how socko could handle this transparently for an application due to some of the things I mentioned and the amount of testing required to ensure that the application doesn't have a leak means that its not unreasonable for the application to have to handle things. With Android KitKat and IE10 now supporting websockets hopefully we are only one 3 year hardware refresh cycle from universal support and the techniques above will no longer be required.

chiappone commented 10 years ago

Thanks for the info.