unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
* [PATCH 0/2] no avoiding rack.hijack anymore
@ 2015-05-16 21:30 Eric Wong
  2015-05-16 21:30 ` [PATCH 1/2] http_request: support rack.hijack by default Eric Wong
  2015-05-16 21:30 ` [PATCH 2/2] avoid extra allocation for hijack proc creation Eric Wong
  0 siblings, 2 replies; 4+ messages in thread
From: Eric Wong @ 2015-05-16 21:30 UTC (permalink / raw)
  To: unicorn-public; +Cc: e

I'm not sure if it makes sense to use rack.hijack with a prefork server
like unicorn which only works behind nginx, but maybe somebody does...

Eric Wong (2):
      http_request: support rack.hijack by default
      avoid extra allocation for hijack proc creation

 lib/unicorn/http_request.rb | 40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] http_request: support rack.hijack by default
  2015-05-16 21:30 [PATCH 0/2] no avoiding rack.hijack anymore Eric Wong
@ 2015-05-16 21:30 ` Eric Wong
  2015-05-19 20:01   ` [PATCH] http_response: avoid special-casing for Rack < 1.5 Eric Wong
  2015-05-16 21:30 ` [PATCH 2/2] avoid extra allocation for hijack proc creation Eric Wong
  1 sibling, 1 reply; 4+ messages in thread
From: Eric Wong @ 2015-05-16 21:30 UTC (permalink / raw)
  To: unicorn-public; +Cc: e

Rack 1.4 and earlier will soon die out, so avoid having extra code

The only minor overhead is assigning two hash slots and
the extra hash checks when running ancient versions of Rack,
so it is unlikely anybody cares about that overhead with Rack 1.5
and later.
---
 lib/unicorn/http_request.rb | 32 +++++++++-----------------------
 1 file changed, 9 insertions(+), 23 deletions(-)

diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb
index 9888430..b32003e 100644
--- a/lib/unicorn/http_request.rb
+++ b/lib/unicorn/http_request.rb
@@ -13,13 +13,16 @@ class Unicorn::HttpParser
     "rack.multiprocess" => true,
     "rack.multithread" => false,
     "rack.run_once" => false,
-    "rack.version" => [1, 1],
+    "rack.version" => [1, 2],
+    "rack.hijack?" => true,
     "SCRIPT_NAME" => "",
 
     # this is not in the Rack spec, but some apps may rely on it
     "SERVER_SOFTWARE" => "Unicorn #{Unicorn::Const::UNICORN_VERSION}"
   }
 
+  RACK_HIJACK = "rack.hijack".freeze
+  RACK_HIJACK_IO = "rack.hijack_io".freeze
   NULL_IO = StringIO.new("")
 
   attr_accessor :response_start_sent
@@ -98,28 +101,11 @@ class Unicorn::HttpParser
     e.merge!(DEFAULTS)
   end
 
-  # Rack 1.5.0 (protocol version 1.2) adds hijack request support
-  if ((Rack::VERSION[0] << 8) | Rack::VERSION[1]) >= 0x0102
-    DEFAULTS["rack.hijack?"] = true
-    DEFAULTS["rack.version"] = [1, 2]
-
-    RACK_HIJACK = "rack.hijack".freeze
-    RACK_HIJACK_IO = "rack.hijack_io".freeze
-
-    def hijacked?
-      env.include?(RACK_HIJACK_IO)
-    end
-
-    def hijack_setup(e, socket)
-      e[RACK_HIJACK] = proc { e[RACK_HIJACK_IO] = socket }
-    end
-  else
-    # old Rack, do nothing.
-    def hijack_setup(e, _)
-    end
+  def hijacked?
+    env.include?(RACK_HIJACK_IO)
+  end
 
-    def hijacked?
-      false
-    end
+  def hijack_setup(e, socket)
+    e[RACK_HIJACK] = proc { e[RACK_HIJACK_IO] = socket }
   end
 end
-- 
EW


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] avoid extra allocation for hijack proc creation
  2015-05-16 21:30 [PATCH 0/2] no avoiding rack.hijack anymore Eric Wong
  2015-05-16 21:30 ` [PATCH 1/2] http_request: support rack.hijack by default Eric Wong
