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

WebSocket + Falcon + Rack middlewares using BodyProxy = No async task available! #34

Closed
u3shit opened this issue Dec 22, 2021 · 2 comments

Comments

@u3shit
Copy link

u3shit commented Dec 22, 2021

I'm trying to create a websocket server in a Rack application, unfortunately it looks like any middleware that uses BodyProxy (for example CommonLogger or Lint) break the websocket support.

require 'async/websocket/adapters/rack'
require 'rack'

app = lambda do |env|
  Async::WebSocket::Adapters::Rack.open(env) do |connection|
    message = connection.read
    connection.write message.reverse
  end
end

app = Rack::CommonLogger.new app
Rack::Handler.get('falcon').run app, Port: 9999

Trying to connect to this server results in:

 1.39s    error: Async::Task [oid=0x280] [ec=0x294] [pid=27023] [2021-12-22 17:40:57 +0100]
               |   ArgumentError: wrong number of arguments (given 1, expected 0)
               |   → /home/u3/.gem/ruby/3.0.0/gems/async-io-1.32.2/lib/async/io/stream.rb:216 in `close'
               |     /home/u3/.gem/ruby/3.0.0/gems/protocol-http-0.22.5/lib/protocol/http/body/readable.rb:75 in `ensure in call'
               |     /home/u3/.gem/ruby/3.0.0/gems/protocol-http-0.22.5/lib/protocol/http/body/readable.rb:75 in `call'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-http-0.56.5/lib/async/http/protocol/http1/server.rb:82 in `each'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-http-0.56.5/lib/async/http/server.rb:53 in `accept'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-io-1.32.2/lib/async/io/server.rb:32 in `block in accept_each'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-io-1.32.2/lib/async/io/socket.rb:73 in `block in accept'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-1.30.1/lib/async/task.rb:260 in `block in make_fiber'
               |   Caused by RuntimeError: No async task available!
               |   → /home/u3/.gem/ruby/3.0.0/gems/async-1.30.1/lib/async/task.rb:189 in `current'
               |     /home/u3/.gem/ruby/3.0.0/gems/async-http-0.56.5/lib/async/http/body/hijack.rb:78 in `read'
               |     /home/u3/.gem/ruby/3.0.0/gems/protocol-http-0.22.5/lib/protocol/http/body/readable.rb:86 in `each'
               |     /home/u3/.gem/ruby/3.0.0/gems/rack-2.2.3/lib/rack/body_proxy.rb:41 in `method_missing'
               |     test.rb:in `each' 

This does not happen if I remove the app = Rack::CommonLogger.new app line.

Falcon::Adapter::Output does a @body.to_enum(:each) which creates a Fiber internally, but it won't be an async fiber, hence the error. (Without BodyProxy, falcon can somehow figure out the response is a Hijack and it doesn't even create an Output from what can I tell.) Any idea what to do with this? (I'm trying to port an app using EventMachine+thin+faye-websocket, there this configuration worked without problems.)
P.s. the rack server example doesn't seem to work for me, it throws an undefined method `run' for main:Object error in an infinite loop for me.

@ioquatix
Copy link
Member

I believe Rack 3.0 will fix this problem, but let me investigate.

@ioquatix
Copy link
Member

We have merged the streaming proposal so Rack 3 will work correctly, even from within Rails, but it will take some time for this change to work it's way through the eco-system.

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

No branches or pull requests

2 participants