rack 1.3.10 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- data/COPYING +1 -1
 - data/KNOWN-ISSUES +0 -9
 - data/README.rdoc +4 -118
 - data/Rakefile +15 -0
 - data/SPEC +3 -5
 - data/lib/rack.rb +0 -12
 - data/lib/rack/auth/abstract/request.rb +1 -5
 - data/lib/rack/auth/basic.rb +1 -1
 - data/lib/rack/auth/digest/nonce.rb +1 -1
 - data/lib/rack/backports/uri/common_18.rb +28 -14
 - data/lib/rack/backports/uri/common_192.rb +17 -14
 - data/lib/rack/body_proxy.rb +0 -10
 - data/lib/rack/builder.rb +26 -18
 - data/lib/rack/cascade.rb +1 -12
 - data/lib/rack/chunked.rb +2 -0
 - data/lib/rack/content_type.rb +7 -1
 - data/lib/rack/deflater.rb +1 -5
 - data/lib/rack/directory.rb +5 -1
 - data/lib/rack/file.rb +26 -9
 - data/lib/rack/handler.rb +2 -2
 - data/lib/rack/head.rb +0 -1
 - data/lib/rack/lint.rb +3 -5
 - data/lib/rack/methodoverride.rb +10 -4
 - data/lib/rack/mime.rb +606 -171
 - data/lib/rack/mock.rb +2 -1
 - data/lib/rack/multipart.rb +2 -2
 - data/lib/rack/multipart/parser.rb +3 -10
 - data/lib/rack/reloader.rb +1 -1
 - data/lib/rack/request.rb +45 -13
 - data/lib/rack/response.rb +15 -14
 - data/lib/rack/sendfile.rb +8 -6
 - data/lib/rack/server.rb +4 -30
 - data/lib/rack/session/abstract/id.rb +25 -6
 - data/lib/rack/session/cookie.rb +12 -16
 - data/lib/rack/static.rb +21 -8
 - data/lib/rack/urlmap.rb +28 -13
 - data/lib/rack/utils.rb +22 -28
 - data/rack.gemspec +5 -5
 - data/test/builder/end.ru +2 -0
 - data/test/cgi/lighttpd.conf +1 -0
 - data/test/cgi/sample_rackup.ru +1 -1
 - data/test/cgi/test+directory/test+file +1 -0
 - data/test/cgi/test.ru +1 -1
 - data/test/gemloader.rb +6 -2
 - data/test/spec_auth_basic.rb +4 -9
 - data/test/spec_auth_digest.rb +3 -16
 - data/test/spec_body_proxy.rb +0 -4
 - data/test/spec_builder.rb +63 -20
 - data/test/spec_cascade.rb +10 -13
 - data/test/spec_cgi.rb +1 -1
 - data/test/spec_chunked.rb +39 -12
 - data/test/spec_commonlogger.rb +4 -3
 - data/test/spec_conditionalget.rb +16 -12
 - data/test/spec_content_length.rb +1 -1
 - data/test/spec_content_type.rb +6 -0
 - data/test/spec_deflater.rb +2 -2
 - data/test/spec_directory.rb +12 -0
 - data/test/spec_fastcgi.rb +1 -1
 - data/test/spec_file.rb +58 -8
 - data/test/spec_head.rb +6 -18
 - data/test/spec_lint.rb +2 -2
 - data/test/spec_methodoverride.rb +15 -0
 - data/test/spec_mock.rb +6 -2
 - data/test/spec_mongrel.rb +8 -8
 - data/test/spec_multipart.rb +10 -63
 - data/test/spec_request.rb +94 -21
 - data/test/spec_response.rb +22 -24
 - data/test/spec_sendfile.rb +3 -0
 - data/test/spec_server.rb +2 -49
 - data/test/spec_session_cookie.rb +58 -22
 - data/test/spec_session_memcache.rb +31 -1
 - data/test/spec_session_pool.rb +10 -4
 - data/test/spec_static.rb +8 -0
 - data/test/spec_thin.rb +2 -2
 - data/test/spec_utils.rb +38 -35
 - data/test/spec_webrick.rb +5 -3
 - data/test/static/index.html +1 -0
 - metadata +13 -18
 - data/contrib/rack.png +0 -0
 - data/contrib/rack.svg +0 -150
 - data/lib/rack/backports/uri/common_193.rb +0 -29
 - data/test/builder/line.ru +0 -1
 - data/test/spec_auth.rb +0 -57
 
    
        data/lib/rack/mock.rb
    CHANGED
    
    | 
         @@ -57,6 +57,7 @@ module Rack 
     | 
|
| 
       57 
57 
     | 
    
         
             
                def post(uri, opts={})   request("POST", uri, opts)   end
         
     | 
| 
       58 
58 
     | 
    
         
             
                def put(uri, opts={})    request("PUT", uri, opts)    end
         
     | 
| 
       59 
59 
     | 
    
         
             
                def delete(uri, opts={}) request("DELETE", uri, opts) end
         
     | 
| 
      
 60 
     | 
    
         
            +
                def head(uri, opts={})   request("HEAD", uri, opts)   end
         
     | 
| 
       60 
61 
     | 
    
         | 
| 
       61 
62 
     | 
    
         
             
                def request(method="GET", uri="", opts={})
         
     | 
| 
       62 
63 
     | 
    
         
             
                  env = self.class.env_for(uri, opts.merge(:method => method))
         
     | 
| 
         @@ -182,7 +183,7 @@ module Rack 
     | 
|
| 
       182 
183 
     | 
    
         
             
                end
         
     | 
| 
       183 
184 
     | 
    
         | 
| 
       184 
