gruis / sinatra-websocket

Makes it easy to upgrade any request to a websocket connection in Sinatra
https://rubygems.org/gems/sinatra-websocket
Other
230 stars 31 forks source link

Showoff app works locally, fails on heroku #15

Open donv opened 9 years ago

donv commented 9 years ago

Hi!

I have an app at with source at

https://github.com/donv/ruby_for_java_developers

running at

http://ruby-for-java.herokuapp.com/

When users connect, a websocket should be opened to enable a follow mode if the user presses the g key.

However, when users now connect, the websocket request fails on the server with error 500. Any idea what could be wrong?

2015-04-13T13:15:36.559242+00:00 heroku[router]: at=info method=GET path="/control" host=ruby-for-java.herokuapp.com request_id=022698ff-1d78-44ac-9532-bdd778b8a0cf fwd="139.112.1.135" dyno=web.1 connect=3ms service=3ms status=500 bytes=222
2015-04-13T13:15:36.558146+00:00 app[web.1]: 2015-04-13 13:15:36 - SinatraWebsocket::Error::ConfigurationError - Could not find an async callback in our environment!:
2015-04-13T13:15:36.558150+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-websocket-0.3.1/lib/sinatra-websocket.rb:16:in `from_env'
2015-04-13T13:15:36.558152+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-websocket-0.3.1/lib/sinatra-websocket/ext/sinatra/request.rb:17:in `websocket'
2015-04-13T13:15:36.558154+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/showoff-0.9.10.8/lib/showoff.rb:1135:in `block in <class:ShowOff>'
2015-04-13T13:15:36.558155+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1610:in `call'
2015-04-13T13:15:36.558156+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1610:in `block in compile!'
2015-04-13T13:15:36.558158+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:974:in `[]'
2015-04-13T13:15:36.558159+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:974:in `block (3 levels) in route!'
2015-04-13T13:15:36.558161+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:993:in `route_eval'
2015-04-13T13:15:36.558162+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:974:in `block (2 levels) in route!'
2015-04-13T13:15:36.558163+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1014:in `block in process_route'
2015-04-13T13:15:36.558167+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1012:in `catch'
2015-04-13T13:15:36.558169+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1012:in `process_route'
2015-04-13T13:15:36.558170+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:972:in `block in route!'
2015-04-13T13:15:36.558171+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:971:in `each'
2015-04-13T13:15:36.558172+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:971:in `route!'
2015-04-13T13:15:36.558174+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1084:in `block in dispatch!'
2015-04-13T13:15:36.558175+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
2015-04-13T13:15:36.558176+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
2015-04-13T13:15:36.558177+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
2015-04-13T13:15:36.558178+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1081:in `dispatch!'
2015-04-13T13:15:36.558180+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `block in call!'
2015-04-13T13:15:36.558181+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `block in invoke'
2015-04-13T13:15:36.558182+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `catch'
2015-04-13T13:15:36.558183+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:1066:in `invoke'
2015-04-13T13:15:36.558184+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:906:in `call!'
2015-04-13T13:15:36.558186+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:894:in `call'
2015-04-13T13:15:36.558187+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
2015-04-13T13:15:36.558188+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb:16:in `call'
2015-04-13T13:15:36.558189+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
2015-04-13T13:15:36.558191+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
2015-04-13T13:15:36.558192+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
2015-04-13T13:15:36.558193+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
2015-04-13T13:15:36.558195+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-1.6.0/lib/rack/logger.rb:15:in `call'
2015-04-13T13:15:36.558196+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/rack_patch.rb:13:in `call'
2015-04-13T13:15:36.558197+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:218:in `call'
2015-04-13T13:15:36.558198+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:211:in `call'
2015-04-13T13:15:36.558199+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-1.6.0/lib/rack/head.rb:13:in `call'
2015-04-13T13:15:36.558201+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/rack-1.6.0/lib/rack/methodoverride.rb:22:in `call'
2015-04-13T13:15:36.558202+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:181:in `call'
2015-04-13T13:15:36.558203+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/sinatra-1.4.6/lib/sinatra/base.rb:2021:in `call'
2015-04-13T13:15:36.558204+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/configuration.rb:51:in `call'
2015-04-13T13:15:36.558205+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/server.rb:507:in `handle_request'
2015-04-13T13:15:36.558211+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/server.rb:375:in `process_client'
2015-04-13T13:15:36.558212+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/server.rb:262:in `block in run'
2015-04-13T13:15:36.558213+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/thread_pool.rb:104:in `call'
2015-04-13T13:15:36.558214+00:00 app[web.1]:    /app/vendor/bundle/ruby/2.0.0/gems/puma-2.11.2/lib/puma/thread_pool.rb:104:in `block in spawn_thread'
2015-04-13T13:15:36.558463+00:00 app[web.1]: 139.112.1.135 - - [13/Apr/2015:13:15:36 +0000] "GET /control HTTP/1.1" 500 30 0.0007
gruis commented 9 years ago

It looks like you're using a web server that doesn't support async callbacks:

2015-04-13 13:15:36 - SinatraWebsocket::Error::ConfigurationError - Could not find an async callback in our environment!:

I've been using Thin. I think a few other servers are supported, but it seems that puma is not one of them.

donv commented 9 years ago

Ah, I see. Thank you. What server is used when I do showoff serve?

gruis commented 9 years ago

https://github.com/simulacre/sinatra-websocket/blame/master/README.md#L15

It uses Thin.

donv commented 9 years ago

Thanks @simulacre ! Indeed, it uses Thin locally and works well. I still want to explore using puma and see if it can work, before switching to Thin if necessary.

I did find this issue that (if I read it correctly) states that puma 2 supports async callbacks.

https://github.com/puma/puma/issues/3

But sinatra+puma don't work together?

gruis commented 9 years ago

It looks like Puma uses an different internal API for streaming than what the sinatra-websocket code is expecting. It should be possible to make it work, but I haven't looked at the Puma code in detail yet.

kethomassen commented 9 years ago

@simulacre Please look into it - want to upgrade for better performance and concurrency but can't while I'm using this :|

gruis commented 9 years ago

@kethomassen if you setup your Profile to use Thin it should work on Heroku. I tested the showoff app just now on Heroku and had no problems.

https://github.com/simulacre/sinatra-websocket/pull/19/files#diff-5bd6b85c2d6fc987875f4bf82de2a15aR1

kethomassen commented 9 years ago

@simulacre I was meaning looking into Puma support, I want to use it over Thin for the improvements it has.

jficz commented 1 year ago

Not relevant for Heroku but similar problem happens when running showoff behind a nginx-based revese proxy. A workaround exists: https://github.com/gruis/sinatra-websocket/issues/23#issuecomment-1594319679