@ 2015-05-16 21:30 ` Eric Wong
  1 sibling, 0 replies; 4+ messages in thread
From: Eric Wong @ 2015-05-16 21:30 UTC (permalink / raw)
  To: unicorn-public; +Cc: e

proc creation is expensive, so merely use a 48-byte generic ivar
hash slot for @socket instead.
---
 lib/unicorn/http_request.rb | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb
index b32003e..b60e383 100644
--- a/lib/unicorn/http_request.rb
+++ b/lib/unicorn/http_request.rb
@@ -97,15 +97,21 @@ class Unicorn::HttpParser
 
     e[RACK_INPUT] = 0 == content_length ?
                     NULL_IO : @@input_class.new(socket, self)
-    hijack_setup(e, socket)
+
+    # for Rack hijacking in Rack 1.5 and later
+    @socket = socket
+    e[RACK_HIJACK] = self
+
     e.merge!(DEFAULTS)
   end
 
-  def hijacked?
-    env.include?(RACK_HIJACK_IO)
+  # for rack.hijack, we respond to this method so no extra allocation
+  # of a proc object
+  def call
+    env[RACK_HIJACK_IO] = @socket
   end
 
-  def hijack_setup(e, socket)
-    e[RACK_HIJACK] = proc { e[RACK_HIJACK_IO] = socket }
+  def hijacked?
+    env.include?(RACK_HIJACK_IO)
   end
 end
-- 
EW


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] http_response: avoid special-casing for Rack < 1.5
  2015-05-16 21:30 ` [PATCH 1/2] http_request: support rack.hijack by default Eric Wong
@ 2015-05-19 20:01   ` Eric Wong
  0 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2015-05-19 20:01 UTC (permalink / raw)
  To: unicorn-public

Rack 1.4 and earlier will soon die out, so avoid having extra,
overengineered code and method dispatch to silently drop support
for mis-hijacking with old Rack versions.

This will cause improperly hijacked responses in all versions of
Rack to fail, but allows properly hijacked responses to work
regardless of Rack version.

Followup-to: commit fdf09e562733f9509d275cb13c1c1a04e579a68a
("http_request: support rack.hijack by default")
---
 lib/unicorn/http_response.rb | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb
index cc027c5..c9c2de8 100644
--- a/lib/unicorn/http_response.rb
+++ b/lib/unicorn/http_response.rb
@@ -36,9 +36,9 @@ def http_response_write(socket, status, headers, body,
         when %r{\A(?:Date\z|Connection\z)}i
           next
         when "rack.hijack"
-          # this was an illegal key in Rack < 1.5, so it should be
-          # OK to silently discard it for those older versions
-          hijack = hijack_prepare(value)
+          # This should only be hit under Rack >= 1.5, as this was an illegal
+          # key in Rack < 1.5
+          hijack = value
         else
           if value =~ /\n/
             # avoiding blank, key-only cookies with /\n+/
@@ -60,14 +60,4 @@ def http_response_write(socket, status, headers, body,
   ensure
     body.respond_to?(:close) and body.close
   end
-
-  # Rack 1.5.0 (protocol version 1.2) adds response hijacking support
-  if ((Rack::VERSION[0] << 8) | Rack::VERSION[1]) >= 0x0102
-    def hijack_prepare(value)
-      value
-    end
-  else
-    def hijack_prepare(_)
-    end
-  end
 end
-- 
EW


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-05-19 20:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-16 21:30 [PATCH 0/2] no avoiding rack.hijack anymore Eric Wong
2015-05-16 21:30 ` [PATCH 1/2] http_request: support rack.hijack by default Eric Wong
2015-05-19 20:01   ` [PATCH] http_response: avoid special-casing for Rack < 1.5 Eric Wong
2015-05-16 21:30 ` [PATCH 2/2] avoid extra allocation for hijack proc creation Eric Wong

Code repositories for project(s) associated with this inbox:

	../../../unicorn.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).