Giter VIP home page Giter VIP logo

reel's Introduction

Reel

Gem Version MIT licensed Build Status Maintained: no

"A dizzying lifetime... reeling by on celluloid" -- Rush / Between The Wheels

Reel is a fast, non-blocking "evented" web server built on http_parser.rb, websocket-driver, Celluloid::IO, and nio4r. Thanks to Celluloid, Reel also works great for multithreaded applications and provides traditional multithreaded blocking I/O support too.

Connections to Reel can be either non-blocking and handled entirely within the Reel::Server thread (handling HTTP, HTTPS, or UNIX sockets), or the same connections can be dispatched to worker threads where they will perform ordinary blocking IO. Reel provides no built-in thread pool, however you can build one yourself using Celluloid.pool, or because Celluloid already pools threads to begin with, you can simply use an actor per connection.

This gives you the best of both worlds: non-blocking I/O for when you're primarily I/O bound, and threads for where you're compute bound.

Is it any good?

Yes

Documentation

Please see the Reel Wiki for detailed documentation and usage notes.

YARD documentation is also available.

Framework Adapters

Rack

A Rack adapter for Reel is available at:

https://github.com/celluloid/reel-rack

Webmachine

The most notable library with native Reel support is webmachine-ruby, an advanced HTTP framework for Ruby with a complete state machine for proper processing of HTTP/1.1 requests. Together with Reel, Webmachine provides full streaming support for both requests and responses.

To use Reel with Webmachine, add the following to your Gemfile:

gem 'webmachine', git: 'git://github.com/seancribbs/webmachine-ruby.git'

Then use config.adapter = :Reel when configuring a Webmachine app, e.g:

MyApp = Webmachine::Application.new do |app|
  app.routes do
    add ['*'], MyHome
  end

  app.configure do |config|
    config.ip      = MYAPP_IP
    config.port    = MYAPP_PORT
    config.adapter = :Reel

    # Optional: handler for incoming websockets
    config.adapter_options[:websocket_handler] = proc do |websocket|
      # websocket is a Reel::WebSocket
      websocket << "hello, world"
    end
  end
end

MyApp.run

See the Webmachine documentation for further information

Ruby API

Reel aims to provide a "bare metal" API that other frameworks (such as Rack and Webmachine) can leverage. This API can also be nice in performance critical applications.

Block Form

Reel lets you pass a block to initialize which receives connections:

require 'celluloid/autostart'
require 'reel'

Reel::Server::HTTP.supervise("0.0.0.0", 3000) do |connection|
  # Support multiple keep-alive requests per connection
  connection.each_request do |request|
    # WebSocket support
    if request.websocket?
      puts "Client made a WebSocket request to: #{request.url}"
      websocket = request.websocket

      websocket << "Hello everyone out there in WebSocket land"
      websocket.close
    else
      puts "Client requested: #{request.method} #{request.url}"
      request.respond :ok, "Hello, world!"
    end
  end
end

sleep

When we read a request from the incoming connection, we'll either get back a Reel::Request object, indicating a normal HTTP connection, or a Reel::WebSocket object for WebSockets connections.

Subclass Form

You can also subclass Reel, which allows additional customizations:

require 'celluloid/autostart'
require 'reel'

class MyServer < Reel::Server::HTTP
  def initialize(host = "127.0.0.1", port = 3000)
    super(host, port, &method(:on_connection))
  end

  def on_connection(connection)
    connection.each_request do |request|
      if request.websocket?
        handle_websocket(request.websocket)
      else
        handle_request(request)
      end
    end
  end

  def handle_request(request)
    request.respond :ok, "Hello, world!"
  end

  def handle_websocket(sock)
    sock << "Hello everyone out there in WebSocket land!"
    sock.close
  end
end

MyServer.run

Supported Ruby Versions

This library supports and is tested against the following Ruby versions:

  • Ruby (MRI) 2.0, 2.1, 2.2, 2.3
  • JRuby 9000

Contributing

  • Fork this repository on GitHub
  • Make your changes and send us a pull request
  • If we like them we'll merge them
  • If we've accepted a patch, feel free to ask for commit access

License

Copyright (c) 2012-2016 Tony Arcieri. Distributed under the MIT License. See LICENSE.txt for further details.

reel's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reel's Issues

SSLServer responses hang and/or do not render.

Similar to #80 if not the same.

Only able to use Curl and Safari so far, with Chrome and Firefox only working for a single pageload, some of the time. That single working pageload is usually a small icon, such a favicon.ico and nothing more. As I said, Safari and Curl work great... including Secure Web Sockets ( well, Safari at least ).

On Chrome and Firefox, usually/always the server hangs, even if refreshing that favicon.ico which previously worked ( once every few minutes ), and it needs to be stopped on the browser side. On the server side, a busy worker remains.

I inserted some debug output points, and I see that when the SSL server hangs, it is pipelining, and hanging on the second request on the connection... however there was never a first request to process! Safari and Curl show no pipelining.

