about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-07-08 23:21:18 +0000
committerEric Wong <normalperson@yhbt.net>2010-07-08 23:21:18 +0000
commit9abb447a573751b87e26ce35f4f05d58290f4c41 (patch)
tree1adb0dac9acd99c9add0880751c7e022003776ef
parent235985c6c4b37ed9a170c38052db3ef0772b1527 (diff)
downloadrainbows-9abb447a573751b87e26ce35f4f05d58290f4c41.tar.gz
Cramp monkey patches Rainbows internals for WebSockets
support and we forgot about it.  Add a new integration
test to ensure this continues to work in the future
(and force us to update the test for newer Cramp).
-rw-r--r--lib/rainbows.rb3
-rw-r--r--lib/rainbows/base.rb4
-rw-r--r--lib/rainbows/event_machine.rb4
-rw-r--r--lib/rainbows/fiber/body.rb2
-rw-r--r--lib/rainbows/fiber/rev.rb2
-rw-r--r--lib/rainbows/http_response.rb48
-rw-r--r--lib/rainbows/response.rb44
-rw-r--r--lib/rainbows/response/body.rb (renamed from lib/rainbows/http_response/body.rb)2
-rw-r--r--lib/rainbows/rev/client.rb2
-rw-r--r--lib/rainbows/rev/core.rb2
-rw-r--r--lib/rainbows/rev_fiber_spawn.rb2
-rw-r--r--lib/rainbows/writer_thread_pool.rb2
-rw-r--r--lib/rainbows/writer_thread_spawn.rb4
-rw-r--r--t/cramp/rainsocket.ru26
-rwxr-xr-xt/t0501-cramp-rainsocket.sh38
15 files changed, 130 insertions, 55 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index 7bc9a92..4e9578b 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -33,7 +33,7 @@ module Rainbows
 
   require 'rainbows/const'
   require 'rainbows/http_server'
-  require 'rainbows/http_response'
+  require 'rainbows/response'
   require 'rainbows/base'
   require 'rainbows/tee_input'
   autoload :Sendfile, 'rainbows/sendfile'
@@ -127,4 +127,5 @@ module Rainbows
   autoload :Fiber, 'rainbows/fiber' # core class
   autoload :ByteSlice, 'rainbows/byte_slice'
   autoload :StreamFile, 'rainbows/stream_file'
+  autoload :HttpResponse, 'rainbows/http_response' # deprecated
 end
diff --git a/lib/rainbows/base.rb b/lib/rainbows/base.rb
index cd719d2..a619b00 100644
--- a/lib/rainbows/base.rb
+++ b/lib/rainbows/base.rb
@@ -10,7 +10,7 @@ module Rainbows::Base
 
   # :stopdoc:
   include Rainbows::Const
-  include Rainbows::HttpResponse
+  include Rainbows::Response
 
   # shortcuts...
   G = Rainbows::G
@@ -21,7 +21,7 @@ module Rainbows::Base
   # this method is called by all current concurrency models
   def init_worker_process(worker)
     super(worker)
-    Rainbows::HttpResponse.setup(self.class)
+    Rainbows::Response.setup(self.class)
     Rainbows::MaxBody.setup
     G.tmp = worker.tmp
 
diff --git a/lib/rainbows/event_machine.rb b/lib/rainbows/event_machine.rb
index 0ad604e..0404493 100644
--- a/lib/rainbows/event_machine.rb
+++ b/lib/rainbows/event_machine.rb
@@ -50,7 +50,7 @@ module Rainbows
 
     class Client < EM::Connection
       include Rainbows::EvCore
-      include Rainbows::HttpResponse
+      include Rainbows::Response
       G = Rainbows::G
 
       def initialize(io)
@@ -227,7 +227,7 @@ module Rainbows
     end
 
     def init_worker_process(worker)
-      Rainbows::HttpResponse.setup(Rainbows::EventMachine::Client)
+      Rainbows::Response.setup(Rainbows::EventMachine::Client)
       super
     end
 
diff --git a/lib/rainbows/fiber/body.rb b/lib/rainbows/fiber/body.rb
index b77e310..3de45ee 100644
--- a/lib/rainbows/fiber/body.rb
+++ b/lib/rainbows/fiber/body.rb
@@ -1,7 +1,7 @@
 # -*- encoding: binary -*-
 # non-portable body handling for Fiber-based concurrency goes here
 # this module is required and included in worker processes only
-# this is meant to be included _after_ Rainbows::HttpResponse::Body
+# this is meant to be included _after_ Rainbows::Response::Body
 module Rainbows::Fiber::Body # :nodoc:
 
   # TODO non-blocking splice(2) under Linux
diff --git a/lib/rainbows/fiber/rev.rb b/lib/rainbows/fiber/rev.rb
index 2e8f076..a1ffe33 100644
--- a/lib/rainbows/fiber/rev.rb
+++ b/lib/rainbows/fiber/rev.rb
@@ -52,7 +52,7 @@ module Rainbows::Fiber
       include Unicorn
       include Rainbows
       include Rainbows::Const
