From 17feb4c52dd7807ee930645c2eb129b6886f66fa Mon Sep 17 00:00:00 2001
From: Ryan Tomayko <rtomayko@gmail.com>
Date: Thu, 5 Mar 2009 21:21:52 -0800
Subject: [PATCH 4/4] Handlers use ContentLength and Chunked middleware where needed

Each Rack handler now automatically wraps the app in one or more
pieces of middleware based on how the server is implemented. All
handlers use the Rack::ContentLength middleware and some handlers
use the Rack::Chunked middleware. Handlers that don't use the
Chunked middleware either do not require CE for some reason or
implement CE at the server level.

* The Thin handler uses Chunked and ContentLength middleware. Thin
  has built-in CE support but also allows the app to apply it
  explicitly. Using our middleware for consistency and also because
  I believe the Thin folks want to remove CE support in the future.

* The Mongrel handler uses Chunked and ContentLength middleware.
  Mongrel has built-in CE support but also allows the app to apply
  it explicitly. Using our middleware for consistency across
  handlers.

* The SCGI handler uses Chunked and ContentLength middleware.

* The WEBrick handler uses ContentLength middleware only; WEBrick
  has a really touchy CE implementation that doesn't like it when
  CE is applied by the application.

* The FastCGI handler uses ContentLength only. FastCGI has its own
  mechanism for transferring bodies that do not include an
  explicit Content-Length. The FastCGI server applies the chunked
  encoding if needed.

* The CGI handler uses ContentLength only. The CGI spec forbids the
  use of the Transfer-Encoding header in output from CGI programs.
  The server program is responsible for applying the chunked
  encoding if needed. Closing stdout signals the end of the body
  so it's not really needed anyway.

* The LSWS handler uses ContentLength middleware only. Like CGI, LSWS
  closes the stream after transfer so chunked encoding is never
  required.
---
 lib/rack/handler/cgi.rb     |    4 ++++
 lib/rack/handler/fastcgi.rb |    3 +++
 lib/rack/handler/lsws.rb    |    5 ++++-
 lib/rack/handler/mongrel.rb |    4 +++-
 lib/rack/handler/scgi.rb    |    4 +++-
 lib/rack/handler/thin.rb    |    3 +++
 lib/rack/handler/webrick.rb |    3 ++-
 7 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/lib/rack/handler/cgi.rb b/lib/rack/handler/cgi.rb
index f2c976c..e38156c 100644
--- a/lib/rack/handler/cgi.rb
+++ b/lib/rack/handler/cgi.rb
@@ -1,3 +1,5 @@
+require 'rack/content_length'
+
 module Rack
   module Handler
     class CGI
@@ -6,6 +8,8 @@ module Rack
       end
 
       def self.serve(app)
+        app = ContentLength.new(app)
+
         env = ENV.to_hash
         env.delete "HTTP_CONTENT_LENGTH"
 
diff --git a/lib/rack/handler/fastcgi.rb b/lib/rack/handler/fastcgi.rb
index f03e161..6324c7d 100644
--- a/lib/rack/handler/fastcgi.rb
+++ b/lib/rack/handler/fastcgi.rb
@@ -1,5 +1,6 @@
 require 'fcgi'
 require 'socket'
+require 'rack/content_length'
 
 module Rack
   module Handler
@@ -29,6 +30,8 @@ module Rack
       end
 
       def self.serve(request, app)
+        app = Rack::ContentLength.new(app)
+
         env = request.env
         env.delete "HTTP_CONTENT_LENGTH"
 
diff --git a/lib/rack/handler/lsws.rb b/lib/rack/handler/lsws.rb
index 1f850fc..93b5a16 100644
--- a/lib/rack/handler/lsws.rb
+++ b/lib/rack/handler/lsws.rb
@@ -1,5 +1,6 @@
 require 'lsapi'
-#require 'cgi'
+require 'rack/content_length'
+
 module Rack
   module Handler
     class LSWS
@@ -9,6 +10,8 @@ module Rack
         end
       end
       def self.serve(app)
+        app = Rack::ContentLength.new(app)
+
         env = ENV.to_hash
         env.delete "HTTP_CONTENT_LENGTH"
         env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
diff --git a/lib/rack/handler/mongrel.rb b/lib/rack/handler/mongrel.rb
index 178a1a8..f0c0d58 100644
--- a/lib/rack/handler/mongrel.rb
+++ b/lib/rack/handler/mongrel.rb
@@ -1,5 +1,7 @@
 require 'mongrel'
 require 'stringio'
+require 'rack/content_length'
+require 'rack/chunked'
 
 module Rack
   module Handler
@@ -33,7 +35,7 @@ module Rack
       end
 
       def initialize(app)
-        @app = app
+        @app = Rack::Chunked.new(Rack::ContentLength.new(app))
       end
 
       def process(request, response)
diff --git a/lib/rack/handler/scgi.rb b/lib/rack/handler/scgi.rb
index fd18a83..9495c66 100644
--- a/lib/rack/handler/scgi.rb
+++ b/lib/rack/handler/scgi.rb
@@ -1,5 +1,7 @@
 require 'scgi'
 require 'stringio'
+require 'rack/content_length'
+require 'rack/chunked'
 
 module Rack
   module Handler
@@ -14,7 +16,7 @@ module Rack
       end
       
       def initialize(settings = {})
-        @app = settings[:app]
+        @app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app]))
         @log = Object.new
         def @log.info(*args); end
         def @log.error(*args); end
diff --git a/lib/rack/handler/thin.rb b/lib/rack/handler/thin.rb
index 7ad088b..3d4fedf 100644
--- a/lib/rack/handler/thin.rb
+++ b/lib/rack/handler/thin.rb
@@ -1,9 +1,12 @@
 require "thin"
+require "rack/content_length"
+require "rack/chunked"
 
 module Rack
   module Handler
     class Thin
       def self.run(app, options={})
+        app = Rack::Chunked.new(Rack::ContentLength.new(app))
         server = ::Thin::Server.new(options[:Host] || '0.0.0.0',
                                     options[:Port] || 8080,
                                     app)
diff --git a/lib/rack/handler/webrick.rb b/lib/rack/handler/webrick.rb
index 40be79d..4d535ac 100644
--- a/lib/rack/handler/webrick.rb
+++ b/lib/rack/handler/webrick.rb
@@ -1,5 +1,6 @@
 require 'webrick'
 require 'stringio'
+require 'rack/content_length'
 
 module Rack
   module Handler
@@ -14,7 +15,7 @@ module Rack
 
       def initialize(server, app)
         super server
-        @app = app
+        @app = Rack::ContentLength.new(app)
       end
 
       def service(req, res)
-- 
1.6.2