185 
     | 
    
         
             
                def empty?
         
     | 
| 
       185 
     | 
    
         
            -
                  [201, 204, 304].include? status
         
     | 
| 
      
 186 
     | 
    
         
            +
                  [201, 204, 205, 304].include? status
         
     | 
| 
       186 
187 
     | 
    
         
             
                end
         
     | 
| 
       187 
188 
     | 
    
         
             
              end
         
     | 
| 
       188 
189 
     | 
    
         
             
            end
         
     | 
    
        data/lib/rack/multipart.rb
    CHANGED
    
    | 
         @@ -12,7 +12,7 @@ module Rack 
     | 
|
| 
       12 
12 
     | 
    
         
             
                MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
         
     | 
| 
       13 
13 
     | 
    
         
             
                TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
         
     | 
| 
       14 
14 
     | 
    
         
             
                CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
         
     | 
| 
       15 
     | 
    
         
            -
                DISPPARM = /;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN}) 
     | 
| 
      
 15 
     | 
    
         
            +
                DISPPARM = /;\s*(#{TOKEN})=("(?:\\"|[^"])*"|#{TOKEN})*/
         
     | 
| 
       16 
16 
     | 
    
         
             
                RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i
         
     | 
| 
       17 
17 
     | 
    
         
             
                BROKEN_QUOTED = /^#{CONDISP}.*;\sfilename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i
         
     | 
| 
       18 
18 
     | 
    
         
             
                BROKEN_UNQUOTED = /^#{CONDISP}.*;\sfilename=(#{TOKEN})/i
         
     | 
| 
         @@ -31,4 +31,4 @@ module Rack 
     | 
|
| 
       31 
31 
     | 
    
         
             
                end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
              end
         
     | 
| 
       34 
     | 
    
         
            -
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -78,16 +78,9 @@ module Rack 
     | 
|
| 
       78 
78 
     | 
    
         | 
| 
       79 
79 
     | 
    
         
             
                  def fast_forward_to_first_boundary
         
     | 
| 
       80 
80 
     | 
    
         
             
                    loop do
         
     | 
| 
       81 
     | 
    
         
            -
                       
     | 
| 
       82 
     | 
    
         
            -
                       
     | 
| 
       83 
     | 
    
         
            -
                       
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
                      while @buf.gsub!(/\A([^\n]*\n)/, '')
         
     | 
| 
       86 
     | 
    
         
            -
                        read_buffer = $1
         
     | 
| 
       87 
     | 
    
         
            -
                        return if read_buffer == full_boundary
         
     | 
| 
       88 
     | 
    
         
            -
                      end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                      raise EOFError, "bad content body" if Utils.bytesize(@buf) >= BUFSIZE
         
     | 
| 
      
 81 
     | 
    
         
            +
                      read_buffer = @io.gets
         
     | 
| 
      
 82 
     | 
    
         
            +
                      break if read_buffer == full_boundary
         
     | 
| 
      
 83 
     | 
    
         
            +
                      raise EOFError, "bad content body" if read_buffer.nil?
         
     | 
| 
       91 
84 
     | 
    
         
             
                    end
         
     | 
| 
       92 
85 
     | 
    
         
             
                  end
         
     | 
| 
       93 
86 
     | 
    
         | 
    
        data/lib/rack/reloader.rb
    CHANGED
    
    
    
        data/lib/rack/request.rb
    CHANGED
    
    | 
         @@ -72,6 +72,8 @@ module Rack 
     | 
|
| 
       72 
72 
     | 
    
         
             
                    'https'
         
     | 
| 
       73 
73 
     | 
    
         
             
                  elsif @env['HTTP_X_FORWARDED_SSL'] == 'on'
         
     | 
| 
       74 
74 
     | 
    
         
             
                    'https'
         
     | 
| 
      
 75 
     | 
    
         
            +
                  elsif @env['HTTP_X_FORWARDED_SCHEME']
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @env['HTTP_X_FORWARDED_SCHEME']
         
     | 
| 
       75 
77 
     | 
    
         
             
                  elsif @env['HTTP_X_FORWARDED_PROTO']
         
     | 
| 
       76 
78 
     | 
    
         
             
                    @env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
         
     | 
| 
       77 
79 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -113,15 +115,32 @@ module Rack 
     | 
|
| 
       113 
115 
     | 
    
         
             
                def script_name=(s); @env["SCRIPT_NAME"] = s.to_s             end
         
     | 
| 
       114 
116 
     | 
    
         
             
                def path_info=(s);   @env["PATH_INFO"] = s.to_s               end
         
     | 
| 
       115 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type DELETE
         
     | 
| 
       116 
120 
     | 
    
         
             
                def delete?;  request_method == "DELETE"  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                
         
     | 
| 
      
 122 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type GET
         
     | 
| 
       117 
123 
     | 
    
         
             
                def get?;     request_method == "GET"     end
         
     | 
| 
      
 124 
     | 
    
         
            +
                
         
     | 
| 
      
 125 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type HEAD
         
     | 
| 
       118 
126 
     | 
    
         
             
                def head?;    request_method == "HEAD"    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                
         
     | 
| 
      
 128 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type OPTIONS
         
     | 
| 
       119 
129 
     | 
    
         
             
                def options?; request_method == "OPTIONS" end
         
     | 
| 
      
 130 
     | 
    
         
            +
                
         
     | 
| 
      
 131 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type PATCH
         
     | 
| 
       120 
132 
     | 
    
         
             
                def patch?;   request_method == "PATCH"   end
         
     | 
| 
      
 133 
     | 
    
         
            +
                
         
     | 
| 
      
 134 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type POST
         
     | 
| 
       121 
135 
     | 
    
         
             
                def post?;    request_method == "POST"    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                
         
     | 
| 
      
 137 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type PUT
         
     | 
| 
       122 
138 
     | 
    
         
             
                def put?;     request_method == "PUT"     end
         
     | 
| 
      
 139 
     | 
    
         
            +
                
         
     | 
| 
      
 140 
     | 
    
         
            +
                # Checks the HTTP request method (or verb) to see if it was of type TRACE
         
     | 
| 
       123 
141 
     | 
    
         
             
                def trace?;   request_method == "TRACE"   end
         
     | 
| 
       124 
142 
     | 
    
         | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
       125 
144 
     | 
    
         
             
                # The set of form-data media-types. Requests that do not indicate
         
     | 
| 
       126 
145 
     | 
    
         
             
                # one of the media types presents in this list will not be eligible
         
     | 
| 
       127 
146 
     | 
    
         
             
                # for form-data / param parsing.
         
     | 
| 
         @@ -233,8 +252,8 @@ module Rack 
     | 
|
| 
       233 
252 
     | 
    
         
             
                  hash   = @env["rack.request.cookie_hash"] ||= {}
         
     | 
| 
       234 
253 
     | 
    
         
             
                  string = @env["HTTP_COOKIE"]
         
     | 
| 
       235 
254 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
                  hash.clear unless string
         
     | 
| 
       237 
255 
     | 
    
         
             
                  return hash if string == @env["rack.request.cookie_string"]
         
     | 
| 
      
 256 
     | 
    
         
            +
                  hash.clear
         
     | 
| 
       238 
257 
     | 
    
         | 
| 
       239 
258 
     | 
    
         
             
                  # According to RFC 2109:
         
     | 
| 
       240 
259 
     | 
    
         
             
                  #   If multiple cookies satisfy the criteria above, they are ordered in
         
     | 
| 
         @@ -245,7 +264,8 @@ module Rack 
     | 
|
| 
       245 
264 
     | 
    
         
             
                  @env["rack.request.cookie_string"] = string
         
     | 
| 
       246 
265 
     | 
    
         
             
                  hash
         
     | 
| 
       247 
266 
     | 
    
         
             
                rescue => error
         
     | 
| 
       248 
     | 
    
         
            -
                   
     | 
| 
      
 267 
     | 
    
         
            +
                  error.message.replace "cannot parse Cookie header: #{error.message}"
         
     | 
| 
      
 268 
     | 
    
         
            +
                  raise
         
     | 
| 
       249 
269 
     | 
    
         
             
                end
         
     | 
| 
       250 
270 
     | 
    
         | 
| 
       251 
271 
     | 
    
         
             
                def xhr?
         
     | 
| 
         @@ -278,23 +298,35 @@ module Rack 
     | 
|
| 
       278 
298 
     | 
    
         
             
                end
         
     | 
| 
       279 
299 
     | 
    
         | 
| 
       280 
300 
     | 
    
         
             
                def accept_encoding
         
     | 
| 
       281 
     | 
    
         
            -
                  @env["HTTP_ACCEPT_ENCODING"].to_s.split( 
     | 
| 
       282 
     | 
    
         
            -
                     
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
                    if  
     | 
| 
       285 
     | 
    
         
            -
                       
     | 
| 
       286 
     | 
    
         
            -
                    else
         
     | 
| 
       287 
     | 
    
         
            -
                      raise "Invalid value for Accept-Encoding: #{part.inspect}"
         
     | 
| 
      
 301 
     | 
    
         
            +
                  @env["HTTP_ACCEPT_ENCODING"].to_s.split(/\s*,\s*/).map do |part|
         
     | 
| 
      
 302 
     | 
    
         
            +
                    encoding, parameters = part.split(/\s*;\s*/, 2)
         
     | 
| 
      
 303 
     | 
    
         
            +
                    quality = 1.0
         
     | 
| 
      
 304 
     | 
    
         
            +
                    if parameters and /\Aq=([\d.]+)/ =~ parameters
         
     | 
| 
      
 305 
     | 
    
         
            +
                      quality = $1.to_f
         
     | 
| 
       288 
306 
     | 
    
         
             
                    end
         
     | 
| 
      
 307 
     | 
    
         
            +
                    [encoding, quality]
         
     | 
| 
       289 
308 
     | 
    
         
             
                  end
         
     | 
| 
       290 
309 
     | 
    
         
             
                end
         
     | 
| 
       291 
310 
     | 
    
         | 
| 
      
 311 
     | 
    
         
            +
                def trusted_proxy?(ip)
         
     | 
| 
      
 312 
     | 
    
         
            +
                  ip =~ /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|^::1$|^fd[0-9a-f]{2}:.+|^localhost$/i
         
     | 
| 
      
 313 
     | 
    
         
            +
                end
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
       292 
315 
     | 
    
         
             
                def ip
         
     | 
| 
       293 
     | 
    
         
            -
                   
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
                   
     | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
      
 316 
     | 
    
         
            +
                  remote_addrs = @env['REMOTE_ADDR'] ? @env['REMOTE_ADDR'].split(/[,\s]+/) : []
         
     | 
| 
      
 317 
     | 
    
         
            +
                  remote_addrs.reject! { |addr| trusted_proxy?(addr) }
         
     | 
| 
      
 318 
     | 
    
         
            +
                  
         
     | 
| 
      
 319 
     | 
    
         
            +
                  return remote_addrs.first if remote_addrs.any?
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                  forwarded_ips = @env['HTTP_X_FORWARDED_FOR'] ? @env['HTTP_X_FORWARDED_FOR'].strip.split(/[,\s]+/) : []
         
     | 
| 
      
 322 
     | 
    
         
            +
             
     | 
| 
      
 323 
     | 
    
         
            +
                  if client_ip = @env['HTTP_CLIENT_IP']
         
     | 
| 
      
 324 
     | 
    
         
            +
                    # If forwarded_ips doesn't include the client_ip, it might be an
         
     | 
| 
      
 325 
     | 
    
         
            +
                    # ip spoofing attempt, so we ignore HTTP_CLIENT_IP
         
     | 
| 
      
 326 
     | 
    
         
            +
                    return client_ip if forwarded_ips.include?(client_ip)
         
     | 
| 
       297 
327 
     | 
    
         
             
                  end
         
     | 
| 
      
 328 
     | 
    
         
            +
             
     | 
| 
      
 329 
     | 
    
         
            +
                  return forwarded_ips.reject { |ip| trusted_proxy?(ip) }.last || @env["REMOTE_ADDR"]
         
     | 
| 
       298 
330 
     | 
    
         
             
                end
         
     | 
| 
       299 
331 
     | 
    
         | 
| 
       300 
332 
     | 
    
         
             
                protected
         
     | 
    
        data/lib/rack/response.rb
    CHANGED
    
    | 
         @@ -19,7 +19,7 @@ module Rack 
     | 
|
| 
       19 
19 
     | 
    
         
             
              class Response
         
     | 
| 
       20 
20 
     | 
    
         
             
                attr_accessor :length
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                def initialize(body=[], status=200, header={} 
     | 
| 
      
 22 
     | 
    
         
            +
                def initialize(body=[], status=200, header={})
         
     | 
| 
       23 
23 
     | 
    
         
             
                  @status = status.to_i
         
     | 
| 
       24 
24 
     | 
    
         
             
                  @header = Utils::HeaderHash.new("Content-Type" => "text/html").
         
     | 
| 
       25 
25 
     | 
    
         
             
                                                  merge(header)
         
     | 
| 
         @@ -71,13 +71,12 @@ module Rack 
     | 
|
| 
       71 
71 
     | 
    
         
             
                def finish(&block)
         
     | 
| 
       72 
72 
     | 
    
         
             
                  @block = block
         
     | 
| 
       73 
73 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
                  if [204, 304].include?(status.to_i)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  if [204, 205, 304].include?(status.to_i)
         
     | 
| 
       75 
75 
     | 
    
         
             
                    header.delete "Content-Type"
         
     | 
| 
       76 
76 
     | 
    
         
             
                    header.delete "Content-Length"
         
     | 
| 
       77 
     | 
    
         
            -
                    close
         
     | 
| 
       78 
77 
     | 
    
         
             
                    [status.to_i, header, []]
         
     | 
| 
       79 
78 
     | 
    
         
             
                  else
         
     | 
| 
       80 
     | 
    
         
            -
                    [status.to_i, header,  
     | 
| 
      
 79 
     | 
    
         
            +
                    [status.to_i, header, self]
         
     | 
| 
       81 
80 
     | 
    
         
             
                  end
         
     | 
| 
       82 
81 
     | 
    
         
             
                end
         
     | 
| 
       83 
82 
     | 
    
         
             
                alias to_a finish           # For *response
         
     | 
| 
         @@ -113,19 +112,21 @@ module Rack 
     | 
|
| 
       113 
112 
     | 
    
         
             
                alias headers header
         
     | 
| 
       114 
113 
     | 
    
         | 
| 
       115 
114 
     | 
    
         
             
                module Helpers
         
     | 
| 
       116 
     | 
    
         
            -
                  def invalid?;        
     | 
| 
      
 115 
     | 
    
         
            +
                  def invalid?;       status < 100 || status >= 600;        end
         
     | 
| 
       117 
116 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                  def informational?;  
     | 
| 
       119 
     | 
    
         
            -
                  def successful?;     
     | 
| 
       120 
     | 
    
         
            -
                  def redirection?;    
     | 
| 
       121 
     | 
    
         
            -
                  def client_error?;   
     | 
| 
       122 
     | 
    
         
            -
                  def server_error?;   
     | 
| 
      
 117 
     | 
    
         
            +
                  def informational?; status >= 100 && status < 200;        end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def successful?;    status >= 200 && status < 300;        end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  def redirection?;   status >= 300 && status < 400;        end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  def client_error?;  status >= 400 && status < 500;        end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  def server_error?;  status >= 500 && status < 600;        end
         
     | 
| 
       123 
122 
     | 
    
         | 
| 
       124 
     | 
    
         
            -
                  def ok?;             
     | 
| 
       125 
     | 
    
         
            -
                  def  
     | 
| 
       126 
     | 
    
         
            -
                  def  
     | 
| 
      
 123 
     | 
    
         
            +
                  def ok?;            status == 200;                        end
         
     | 
| 
      
 124 
     | 
    
         
            +
                  def bad_request?;   status == 400;                        end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  def forbidden?;     status == 403;                        end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  def not_found?;     status == 404;                        end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  def unprocessable?; status == 422;                        end
         
     | 
| 
       127 
128 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
                  def redirect?;      [301, 302, 303, 307].include?  
     | 
| 
      
 129 
     | 
    
         
            +
                  def redirect?;      [301, 302, 303, 307].include? status; end
         
     | 
| 
       129 
130 
     | 
    
         | 
| 
       130 
131 
     | 
    
         
             
                  # Headers
         
     | 
| 
       131 
132 
     | 
    
         
             
                  attr_reader :headers, :original_headers
         
     | 
    
        data/lib/rack/sendfile.rb
    CHANGED
    
    | 
         @@ -46,10 +46,11 @@ module Rack 
     | 
|
| 
       46 
46 
     | 
    
         
             
              #     proxy_pass         http://127.0.0.1:8080/;
         
     | 
| 
       47 
47 
     | 
    
         
             
              #   }
         
     | 
| 
       48 
48 
     | 
    
         
             
              #
         
     | 
| 
       49 
     | 
    
         
            -
              # Note that the X-Sendfile-Type header must be set exactly as shown above. 
     | 
| 
       50 
     | 
    
         
            -
              # X-Accel-Mapping header should specify the  
     | 
| 
       51 
     | 
    
         
            -
              # equals sign (=), followed name of the  
     | 
| 
       52 
     | 
    
         
            -
              # to. The middleware performs a simple substitution on the 
     | 
| 
      
 49 
     | 
    
         
            +
              # Note that the X-Sendfile-Type header must be set exactly as shown above.
         
     | 
| 
      
 50 
     | 
    
         
            +
              # The X-Accel-Mapping header should specify the location on the file system,
         
     | 
| 
      
 51 
     | 
    
         
            +
              # followed by an equals sign (=), followed name of the private URL pattern
         
     | 
| 
      
 52 
     | 
    
         
            +
              # that it maps to. The middleware performs a simple substitution on the
         
     | 
| 
      
 53 
     | 
    
         
            +
              # resulting path.
         
     | 
| 
       53 
54 
     | 
    
         
             
              #
         
     | 
| 
       54 
55 
     | 
    
         
             
              # See Also: http://wiki.codemongers.com/NginxXSendfile
         
     | 
| 
       55 
56 
     | 
    
         
             
              #
         
     | 
| 
         @@ -104,10 +105,11 @@ module Rack 
     | 
|
| 
       104 
105 
     | 
    
         
             
                    when 'X-Accel-Redirect'
         
     | 
| 
       105 
106 
     | 
    
         
             
                      path = F.expand_path(body.to_path)
         
     | 
| 
       106 
107 
     | 
    
         
             
                      if url = map_accel_path(env, path)
         
     | 
| 
      
 108 
     | 
    
         
            +
                        headers['Content-Length'] = '0'
         
     | 
| 
       107 
109 
     | 
    
         
             
                        headers[type] = url
         
     | 
| 
       108 
110 
     | 
    
         
             
                        body = []
         
     | 
| 
       109 
111 
     | 
    
         
             
                      else
         
     | 
| 
       110 
     | 
    
         
            -
                        env['rack.errors']  
     | 
| 
      
 112 
     | 
    
         
            +
                        env['rack.errors'].puts "X-Accel-Mapping header missing"
         
     | 
| 
       111 
113 
     | 
    
         
             
                      end
         
     | 
| 
       112 
114 
     | 
    
         
             
                    when 'X-Sendfile', 'X-Lighttpd-Send-File'
         
     | 
| 
       113 
115 
     | 
    
         
             
                      path = F.expand_path(body.to_path)
         
     | 
| 
         @@ -116,7 +118,7 @@ module Rack 
     | 
|
| 
       116 
118 
     | 
    
         
             
                      body = []
         
     | 
| 
       117 
119 
     | 
    
         
             
                    when '', nil
         
     | 
| 
       118 
120 
     | 
    
         
             
                    else
         
     | 
| 
       119 
     | 
    
         
            -
                      env['rack.errors']  
     | 
| 
      
 121 
     | 
    
         
            +
                      env['rack.errors'].puts "Unknown x-sendfile variation: '#{variation}'.\n"
         
     | 
| 
       120 
122 
     | 
    
         
             
                    end
         
     | 
| 
       121 
123 
     | 
    
         
             
                  end
         
     | 
| 
       122 
124 
     | 
    
         
             
                  [status, headers, body]
         
     | 
    
        data/lib/rack/server.rb
    CHANGED
    
    | 
         @@ -26,7 +26,7 @@ module Rack 
     | 
|
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
                      opts.on("-I", "--include PATH",
         
     | 
| 
       28 
28 
     | 
    
         
             
                              "specify $LOAD_PATH (may be used more than once)") { |path|
         
     | 
| 
       29 
     | 
    
         
            -
                         
     | 
| 
      
 29 
     | 
    
         
            +
                        options[:include] = path.split(":")
         
     | 
| 
       30 
30 
     | 
    
         
             
                      }
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                      opts.on("-r", "--require LIBRARY",
         
     | 
| 
         @@ -226,7 +226,7 @@ module Rack 
     | 
|
| 
       226 
226 
     | 
    
         
             
                  self.class.middleware
         
     | 
| 
       227 
227 
     | 
    
         
             
                end
         
     | 
| 
       228 
228 
     | 
    
         | 
| 
       229 
     | 
    
         
            -
                def start
         
     | 
| 
      
 229 
     | 
    
         
            +
                def start &blk
         
     | 
| 
       230 
230 
     | 
    
         
             
                  if options[:warn]
         
     | 
| 
       231 
231 
     | 
    
         
             
                    $-w = true
         
     | 
| 
       232 
232 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -247,14 +247,11 @@ module Rack 
     | 
|
| 
       247 
247 
     | 
    
         
             
                    pp app
         
     | 
| 
       248 
248 
     | 
    
         
             
                  end
         
     | 
| 
       249 
249 
     | 
    
         | 
| 
       250 
     | 
    
         
            -
                  check_pid! if options[:pid]
         
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
       252 
250 
     | 
    
         
             
                  # Touch the wrapped app, so that the config.ru is loaded before
         
     | 
| 
       253 
251 
     | 
    
         
             
                  # daemonization (i.e. before chdir, etc).
         
     | 
| 
       254 
252 
     | 
    
         
             
                  wrapped_app
         
     | 
| 
       255 
253 
     | 
    
         | 
| 
       256 
254 
     | 
    
         
             
                  daemonize_app if options[:daemonize]
         
     | 
| 
       257 
     | 
    
         
            -
             
     | 
| 
       258 
255 
     | 
    
         
             
                  write_pid if options[:pid]
         
     | 
| 
       259 
256 
     | 
    
         | 
| 
       260 
257 
     | 
    
         
             
                  trap(:INT) do
         
     | 
| 
         @@ -265,7 +262,7 @@ module Rack 
     | 
|
| 
       265 
262 
     | 
    
         
             
                    end
         
     | 
| 
       266 
263 
     | 
    
         
             
                  end
         
     | 
| 
       267 
264 
     | 
    
         | 
| 
       268 
     | 
    
         
            -
                  server.run wrapped_app, options
         
     | 
| 
      
 265 
     | 
    
         
            +
                  server.run wrapped_app, options, &blk
         
     | 
| 
       269 
266 
     | 
    
         
             
                end
         
     | 
| 
       270 
267 
     | 
    
         | 
| 
       271 
268 
     | 
    
         
             
                def server
         
     | 
| 
         @@ -277,7 +274,7 @@ module Rack 
     | 
|
| 
       277 
274 
     | 
    
         
             
                    options = default_options
         
     | 
| 
       278 
275 
     | 
    
         | 
| 
       279 
276 
     | 
    
         
             
                    # Don't evaluate CGI ISINDEX parameters.
         
     | 
| 
       280 
     | 
    
         
            -
                    # http:// 
     | 
| 
      
 277 
     | 
    
         
            +
                    # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
         
     | 
| 
       281 
278 
     | 
    
         
             
                    args.clear if ENV.include?("REQUEST_METHOD")
         
     | 
| 
       282 
279 
     | 
    
         | 
| 
       283 
280 
     | 
    
         
             
                    options.merge! opt_parser.parse!(args)
         
     | 
| 
         @@ -322,28 +319,5 @@ module Rack 
     | 
|
| 
       322 
319 
     | 
    
         
             
                    ::File.open(options[:pid], 'w'){ |f| f.write("#{Process.pid}") }
         
     | 
| 
       323 
320 
     | 
    
         
             
                    at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
         
     | 
| 
       324 
321 
     | 
    
         
             
                  end
         
     | 
| 
       325 
     | 
    
         
            -
             
     | 
| 
       326 
     | 
    
         
            -
                  def check_pid!
         
     | 
| 
       327 
     | 
    
         
            -
                    case pidfile_process_status
         
     | 
| 
       328 
     | 
    
         
            -
                    when :running, :not_owned
         
     | 
| 
       329 
     | 
    
         
            -
                      $stderr.puts "A server is already running. Check #{options[:pid]}."
         
     | 
| 
       330 
     | 
    
         
            -
                      exit(1)
         
     | 
| 
       331 
     | 
    
         
            -
                    when :dead
         
     | 
| 
       332 
     | 
    
         
            -
                      ::File.delete(options[:pid])
         
     | 
| 
       333 
     | 
    
         
            -
                    end
         
     | 
| 
       334 
     | 
    
         
            -
                  end
         
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
                  def pidfile_process_status
         
     | 
| 
       337 
     | 
    
         
            -
                    return :exited unless ::File.exist?(options[:pid])
         
     | 
| 
       338 
     | 
    
         
            -
             
     | 
| 
       339 
     | 
    
         
            -
                    pid = ::File.read(options[:pid]).to_i
         
     | 
| 
       340 
     | 
    
         
            -
                    Process.kill(0, pid)
         
     | 
| 
       341 
     | 
    
         
            -
                    :running
         
     | 
| 
       342 
     | 
    
         
            -
                  rescue Errno::ESRCH
         
     | 
| 
       343 
     | 
    
         
            -
                    :dead
         
     | 
| 
       344 
     | 
    
         
            -
                  rescue Errno::EPERM
         
     | 
| 
       345 
     | 
    
         
            -
                    :not_owned
         
     | 
| 
       346 
     | 
    
         
            -
                  end
         
     | 
| 
       347 
     | 
    
         
            -
             
     | 
| 
       348 
322 
     | 
    
         
             
              end
         
     | 
| 
       349 
323 
     | 
    
         
             
            end
         
     | 
| 
         @@ -95,8 +95,11 @@ module Rack 
     | 
|
| 
       95 
95 
     | 
    
         
             
                    end
         
     | 
| 
       96 
96 
     | 
    
         | 
| 
       97 
97 
     | 
    
         
             
                    def inspect
         
     | 
| 
       98 
     | 
    
         
            -
                       
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
      
 98 
     | 
    
         
            +
                      if loaded?
         
     | 
| 
      
 99 
     | 
    
         
            +
                        super
         
     | 
| 
      
 100 
     | 
    
         
            +
                      else
         
     | 
| 
      
 101 
     | 
    
         
            +
                        "#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>"
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
       100 
103 
     | 
    
         
             
                    end
         
     | 
| 
       101 
104 
     | 
    
         | 
| 
       102 
105 
     | 
    
         
             
                    def exists?
         
     | 
| 
         @@ -108,6 +111,11 @@ module Rack 
     | 
|
| 
       108 
111 
     | 
    
         
             
                      @loaded
         
     | 
| 
       109 
112 
     | 
    
         
             
                    end
         
     | 
| 
       110 
113 
     | 
    
         | 
| 
      
 114 
     | 
    
         
            +
                    def empty?
         
     | 
| 
      
 115 
     | 
    
         
            +
                      load_for_read!
         
     | 
| 
      
 116 
     | 
    
         
            +
                      super
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
       111 
119 
     | 
    
         
             
                  private
         
     | 
| 
       112 
120 
     | 
    
         | 
| 
       113 
121 
     | 
    
         
             
                    def load_for_read!
         
     | 
| 
         @@ -144,7 +152,9 @@ module Rack 
     | 
|
| 
       144 
152 
     | 
    
         
             
                  #   'rack.session'
         
     | 
| 
       145 
153 
     | 
    
         
             
                  # * :path, :domain, :expire_after, :secure, and :httponly set the related
         
     | 
| 
       146 
154 
     | 
    
         
             
                  #   cookie options as by Rack::Response#add_cookie
         
     | 
| 
       147 
     | 
    
         
            -
                  # * : 
     | 
| 
      
 155 
     | 
    
         
            +
                  # * :skip will not a set a cookie in the response nor update the session state
         
     | 
| 
      
 156 
     | 
    
         
            +
                  # * :defer will not set a cookie in the response but still update the session
         
     | 
| 
      
 157 
     | 
    
         
            +
                  #   state if it is used with a backend
         
     | 
| 
       148 
158 
     | 
    
         
             
                  # * :renew (implementation dependent) will prompt the generation of a new
         
     | 
| 
       149 
159 
     | 
    
         
             
                  #   session id, and migration of data to be referenced at the new id. If
         
     | 
| 
       150 
160 
     | 
    
         
             
                  #   :defer is set, it will be overridden and the cookie will be set.
         
     | 
| 
         @@ -260,21 +270,30 @@ module Rack 
     | 
|
| 
       260 
270 
     | 
    
         
             
                    end
         
     | 
| 
       261 
271 
     | 
    
         | 
| 
       262 
272 
     | 
    
         
             
                    # Session should be commited if it was loaded, any of specific options like :renew, :drop
         
     | 
| 
       263 
     | 
    
         
            -
                    # or :expire_after was given and the security permissions match.
         
     | 
| 
      
 273 
     | 
    
         
            +
                    # or :expire_after was given and the security permissions match. Skips if skip is given.
         
     | 
| 
       264 
274 
     | 
    
         | 
| 
       265 
275 
     | 
    
         
             
                    def commit_session?(env, session, options)
         
     | 
| 
       266 
     | 
    
         
            -
                       
     | 
| 
      
 276 
     | 
    
         
            +
                      if options[:skip]
         
     | 
| 
      
 277 
     | 
    
         
            +
                        false
         
     | 
| 
      
 278 
     | 
    
         
            +
                      else
         
     | 
| 
      
 279 
     | 
    
         
            +
                        has_session = loaded_session?(session) || forced_session_update?(session, options)
         
     | 
| 
      
 280 
     | 
    
         
            +
                        has_session && security_matches?(env, options)
         
     | 
| 
      
 281 
     | 
    
         
            +
                      end
         
     | 
| 
       267 
282 
     | 
    
         
             
                    end
         
     | 
| 
       268 
283 
     | 
    
         | 
| 
       269 
284 
     | 
    
         
             
                    def loaded_session?(session)
         
     | 
| 
       270 
285 
     | 
    
         
             
                      !session.is_a?(SessionHash) || session.loaded?
         
     | 
| 
       271 
286 
     | 
    
         
             
                    end
         
     | 
| 
       272 
287 
     | 
    
         | 
| 
      
 288 
     | 
    
         
            +
                    def forced_session_update?(session, options)
         
     | 
| 
      
 289 
     | 
    
         
            +
                      force_options?(options) && session && !session.empty?
         
     | 
| 
      
 290 
     | 
    
         
            +
                    end
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
       273 
292 
     | 
    
         
             
                    def force_options?(options)
         
     | 
| 
       274 
293 
     | 
    
         
             
                      options.values_at(:renew, :drop, :defer, :expire_after).any?
         
     | 
| 
       275 
294 
     | 
    
         
             
                    end
         
     | 
| 
       276 
295 
     | 
    
         | 
| 
       277 
     | 
    
         
            -
                    def  
     | 
| 
      
 296 
     | 
    
         
            +
                    def security_matches?(env, options)
         
     | 
| 
       278 
297 
     | 
    
         
             
                      return true unless options[:secure]
         
     | 
| 
       279 
298 
     | 
    
         
             
                      request = Rack::Request.new(env)
         
     | 
| 
       280 
299 
     | 
    
         
             
                      request.ssl?
         
     | 
    
        data/lib/rack/session/cookie.rb
    CHANGED
    
    | 
         @@ -14,6 +14,7 @@ module Rack 
     | 
|
| 
       14 
14 
     | 
    
         
             
                # Both methods must take a string and return a string.
         
     | 
| 
       15 
15 
     | 
    
         
             
                #
         
     | 
| 
       16 
16 
     | 
    
         
             
                # When the secret key is set, cookie data is checked for data integrity.
         
     | 
| 
      
 17 
     | 
    
         
            +
                # The old secret key is also accepted and allows graceful secret rotation.
         
     | 
| 
       17 
18 
     | 
    
         
             
                #
         
     | 
| 
       18 
19 
     | 
    
         
             
                # Example:
         
     | 
| 
       19 
20 
     | 
    
         
             
                #
         
     | 
| 
         @@ -21,14 +22,15 @@ module Rack 
     | 
|
| 
       21 
22 
     | 
    
         
             
                #                                :domain => 'foo.com',
         
     | 
| 
       22 
23 
     | 
    
         
             
                #                                :path => '/',
         
     | 
| 
       23 
24 
     | 
    
         
             
                #                                :expire_after => 2592000,
         
     | 
| 
       24 
     | 
    
         
            -
                #                                :secret => 'change_me'
         
     | 
| 
      
 25 
     | 
    
         
            +
                #                                :secret => 'change_me',
         
     | 
| 
      
 26 
     | 
    
         
            +
                #                                :old_secret => 'also_change_me'
         
     | 
| 
       25 
27 
     | 
    
         
             
                #
         
     | 
| 
       26 
28 
     | 
    
         
             
                #     All parameters are optional.
         
     | 
| 
       27 
29 
     | 
    
         
             
                #
         
     | 
| 
       28 
30 
     | 
    
         
             
                # Example of a cookie with no encoding:
         
     | 
| 
       29 
31 
     | 
    
         
             
                #
         
     | 
| 
       30 
32 
     | 
    
         
             
                #   Rack::Session::Cookie.new(application, {
         
     | 
| 
       31 
     | 
    
         
            -
                #     :coder =>  
     | 
| 
      
 33 
     | 
    
         
            +
                #     :coder => Rack::Session::Cookie::Identity.new
         
     | 
| 
       32 
34 
     | 
    
         
             
                #   })
         
     | 
| 
       33 
35 
     | 
    
         
             
                #
         
     | 
| 
       34 
36 
     | 
    
         
             
                # Example of a cookie with custom encoding:
         
     | 
| 
         @@ -80,15 +82,7 @@ module Rack 
     | 
|
| 
       80 
82 
     | 
    
         | 
| 
       81 
83 
     | 
    
         
             
                  def initialize(app, options={})
         
     | 
| 
       82 
84 
     | 
    
         
             
                    @secret = options[:secret]
         
     | 
| 
       83 
     | 
    
         
            -
                     
     | 
| 
       84 
     | 
    
         
            -
                    SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
         
     | 
| 
       85 
     | 
    
         
            -
                    This poses a security threat. It is strongly recommended that you
         
     | 
| 
       86 
     | 
    
         
            -
                    provide a secret to prevent exploits that may be possible from crafted
         
     | 
| 
       87 
     | 
    
         
            -
                    cookies. This will not be supported in future versions of Rack, and
         
     | 
| 
       88 
     | 
    
         
            -
                    future versions will even invalidate your existing user cookies.
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                    Called from: #{caller[0]}.
         
     | 
| 
       91 
     | 
    
         
            -
                    MSG
         
     | 
| 
      
 85 
     | 
    
         
            +
                    @old_secret = options[:old_secret]
         
     | 
| 
       92 
86 
     | 
    
         
             
                    @coder  = options[:coder] ||= Base64::Marshal.new
         
     | 
| 
       93 
87 
     | 
    
         
             
                    super(app, options.merge!(:cookie_only => true))
         
     | 
| 
       94 
88 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -110,9 +104,11 @@ module Rack 
     | 
|
| 
       110 
104 
     | 
    
         
             
                      request = Rack::Request.new(env)
         
     | 
| 
       111 
105 
     | 
    
         
             
                      session_data = request.cookies[@key]
         
     | 
| 
       112 
106 
     | 
    
         | 
| 
       113 
     | 
    
         
            -
                      if @secret && session_data
         
     | 
| 
      
 107 
     | 
    
         
            +
                      if (@secret || @old_secret) && session_data
         
     | 
| 
       114 
108 
     | 
    
         
             
                        session_data, digest = session_data.split("--")
         
     | 
| 
       115 
     | 
    
         
            -
                        session_data  
     | 
| 
      
 109 
     | 
    
         
            +
                        if (digest != generate_hmac(session_data, @secret)) && (digest != generate_hmac(session_data, @old_secret))
         
     | 
| 
      
 110 
     | 
    
         
            +
                          session_data = nil
         
     | 
| 
      
 111 
     | 
    
         
            +
                        end
         
     | 
| 
       116 
112 
     | 
    
         
             
                      end
         
     | 
| 
       117 
113 
     | 
    
         | 
| 
       118 
114 
     | 
    
         
             
                      coder.decode(session_data) || {}
         
     | 
| 
         @@ -136,7 +132,7 @@ module Rack 
     | 
|
| 
       136 
132 
     | 
    
         
             
                    session_data = coder.encode(session)
         
     | 
| 
       137 
133 
     | 
    
         | 
| 
       138 
134 
     | 
    
         
             
                    if @secret
         
     | 
| 
       139 
     | 
    
         
            -
                      session_data = "#{session_data}--#{generate_hmac(session_data)}"
         
     | 
| 
      
 135 
     | 
    
         
            +
                      session_data = "#{session_data}--#{generate_hmac(session_data, @secret)}"
         
     | 
| 
       140 
136 
     | 
    
         
             
                    end
         
     | 
| 
       141 
137 
     | 
    
         | 
| 
       142 
138 
     | 
    
         
             
                    if session_data.size > (4096 - @key.size)
         
     | 
| 
         @@ -152,8 +148,8 @@ module Rack 
     | 
|
| 
       152 
148 
     | 
    
         
             
                    generate_sid unless options[:drop]
         
     | 
| 
       153 
149 
     | 
    
         
             
                  end
         
     | 
| 
       154 
150 
     | 
    
         | 
| 
       155 
     | 
    
         
            -
                  def generate_hmac(data)
         
     | 
| 
       156 
     | 
    
         
            -
                    OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new,  
     | 
| 
      
 151 
     | 
    
         
            +
                  def generate_hmac(data, secret)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, data)
         
     | 
| 
       157 
153 
     | 
    
         
             
                  end
         
     | 
| 
       158 
154 
     | 
    
         | 
| 
       159 
155 
     | 
    
         
             
                end
         
     |