-      include Rainbows::HttpResponse
+      include Rainbows::Response
       FIO = Rainbows::Fiber::IO
 
       def to_io
diff --git a/lib/rainbows/http_response.rb b/lib/rainbows/http_response.rb
index 677b5a7..cf17aa1 100644
--- a/lib/rainbows/http_response.rb
+++ b/lib/rainbows/http_response.rb
@@ -1,44 +1,10 @@
 # -*- encoding: binary -*-
-require 'time' # for Time#httpdate
-
-# :stopdoc:
-module Rainbows::HttpResponse
-
-  CODES = Unicorn::HttpResponse::CODES
-
-  def response_header(response, out)
-    status, headers = response
-    status = CODES[status.to_i] || status
-
-    headers.each do |key, value|
-      next if %r{\A(?:X-Rainbows-|Connection\z|Date\z|Status\z)}i =~ key
-      if value =~ /\n/
-        # avoiding blank, key-only cookies with /\n+/
-        out.concat(value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" })
-      else
-        out << "#{key}: #{value}\r\n"
-      end
-    end
-
-    "HTTP/1.1 #{status}\r\n" \
-    "Date: #{Time.now.httpdate}\r\n" \
-    "Status: #{status}\r\n" \
-    "#{out.join('')}\r\n"
-  end
-
-  def write_header(socket, response, out)
-    out and socket.write(response_header(response, out))
-  end
-
-  def write_response(socket, response, out)
-    write_header(socket, response, out)
-    write_body(socket, response[2])
-  end
-
-  # called after forking
-  def self.setup(klass)
-    require('rainbows/http_response/body') and
-      klass.__send__(:include, Rainbows::HttpResponse::Body)
+# deprecated, use Rainbows::Response instead
+# Cramp 0.11 relies on this
+# :enddoc:
+class Rainbows::HttpResponse
+  class << self
+    include Rainbows::Response
+    alias write write_response
   end
 end
-# :startdoc:
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
new file mode 100644
index 0000000..8d131b0
--- /dev/null
+++ b/lib/rainbows/response.rb
@@ -0,0 +1,44 @@
+# -*- encoding: binary -*-
+require 'time' # for Time#httpdate
+
+# :stopdoc:
+module Rainbows::Response
+
+  CODES = Unicorn::HttpResponse::CODES
+
+  def response_header(response, out)
+    status, headers = response
+    status = CODES[status.to_i] || status
+
+    headers.each do |key, value|
+      next if %r{\A(?:X-Rainbows-|Connection\z|Date\z|Status\z)}i =~ key
+      if value =~ /\n/
+        # avoiding blank, key-only cookies with /\n+/
+        out.concat(value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" })
+      else
+        out << "#{key}: #{value}\r\n"
+      end
+    end
+
+    "HTTP/1.1 #{status}\r\n" \
+    "Date: #{Time.now.httpdate}\r\n" \
+    "Status: #{status}\r\n" \
+    "#{out.join('')}\r\n"
+  end
+
+  def write_header(socket, response, out)
+    out and socket.write(response_header(response, out))
+  end
+
+  def write_response(socket, response, out)
+    write_header(socket, response, out)
+    write_body(socket, response[2])
+  end
+
+  # called after forking
+  def self.setup(klass)
+    require('rainbows/response/body') and
+      klass.__send__(:include, Rainbows::Response::Body)
+  end
+end
+# :startdoc:
diff --git a/lib/rainbows/http_response/body.rb b/lib/rainbows/response/body.rb
index 2ce09da..8d8ec27 100644
--- a/lib/rainbows/http_response/body.rb
+++ b/lib/rainbows/response/body.rb
@@ -26,7 +26,7 @@
 #            `- write_body_file
 #            `- write_body_stream
 #
-module Rainbows::HttpResponse::Body # :nodoc:
+module Rainbows::Response::Body # :nodoc:
   ALIASES = {}
 
   # to_io is not part of the Rack spec, but make an exception here
diff --git a/lib/rainbows/rev/client.rb b/lib/rainbows/rev/client.rb
index bc8d7fa..91947b6 100644
--- a/lib/rainbows/rev/client.rb
+++ b/lib/rainbows/rev/client.rb
@@ -6,7 +6,7 @@ module Rainbows
     class Client < ::Rev::IO
       include Rainbows::ByteSlice
       include Rainbows::EvCore
-      include Rainbows::HttpResponse
+      include Rainbows::Response
       G = Rainbows::G
       HH = Rack::Utils::HeaderHash
 
diff --git a/lib/rainbows/rev/core.rb b/lib/rainbows/rev/core.rb
index 2488cf2..4668cce 100644
--- a/lib/rainbows/rev/core.rb
+++ b/lib/rainbows/rev/core.rb
@@ -22,7 +22,7 @@ module Rainbows
       # for connections and doesn't die until the parent dies (or is
       # given a INT, QUIT, or TERM signal)
       def worker_loop(worker)
-        Rainbows::HttpResponse.setup(Rainbows::Rev::Client)
+        Rainbows::Response.setup(Rainbows::Rev::Client)
         require 'rainbows/rev/sendfile'
         Rainbows::Rev::Client.__send__(:include, Rainbows::Rev::Sendfile)
         init_worker_process(worker)
diff --git a/lib/rainbows/rev_fiber_spawn.rb b/lib/rainbows/rev_fiber_spawn.rb
index 4d64e39..e9ea1db 100644
--- a/lib/rainbows/rev_fiber_spawn.rb
+++ b/lib/rainbows/rev_fiber_spawn.rb
@@ -16,7 +16,7 @@ module Rainbows
     include Fiber::Rev
 
     def worker_loop(worker)
-      Rainbows::HttpResponse.setup(Rainbows::Fiber::Rev::Server)
+      Rainbows::Response.setup(Rainbows::Fiber::Rev::Server)
       init_worker_process(worker)
       Server.const_set(:MAX, @worker_connections)
       Rainbows::Fiber::Base.setup(Rainbows::Fiber::Rev::Server, nil)
diff --git a/lib/rainbows/writer_thread_pool.rb b/lib/rainbows/writer_thread_pool.rb
index a2ef1ba..84b750b 100644
--- a/lib/rainbows/writer_thread_pool.rb
+++ b/lib/rainbows/writer_thread_pool.rb
@@ -61,7 +61,7 @@ module Rainbows
     end
 
     def worker_loop(worker)
-      Rainbows::HttpResponse.setup(self.class)
+      Rainbows::Response.setup(self.class)
       self.class.__send__(:alias_method, :sync_write_body, :write_body)
       self.class.__send__(:include, Response)
 
diff --git a/lib/rainbows/writer_thread_spawn.rb b/lib/rainbows/writer_thread_spawn.rb
index 9e793fc..b9bbad2 100644
--- a/lib/rainbows/writer_thread_spawn.rb
+++ b/lib/rainbows/writer_thread_spawn.rb
@@ -28,7 +28,7 @@ module Rainbows
     # used to wrap a BasicSocket to use with +q+ for all writes
     # this is compatible with IO.select
     class MySocket < Struct.new(:to_io, :q, :thr)
-      include Rainbows::HttpResponse
+      include Rainbows::Response
 
       def readpartial(size, buf = "")
         to_io.readpartial(size, buf)
@@ -100,7 +100,7 @@ module Rainbows
 
     def worker_loop(worker)
       MySocket.const_set(:MAX, worker_connections)
-      Rainbows::HttpResponse.setup(MySocket)
+      Rainbows::Response.setup(MySocket)
       super(worker) # accept loop from Unicorn
       CUR.delete_if do |t,q|
         q << nil
diff --git a/t/cramp/rainsocket.ru b/t/cramp/rainsocket.ru
new file mode 100644
index 0000000..0d26f70
--- /dev/null
+++ b/t/cramp/rainsocket.ru
@@ -0,0 +1,26 @@
+# based on examples/rainsocket.ru git://github.com/lifo/cramp
+# Rack::Lint does not like async + EM stuff, so disable it:
+#\ -E deployment
+require 'cramp/controller'
+
+Cramp::Controller::Websocket.backend = :rainbows
+
+class WelcomeController < Cramp::Controller::Websocket
+  periodic_timer :send_hello_world, :every => 2
+  on_data :received_data
+
+  def received_data(data)
+    if data =~ /fuck/
+      render "You cant say fuck in here"
+      finish
+    else
+      render "Got your #{data}"
+    end
+  end
+
+  def send_hello_world
+    render "Hello from the Server!\n"
+  end
+end
+
+run WelcomeController
diff --git a/t/t0501-cramp-rainsocket.sh b/t/t0501-cramp-rainsocket.sh
new file mode 100755
index 0000000..6e3aea4
--- /dev/null
+++ b/t/t0501-cramp-rainsocket.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+. ./test-lib.sh
+case $model in
+EventMachine) ;;
+*)
+        t_info "skipping $T since it's not compatible with $model"
+        exit 0
+        ;;
+esac
+require_check cramp Cramp::VERSION
+
+t_plan 4 "WebSocket monkey patch validity test for Cramp"
+
+CONFIG_RU=cramp/rainsocket.ru
+
+t_begin "setup and start" && {
+        rainbows_setup
+        rtmpfiles curl_err
+
+        # Like the rest of the EM/async stuff, it's not Rack::Lint compatible
+        rainbows -E deployment -D $CONFIG_RU -c $unicorn_config
+        rainbows_wait_start
+}
+
+t_begin "wait for server to say hello to us" && {
+        ok=$((curl --no-buffer -sS http://$listen/ || :) | \
+             awk '/Hello from the Server/ { print "ok"; exit 0 }')
+
+        test x"$ok" = xok
+}
+
+t_begin "termination signal sent" && {
+        kill $rainbows_pid
+}
+
+t_begin "no errors in stderr" && check_stderr
+
+t_done