about summary refs log tree commit homepage
path: root/lib/unicorn.rb
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-01-27 00:08:19 +0000
committerEric Wong <e@80x24.org>2016-01-27 00:28:01 +0000
commit3d69a6f064078eeb28c1819725d3715ce6905374 (patch)
treefc8400bf722ae60869043711df57a932c5137c01 /lib/unicorn.rb
parent7c0271ef26dd41eb0fc1ca3370883c49a45b2dec (diff)
downloadunicorn-3d69a6f064078eeb28c1819725d3715ce6905374.tar.gz
We do not want to pull in a newer or older version of rack depending
on an the application running under it requires.  Furthermore, it
has always been possible to use unicorn without any middleware at
all.

Without rack, we'll be missing descriptive status text in the first
response line, but any valid HTTP/1.x parser should be able to
handle it properly.

ref:
 http://bogomips.org/unicorn-public/20160121201255.GA6186@dcvr.yhbt.net/t/#u

Thanks-to: Adam Duke <adam.v.duke@gmail.com>
Thanks-to: Aaron Patterson <tenderlove@ruby-lang.org>
Diffstat (limited to 'lib/unicorn.rb')
-rw-r--r--lib/unicorn.rb45
1 files changed, 27 insertions, 18 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index b0e6bd1..bb66b61 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -1,9 +1,14 @@
 # -*- encoding: binary -*-
 require 'etc'
 require 'stringio'
-require 'rack'
 require 'kgio'
 
+begin
+  require 'rack'
+rescue LoadError
+  warn 'rack not available, functionality reduced'
+end
+
 # :stopdoc:
 # Unicorn module containing all of the classes (include C extensions) for
 # running a Unicorn web server.  It contains a minimalist HTTP server with just
@@ -32,6 +37,9 @@ module Unicorn
   def self.builder(ru, op)
     # allow Configurator to parse cli switches embedded in the ru file
     op = Unicorn::Configurator::RACKUP.merge!(:file => ru, :optparse => op)
+    if ru =~ /\.ru$/ && !defined?(Rack::Builder)
+      abort "rack and Rack::Builder must be available for processing #{ru}"
+    end
 
     # Op is going to get cleared before the returned lambda is called, so
     # save this value so that it's still there when we need it:
@@ -53,32 +61,33 @@ module Unicorn
 
       return inner_app if no_default_middleware
 
+      middleware = { # order matters
+        ContentLength: nil,
+        Chunked: nil,
+        CommonLogger: [ $stderr ],
+        ShowExceptions: nil,
+        Lint: nil,
+        TempfileReaper: nil,
+      }
+
       # return value, matches rackup defaults based on env
       # Unicorn does not support persistent connections, but Rainbows!
       # and Zbatery both do.  Users accustomed to the Rack::Server default
       # middlewares will need ContentLength/Chunked middlewares.
       case ENV["RACK_ENV"]
       when "development"
-        Rack::Builder.new do
-          use Rack::ContentLength
-          use Rack::Chunked
-          use Rack::CommonLogger, $stderr
-          use Rack::ShowExceptions
-          use Rack::Lint
-          use Rack::TempfileReaper if Rack.const_defined?(:TempfileReaper)
-          run inner_app
-        end.to_app
       when "deployment"
-        Rack::Builder.new do
-          use Rack::ContentLength
-          use Rack::Chunked
-          use Rack::CommonLogger, $stderr
-          use Rack::TempfileReaper if Rack.const_defined?(:TempfileReaper)
-          run inner_app
-        end.to_app
+        middleware.delete(:ShowExceptions)
+        middleware.delete(:Lint)
       else
-        inner_app
+        return inner_app
       end
+      Rack::Builder.new do
+        middleware.each do |m, args|
+          use(Rack.const_get(m), *args) if Rack.const_defined?(m)
+        end
+        run inner_app
+      end.to_app
     end
   end