Infinite wait for `defer { IO.copy_stream }` on files larger than X.

One of the #90 twins.

If one repeatedly refreshes an asset such as /favicon.ico this behavior will not happen. Apparently it is of a certain size where its contents transfer immediately with no interruption. But if there is an asset of a certain amount of size X which is an unknown number right now, it will infinitely wait to fully copy from source to destination.

The main cause I could foresee would be the defer { } operation never having the opportunity to complete. How can this be diagnosed and solved?

Reel 0.3.0 crashing with HTTP gem 0.5.0

gems/reel-0.3.0/lib/reel/request.rb:12:in `class:Request': uninitialized constant HTTP::METHODS (NameError)

This may be fixed in master … will try to test shortly.

'stop' method for Rack::Handler::Reel

NoMethodError: undefined method `stop' for #<Rack::Handler::Reel:0x29874744>

Shutting down a Rack-based implementation of Reel with Ctrl-C, the above fires, so there is no graceful shutdown... even though the previous line in the console is Terminating # actors...

Tried adding this tp Rack::Handler::Reel, but it doesn't seem to help:

def self.stop
  ::Reel::Server.terminate
end

OptionParser missing

Ruby 1.9.3-p194. Reel-0.3.0.

$reel -r config.ru
D, [2012-12-27T14:27:25.129315 #27251] DEBUG -- : Terminating 4 actors...
D, [2012-12-27T14:27:25.130058 #27251] DEBUG -- : Shutdown completed cleanly
/home/serg/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/reel-0.3.0/bin/reel:7:in <top (required)>': uninitialized constant OptionParser (NameError) from /home/serg/.rbenv/versions/1.9.3-p194/bin/reel:23:inload'
from /home/serg/.rbenv/versions/1.9.3-p194/bin/reel:23:in `

'

Can be fixed by adding "require 'optparse'" to the ..../bin/reel file.

Celluloid.defer { IO.copy_stream } transfers getting squashed?

This is proving hard to debug, and hard to prove, but @socket's with IO copies being performed have a tendency to squash responses.

For example, a static file being transferred to a browser will intermittently return nil and not show any error. So, rather than getting an essential .js file, you'll get an empty response and a browser will crash.

First of all, how can this be more clearly debugged, and then how can this be avoided without removing the Celluloid.defer {} call. It seems much faster with that call in place, now it just needs to be stable.

Cannot execute blocks on sender in exclusive mode

require 'bundler/setup'
require 'reel'
require 'celluloid'

class A
  include Celluloid

  def run
    exclusive { start_server }
  end

  def start_server
    @server = Reel::Server.supervise('127.0.0.1', 12345) do |connection|
      while request = connection.request
        connection.respond(Reel::Response.new(:ok, "Hello world"))
      end
    end
  end
end

a = A.new
a.run

sleep
D, [2013-08-12T02:31:09.789693 #19693] DEBUG -- : Terminating 5 actors...
E, [2013-08-12T02:31:09.790925 #19693] ERROR -- : A crashed!
RuntimeError: Cannot execute blocks on sender in exclusive mode
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:11:in `initialize'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:58:in `initialize'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:20:in `new'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:20:in `method_missing'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/legacy.rb:14:in `method_missing'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/actor_proxy.rb:25:in `_send_'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:129:in `new'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/supervisor.rb:10:in `supervise'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:148:in `supervise'
    12.rb:13:in `start_server'
    12.rb:9:in `block in run'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:208:in `exclusive'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:452:in `exclusive'
    12.rb:9:in `run'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `public_send'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `dispatch'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:67:in `dispatch'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:326:in `block in handle_message'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:42:in `block in initialize'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11:in `block in create'
    (celluloid):0:in `remote procedure call'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:95:in `value'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:28:in `method_missing'
    /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/legacy.rb:14:in `method_missing'
    12.rb:22:in `<main>'
D, [2013-08-12T02:31:09.798722 #19693] DEBUG -- : Shutdown completed cleanly
/home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:11:in `initialize': Cannot execute blocks on sender in exclusive mode (RuntimeError)
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:58:in `initialize'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:20:in `new'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:20:in `method_missing'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/legacy.rb:14:in `method_missing'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/actor_proxy.rb:25:in `_send_'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:129:in `new'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/supervisor.rb:10:in `supervise'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:148:in `supervise'
    from 12.rb:13:in `start_server'
    from 12.rb:9:in `block in run'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:208:in `exclusive'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid.rb:452:in `exclusive'
    from 12.rb:9:in `run'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `public_send'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:25:in `dispatch'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:67:in `dispatch'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/actor.rb:326:in `block in handle_message'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/tasks.rb:42:in `block in initialize'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/tasks/task_fiber.rb:11:in `block in create'
    from (celluloid):0:in `remote procedure call'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/calls.rb:95:in `value'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/proxies/sync_proxy.rb:28:in `method_missing'
    from /home/kostya/.rvm/gems/ruby-2.0.0-p0/gems/celluloid-0.14.1/lib/celluloid/legacy.rb:14:in `method_missing'
    from 12.rb:22:in `<main>'

0.13.0 works

SSE Example requires config.ru

Hey,

I am abit new to this and was trying to run your example for Server Side Events, and everytime i try to run it its looking for a config.ru which isn't provided in the example

am I missing something here?

i m getting these.. can anyone help

foreman start
14:59:30 ahn.1  | started with pid 3536
14:59:30 web.1  | started with pid 3539
14:59:39 ahn.1  | Starting Adhearsion server at /home/kaus/fosdem2013-master/ahn
14:59:40 ahn.1  | /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/reel-0.3.0/lib/reel.rb:6:in `require': cannot load such file -- celluloid/autostart (LoadError)
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/reel-0.3.0/lib/reel.rb:6:in `<top (required)>'
14:59:40 ahn.1  |   from /home/kaus/fosdem2013-master/ahn/lib/request_handler.rb:1:in `require'
14:59:40 ahn.1  |   from /home/kaus/fosdem2013-master/ahn/lib/request_handler.rb:1:in `<top (required)>'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:163:in `require'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:163:in `block (2 levels) in load_lib_folder'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:162:in `each'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:162:in `block in load_lib_folder'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:160:in `chdir'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:160:in `load_lib_folder'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:42:in `start'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/initializer.rb:12:in `start'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/cli_commands.rb:120:in `start_app'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/adhearsion-2.2.1/lib/adhearsion/cli_commands.rb:59:in `start'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/thor-0.17.0/lib/thor/task.rb:27:in `run'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/thor-0.17.0/lib/thor/invocation.rb:120:in `invoke_task'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/thor-0.17.0/lib/thor.rb:344:in `dispatch'
14:59:40 ahn.1  |   from /home/kaus/.rvm/gems/ruby-1.9.3-p392/gems/thor-0.17.0/lib/thor/base.rb:434:in `start'
14:59:40 ahn.1  |   from script/ahn:9:in `<main>'
14:59:40 ahn.1  | exited with code 1
14:59:40 system | sending SIGTERM to all processes
SIGTERM received
14:59:40 web.1  | >> Thin web server (v1.5.0 codename Knife)
14:59:40 web.1  | >> Maximum connections set to 1024
14:59:40 web.1  | >> Listening on 0.0.0.0:3000, CTRL+C to stop
14:59:40 web.1  | terminated by SIGTERM

Websocket hangs when >64 KiB packet is sent across it [Windows only]

(Cross-posting of jeremyd/celluloid-websocket-client#10 since I honestly don't know if this is a server or client issue.)

As the subject says, I'm seeing really, really weird behavior with the celluloid-websocket-client. It seems like a "big packet" (bigger than 64 KiB) somehow breaks the socket, making is malfunction and not receive any more packets.

This is with JRuby on Windows. On OSX, everything works as it should, both with small and big packets.

More specifically, these are the exact scenarios (quoting https://github.com/perlun/celluloid-websocket-client/blob/big_packets_bug/examples/roundtrip_client.rb#L19):

if ARGV[0] == 'small'
  # Packets less than 64 KiB, using 16-bit payload length.
  #
  # Works, both on Windows (client + server) and OSX (client + server). No problems encountered with this packet size.
  msg = '123456' * 10000
elsif ARGV[0] == 'big'
  # Packets bigger than 64 KiB, triggering a 64-bit payload length (RFC 6455, section 5.2, "Payload length")
  #
  # Works on OSX client + server
  # Fails on Windows client + server (crashes the websocket so that we never get any response on the second packet either).
  # Fails on Windows client + OSX server (likewise).
  # Fails on Windows server + OSX client (likewise).
  msg = '123456' * 100000
end

To be able to properly isolate the issue, I've made a small test suite which reproduces it. You can find it here: https://github.com/perlun/celluloid-websocket-client/tree/big_packets_bug

(clone my repo and checkout the big_packets_bug branch.)

Run the server like this (after bundle install --standalone etc), in two different windows:

jruby --1.9 -Ilib examples/roundtrip.rb # this starts the (Reel) server
jruby --1.9 -Ilib examples/roundtrip_client.rb # surprisingly enough, this starts the client...

I'm amazed and really don't have any clues as to what's happening. I've looked a bit at both ends, trying to insert puts statements here and there but any constructive feedback would be incredibly helpful here. Naturally, I'll gladly help out with the debugging of this issue..

Many thanks in advance.

Connection Reset or Connection Timeout when benchmarking with AB

In my initial testing of Reel, I used the example subclasses server to see what kind of reqs/sec I could do on my dev machine.

Here's the Reel server: https://gist.github.com/multiplegeorges/4fe3b4ed0f30b298bdd4

I am testing with ab like so:

ab -n 10000 -c 10 http://localhost:3000/

and the set of connections rarely finishes. It will often hit 6000+ and all remaining connections will time out.

But, I am also seeing connection reset errors very often: https://gist.github.com/multiplegeorges/285a3460d0cba9c78f86

Note: nothing changed between those ab runs. I left the Reel server running and just tried again.

Rubies tested: jruby 1.7.4, mri 1.9.3.

What am I missing here?

rackup - Reel fail to start when specifying the number of workers using the -O switch

it's a small fix, I'll submit a patch

bundle exec rackup -s reel  -O 'workers=12'
I, [2013-05-06T23:06:13.125833 #65831]  INFO -- : A Reel good HTTP server!
I, [2013-05-06T23:06:13.125977 #65831]  INFO -- : Listening on 0.0.0.0:9292
E, [2013-05-06T23:06:13.127846 #65831] ERROR -- : Celluloid::PoolManager crashed!
ArgumentError: comparison of String with 2 failed
    /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/pool_manager.rb:14:in `<'
    /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/pool_manager.rb:14:in `initialize'
    /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/calls.rb:11:in `public_send'
    /Users/eran/.rvm/Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/pool_manager.rb:14:in `<': comparison of String with 2 failed (ArgumentError)
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/pool_manager.rb:14:in `initialize'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/calls.rb:11:in `public_send'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/calls.rb:11:in `dispatch'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/calls.rb:63:in `dispatch'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/actor.rb:326:in `block in handle_message'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:28:in `block in initialize'
    from (celluloid):0:in `remote procedure call'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/actor.rb:69:in `call'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid/proxies/actor_proxy.rb:26:in `_send_'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid.rb:104:in `new'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/celluloid-0.13.0/lib/celluloid.rb:138:in `pool'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/reel-0.3.0/lib/rack/handler/reel.rb:40:in `start'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/reel-0.3.0/lib/rack/handler/reel.rb:26:in `run'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/rack-1.5.2/lib/rack/server.rb:264:in `start'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/rack-1.5.2/lib/rack/server.rb:141:in `start'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/gems/rack-1.5.2/bin/rackup:4:in `<top (required)>'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/bin/rackup:19:in `load'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/bin/rackup:19:in `<main>'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/bin/ruby_noexec_wrapper:14:in `eval'
    from /Users/eran/.rvm/gems/ruby-1.9.3-p392@webserver-bench/bin/ruby_noexec_wrapper:14:in `<main>'

SSLServer responses demand explicit Content-Type

I am implementing SSLServer. So far it has bolted-on to the existing environment I have really well, but there is one issue to resolve. It might be in my own use case but it seems to be general, or theoretical.

Responses are being interpreted as plaintext on Chrome and Safari, do not seem to resolve at all under Firefox ( both on Mac OS X 10.7 )... unless Content-Type: text/html is explicitly set on the response.

Adding a Content-Type causes proper behavior, and that includes specifying a MIME type for static files. Ought this be included in Response itself?

NameError: uninitialized constant Reel::RequestBody::StateError

I'm pretty new to Reel/Celluloid so mind my potentially amateur bug report. I'm attempting to create a small HTTP proxy server use Reel + The HTTP Gem

Below is my entire app and it's constantly crashing with the stack trace below it.

require 'celluloid'
require 'celluloid/io'
require 'reel'
require 'http'

class HttpProxy
  include Celluloid::IO

  def initialize(url)
    @url = url
  end

  def request(verb, uri, options={})
    url = "#{@url}#{uri}"
    options = options.merge({ssl_socket_class: Celluloid::IO::SSLSocket})
    HTTP.request(verb, url, options).response
  end

end

class Server < Reel::Server
  def initialize(host = "127.0.0.1", port = 5000)
    super(host, port, &method(:on_connection))
  end

  def on_connection(connection)
    connection.each_request do |request|
      if request.websocket?
        handle_websocket(request)
      else
        handle_request(request)
      end
    end
  end

  def handle_request(request)
    uri = "#{request.uri}"
    uri = "#{uri}?#{request.query_string}" unless request.query_string.nil?
    uri = "#{uri}##{request.fragment}" unless request.fragment.nil?
    options = {}
    options[:headers] = request.headers unless request.headers.nil?
    options[:body] = request.body unless request.body.nil?

    puts "proxying: #{request.method} #{uri} #{request.headers} #{request.body}"

    @proxy ||= HttpProxy.new('https://api.parse.com/2')
    request.respond @proxy.request(request.method, uri, options)
  end

  def handle_websocket(sock)
    sock.close
  end
end

Server.run
NameError: uninitialized constant Reel::RequestBody::StateError
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/request_body.rb:52:in `stream!'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/request_body.rb:20:in `readpartial'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/request_body.rb:26:in `each'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/request_stream.rb:68:in `send_request_body'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/request_stream.rb:31:in `stream'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/request.rb:68:in `stream'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/client.rb:79:in `perform'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/client.rb:58:in `request'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/http-0.5.0/lib/http/chainable.rb:50:in `request'
    /Users/robertjpayne/Desktop/app.rb:16:in `request'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:25:in `public_send'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:25:in `dispatch'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:67:in `dispatch'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/actor.rb:322:in `block in handle_message'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/actor.rb:416:in `block in task'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/tasks.rb:55:in `block in initialize'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/tasks/task_fiber.rb:13:in `block in create'
    (celluloid):0:in `remote procedure call'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:92:in `value'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/proxies/sync_proxy.rb:33:in `method_missing'
    /Users/robertjpayne/Desktop/app.rb:47:in `handle_request'
    /Users/robertjpayne/Desktop/app.rb:31:in `block in on_connection'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/connection.rb:74:in `each_request'
    /Users/robertjpayne/Desktop/app.rb:27:in `on_connection'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/server.rb:32:in `call'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/reel-0.4.0/lib/reel/server.rb:32:in `handle_connection'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:25:in `public_send'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:25:in `dispatch'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/calls.rb:122:in `dispatch'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/actor.rb:322:in `block in handle_message'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/actor.rb:416:in `block in task'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/tasks.rb:55:in `block in initialize'
    /Users/robertjpayne/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/celluloid-0.15.1/lib/celluloid/tasks/task_fiber.rb:13:in `block in create'

POST fails to become Hash and remains nil, during multimedia upload.

Right now using PLUpload ( html5 and/or Flash uploader ) I can crash Reel being used as a Rack handler by POSTing multi-part request.

I know it is limited to multi-part requests or binary files; uploading a large XML file was fine. I am thinking because that is only plain text.

With #33 resolved, this is the only thing stopping me from going to production with Reel, with Rack and Sinatra still in play, then moving off Rack and replacing Sinatra with Octarine at my leisure.

Reel::RackWorker crashed after websocket request and Ctrl-C

For example at http://espresso.github.com/Streaming.html#websockets i get follow error and 100%-loading of cpu core after Ctrl-C

bundle exec rackup -s reel -p 3001 server/bin/app.ru
I, [2013-03-26T08:09:34.353717 #28605]  INFO -- : A Reel good HTTP server!
I, [2013-03-26T08:09:34.353842 #28605]  INFO -- : Listening on 0.0.0.0:3001
127.0.0.1 - - [26/Mar/2013 08:09:42] "GET /websocket 1.1" 200 379 0.0003
127.0.0.1 - - [26/Mar/2013 08:09:42] "GET /websocket 1.1" 200 379 0.0065
127.0.0.1 - - [26/Mar/2013 08:09:43] "GET /favicon.ico 1.1" 404 39 0.0003
127.0.0.1 - - [26/Mar/2013 08:09:43] "GET /favicon.ico 1.1" 404 39 0.0006
^CE, [2013-03-26T08:09:45.311935 #28605] ERROR -- : Reel::RackWorker crashed!
RuntimeError:
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:50:in `resume'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:50:in `resume'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:419:in `task'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:326:in `handle_message'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:183:in `run'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:171:in `block in initialize'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/thread_handle.rb:12:in `block in initialize'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/internal_pool.rb:55:in `call'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/internal_pool.rb:55:in `block in create'
E, [2013-03-26T08:09:45.312185 #28605] ERROR -- : Reel::RackWorker crashed!
RuntimeError:
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:50:in `resume'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:50:in `resume'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:419:in `task'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:296:in `block in every'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/timers-1.1.0/lib/timers.rb:98:in `call'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/timers-1.1.0/lib/timers.rb:98:in `fire'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/timers-1.1.0/lib/timers.rb:55:in `fire'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:186:in `run'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/actor.rb:171:in `block in initialize'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/thread_handle.rb:12:in `block in initialize'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/internal_pool.rb:55:in `call'
    /Users/orangeudav/.rvm/gems/ruby-1.9.3-p392@app/gems/celluloid-0.13.0/lib/celluloid/internal_pool.rb:55:in `block in create'

Support --daemonize

In bin/reel, offer -D and --daemonize options to detach from process and leave it running, returning user to CLI.

NoMethodError: undefined method `peeraddr' for nil:NilClass

Hi,

Trying to get the remote host of a websocket connection fails like this, with JRuby 1.7.2:

NoMethodError: undefined method `peeraddr' for nil:NilClass
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/reel-0.3.0/lib/reel/mixins.rb:19:in `remote_host'
        /usr/local/appfactory-2013.6/src/server/workers/relay_coordinator.rb:98:in `on_connection'
        org/jruby/RubyMethod.java:134:in `call'
        org/jruby/RubyProc.java:249:in `call'
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/reel-0.3.0/lib/reel/server.rb:27:in `handle_connection'
        org/jruby/RubyBasicObject.java:1686:in `__send__'
        org/jruby/RubyKernel.java:1809:in `public_send'
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/celluloid-0.13.0/lib/celluloid/calls.rb:11:in `dispatch'
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/celluloid-0.13.0/lib/celluloid/calls.rb:96:in `dispatch'
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/celluloid-0.13.0/lib/celluloid/actor.rb:326:in `handle_message'
        /usr/local/appfactory-2013.6/src/server/gems/jruby/1.9/gems/celluloid-0.13.0/lib/celluloid/tasks/task_fiber.rb:28:in `initialize'

Impossible to pipeline requests

Reel is great, but wrongly advertise being HTTP/1.1 compatible: one of the most important features, pipelining, is impossible.

When pipelining requests, they are all stacked on the socket. A call to Request.read(connection) will read all of them, feed them to the parser which will correctly detect mutiple requests, but we only see one request from the outside (the last one, in fact)

A supervised Reel::Server hangs after a post-crash restart on MRI 2.0/OS X

(ohai @halorgium, this may interest you)

Reel's crash handling seems like it should be working. I've confirmed that the following happens when a Reel::Server crashes:

  • All outstanding Celluloid tasks are terminated by Celluloid itself. This runs the ensure blocks inside these tasks, which closes the connections to all clients. I've confirmed all of the client sockets are closed and that this approach seems sufficient for terminating client connections no crash.
  • The Reel::Server finalizer runs, closing Reel's Celluloid::IO::TCPSocket
  • The Celluloid::IO shutdown process works correctly and the NIO::Selector associated with Reel::Server's Celluloid::IO::Mailbox is closed.

tl;dr: teardown after a crash seems good, I think?

However, when the supervisor restarts the Reel::Server, all subsequent requests to the rebooted server hang. The server definitely crashes, everything gets torn down, but on subsequent reboot something is wedged for some reason.

Support rolling restart and code reload.

If signal is sent to server ( or reload method called, or file touched if -H specified ):

  • keep open all ports
  • wait for requests to complete
  • reload code and continue operation without downtime.

If in development environment and option passed to bin/reel or option set for server, reload code on update of included *.rb files and tell console which files changed and were reloaded.

SSLSocket cannot be IO.copy_stream destination.

One of the #90 twins.

Using #90's behavior for IO.copy_stream seems fine for HTTP now.

Now the problem is that even if the IO object is properly exposed so that it does not raise an exception, copying IO to an SSLSocket as a destination causes a browser error. I will troubleshoot this further, but so far it seems to always happen.

Will work on repro for this also.

Support WSS

Hi,

Is it just me who can't find the documentation, or is it currently impossible to use Reel with WSS (TLS-secured websockets)? If it is just me - please let me know how to do it. :)

(Can't seem to find the option where to enable it, so I presume it is not yet implemented.)

Best regards,
Per

Connection resets with concurrent connections > 6

When doing some testing against another Celluloid::IO project, I noticed connections getting reset once I hit a certain number of simultaneous clients attempting to connect. It would seem this issue is present in Reel as well, so I'm guessing it's a Celluloid::IO issue. Below are the ApacheBench commands I used to reproduce this issue. I'm using the Reel code provided in the readme as the server.

# Using -r with ab so the tests don't stop on a connection reset
› ab -c 10 -n 1000 -r  http://127.0.0.1:1234/   

Server Software:        
Server Hostname:        127.0.0.1
Server Port:            1234

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      10
Time taken for tests:   2.814 seconds
Complete requests:      1000
Failed requests:        157
   (Connect: 0, Receive: 140, Length: 17, Exceptions: 0)
Write errors:           78
Total transferred:      68658 bytes
HTML transferred:       11760 bytes
Requests per second:    355.36 [#/sec] (mean)
Time per request:       28.140 [ms] (mean)
Time per request:       2.814 [ms] (mean, across all concurrent requests)
Transfer rate:          23.83 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1   10  85.5      3    2586
Processing:     0    3  72.0      0    2268
Waiting:        0    0   0.2      0       3
Total:          1   12 118.4      3    2586

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      4
  75%      4
  80%      5
  90%     10
  95%     13
  98%     20
  99%    106
 100%   2586 (longest request)

Notice the failed requests. I've tried using httperf as well, but it seems to throttle the number of concurrent connections pretty heavily. However, when I set that up properly, it received a lot of connection resets as well.

Based off this StackOverflow - http://stackoverflow.com/questions/6625791/connection-reset-by-peer-error-occured-when-new-tcp-socket - I modified Reel ( https://github.com/celluloid/reel/blob/master/lib/reel/server.rb ) to set listen to 100 on the @server instance. This definitely helped, but I still receive occasional connection resets.

Chunked encoding transposes or mangles second chunk

Run this script: https://gist.github.com/3520657

Then run the curl in the comment. Here's the relevant part of the trace:

<= Recv data, 3 bytes (0x3)
0000: 35 0d 0a                                        5..
<= Recv data, 5 bytes (0x5)
0000: 68 65 6c 6c 6f                                  hello
hello<= Recv data, 8 bytes (0x8)
0000: 35 0d 0a 68 65 6c 6c 6f                         5..hello
== Info: Problem (3) in the Chunked-Encoded data
== Info: Closing connection #0

Streaming Transfer-Encoding: chunked responses requires writing to the Request instead of the Response

Reel's API to send streaming responses using chunked transfer encoding is still a bit wonky:

# Sending transfer_encoding chunked without a body enables streaming mode
request.respond :ok, :transfer_encoding => :chunked

# This will send individual chunks
request << "Hello"
request << "World"
request.finish_response # Write trailer and reset connection to header mode

It'd probably make more sense if we wrote to the response object instead of the request object:

response = Reel::Response.new(:ok, :transfer_encoding => :chunked)
request.respond response

response << "Hello"
response << "World"
response.finish

Websockets fail in Ruby 2.0.0

My application sends JSONs to server via websockets. In YARV 1.9.3 it goes smooth, but in 2.0.0 there are problems when reading them from websocket. Exceptions thrown are inconsistent: either it's not valid UTF-8 or unknown opcode (various ones). From time to time it succeeds, but retrieved message is junk like "\xA9=\xEE8\xBFu\xE0 \xF2g\xF63\xB9u\xB1]". Tried with newest released version and freshly cloned repo.

WebSocket::ParserError: Payload data is not valid UTF-8
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:183:in `process_message!'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:172:in `process_frame!'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:83:in `next_message'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/reel-0.3.0/lib/reel/websocket.rb:66:in `read'
WebSocket::ParserError: Unknown opcode 5
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:216:in `opcode'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:172:in `process_frame!'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/websocket_parser-0.1.1/lib/websocket/parser.rb:83:in `next_message'
/usr/local/Cellar/ruby/2.0.0-p0/lib/ruby/gems/2.0.0/gems/reel-0.3.0/lib/reel/websocket.rb:66:in `read'

HTTPS client certificate validation (mutual authentication)

Reel does not presently support the ability to validate HTTPS client certificates or pass them through the request object. This would be useful for letting clients authenticate cryptographically.

A strawman API:

ssl_options = {
  cert: File.read("server.crt"),
  key: File.read("server.key"),
  client_certs: {
    verify: true,
    max_depth: 1,
    ca_cert: File.read("clientca.crt")
  }
}

valid_user_subject = "/C=US/ST=California/L=San Francisco/O=World YOLO Federation/OU=YOLO Computing/CN=YOLO Crypto/[email protected]"

Reel::SSLServer.run("127.0.0.1", 3000, ssl_options) do |connection|
  connection.each_request do |request|
    if request.certificate.subject == valid_user_subject
      request.respond :ok, "hello, world!"
    else
      request.respond :forbidden, "go away"
    end
  end
end

Connections persisting, after hijack_io enabled handler.

I went to recycle my Reel handler and it said the port was already bound. I checked for any reel process, or any ruby processes for that matter and there were none.

Then I ran netstat -a | grep ":www" > out and was horrified to see as many connections as I have designated workers (eventually). For example:

http://decentrality.com/connections.025-001.log
http://decentrality.com/connections.025-002.log
http://decentrality.com/connections.025-003.log
http://decentrality.com/connections.025-004.log

That is watching a very short time period, with four checks for connections.

Very interesting, after recycling Reel (which evidently was allowed this time):

http://decentrality.com/connections.025-005-recycled.log

Note the change to LAST_ACK & TIME_WAIT
... but all those sockets persisting, even after the process was killed and restarted fresh.

After a long time: http://decentrality.com/connections.025-006.log
So something gets freed up eventually, but it seems like it's the OS doing it.

I recycled again: http://decentrality.com/connections.025-007-recycled.log
... now there is even FIN_WAIT1 which does seem to be the OS on a timer.

I can try to isolate this and remedy it, but can someone please try to duplicate this with @penultimatix's reel or @halorgium's latest hijack_io branch:

https://github.com/halorgium/reel/tree/hijacked-websocket

Impossible http_parser gem dependencies

When attempting to install the reel gem I get error:

ERROR: While executing gem ... (Gem::ImpossibleDependenciesError)
http-0.5.0 requires http_parser.rb (>= 0) but it conflicted:
Activated http_parser.rb-0.5.3 instead of (>= 0.6.0.beta.2) via:
reel-0.4.0

I'm using ubuntu, with rbx 2.1 which was installed using rvm.

Access to publish through Celluloid class method.

Mentioned in IRC to @halorgium: IMO, a class method interface to publish messages ought to be accessible from outside actors, through a class method on Celluloid, just like Futures have such an interface.

For example, Celluloid.publish() or Celluloid::Notifications.publish()

Reel::Response.new modifies callers body_or_headers headers hash

In particular

https://github.com/celluloid/reel/blob/master/lib/reel/response.rb#L29

sets CONTENT_LENGTH, which is then not modified on subsequent
responses.

A proposed fix is a change to

https://github.com/celluloid/reel/blob/master/lib/reel/response.rb#L20

headers = {}.merge body_or_headers

This will cause the setting of CONTENT_LENGTH to be local
to this response.

This gist has a test script with notes:

https://gist.github.com/CootCraig/6395964

handle: "Expect: 100-continue"

Low priority, but I was having a heart attack for a moment when doing some benchmarks vs node and learned something new about HTTP and curl.

Curl against ruby server:

time curl -i --data-binary "@4mb.zip" -H "Content-Type: application/zip" http://localhost:9292/
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 34

GOT THIS MUCH 4443572 (272 chunks)
real    0m2.127s
user    0m0.012s
sys 0m0.025s

Curl against node server:

time curl -i --data-binary "@4mb.zip" -H "Content-Type: application/zip" http://localhost:9292/
HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Content-Type: text/plain
Date: Mon, 14 Oct 2013 09:37:12 GMT
Connection: keep-alive
Transfer-Encoding: chunked

GOT THIS MUCH: 4443572 (70 chunks)
real    0m0.093s
user    0m0.012s
sys 0m0.025s

At first I was thinking, "Oh no! node is so much faster than ruby. What have I been doing wrong with my life."

Then I noticed the extra HTTP/1.1 100 Continue

I added that extra header to my request handler and SWEET GLORY! Ruby really is my friend.

real    0m0.115s
user    0m0.012s
sys 0m0.025s
def route_request(connection, request)
  if request.headers["Expect"] == "100-continue"
    connection.socket << "HTTP/1.1 100 Continue\r\n\r\n"
  end
  length = 0
  chunks = 0

  request.body.each do |chunk|
    chunks += 1
    length += chunk.length
  end
  connection.respond :ok, "GOT THIS MUCH #{length} (#{chunks} chunks)"
end

Not sure if this is in-scope for reel, but even some sort of log message pointing me in the right direction would have prevented much un-warranted soul searching and hair pulling. :D

Reel fails on first 2-3 requests, and after cooling down.

My first 2-3 pageloads always fail, using the Rack adapter for Reel. Not always in the process of returning a response from my application, but more so from returning an essential public file, like a JS or CSS file.

Example stack trace:

Reel::Server crashed!
Celluloid::DeadTaskError: cannot resume a dead task (dead fiber called)
/usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/tasks/task_fiber.rb:51:in resume' /usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/tasks/task_fiber.rb:47:inresume'
/usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/responses.rb:11:in dispatch' /usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/actor.rb:329:inhandle_message'
/usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/actor.rb:196:in run' /usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/actor.rb:184:ininitialize'
/usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/thread_handle.rb:17:in initialize' org/jruby/RubyProc.java:249:incall'
/usr/local/rvm/gems/jruby-1.7.3/gems/celluloid-0.12.4/lib/celluloid/internal_pool.rb:48:in `create'

10.126.130.1 - - [13/Mar/2013 15:10:56] "GET /01E.min.css 1.1" 304 - 0.0380

If I reload the URL in the browser 2-3 times, the request works.

And after an undetermined cool down period, 2-3 requests will also fail, as it does when Reel first starts up to return Rack responses.

SSLServer crashing due to type casting?

TypeError: can't convert Celluloid::IO::TCPServer into Integer
    org/jruby/ext/openssl/SSLContext.java:236:in `setup'
    org/jruby/ext/openssl/SSLSocket.java:145:in `initialize'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-io-43994f60e81b/lib/celluloid/io/ssl_socket.rb:15:in `initialize'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-io-43994f60e81b/lib/celluloid/io/ssl_server.rb:25:in `accept'
    /mu/penultimatix/reel/lib/reel/ssl_server.rb:30:in `run'
    org/jruby/RubyKernel.java:1489:in `loop'
    /mu/penultimatix/reel/lib/reel/ssl_server.rb:28:in `run'
    org/jruby/RubyBasicObject.java:1730:in `__send__'
    org/jruby/RubyKernel.java:1932:in `public_send'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/calls.rb:25:in `dispatch'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/calls.rb:122:in `dispatch'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/actor.rb:322:in `handle_message'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/actor.rb:416:in `task'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/tasks.rb:55:in `initialize'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/tasks.rb:47:in `initialize'
    /usr/local/rvm/gems/jruby-1.7.4/bundler/gems/celluloid-ad503d06e9b0/lib/celluloid/tasks/task_fiber.rb:13:in `create'

This was after moving to a recent commit, I will track down which one.

Pipelining Hangs Reel Server

Hi there, we're currently trying to use Reel as an Adhearsion plugin for some simple statistics reporting, but we've found (thanks @halorgium) that when people make requests from a browser the socket re-use is causing our service to hang up.

We don't necessarily need pipelining to work - a way to stop it from hanging the service or a way to deny user agents before a hang can occur would be enough to move forward. Hoping you may have ideas on a workaround.

A minimal reproduction: https://github.com/vindir/virginia-keepalive

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.