rack 1.5.5 → 1.6.0.beta
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.
- checksums.yaml +4 -4
- data/KNOWN-ISSUES +14 -0
- data/README.rdoc +10 -6
- data/Rakefile +3 -4
- data/SPEC +59 -23
- data/lib/rack.rb +2 -1
- data/lib/rack/auth/abstract/request.rb +1 -1
- data/lib/rack/auth/basic.rb +1 -1
- data/lib/rack/auth/digest/md5.rb +1 -1
- data/lib/rack/backports/uri/common_18.rb +1 -1
- data/lib/rack/builder.rb +19 -4
- data/lib/rack/cascade.rb +2 -2
- data/lib/rack/chunked.rb +12 -1
- data/lib/rack/commonlogger.rb +13 -5
- data/lib/rack/conditionalget.rb +14 -2
- data/lib/rack/content_length.rb +5 -1
- data/lib/rack/deflater.rb +52 -13
- data/lib/rack/directory.rb +8 -2
- data/lib/rack/etag.rb +14 -6
- data/lib/rack/file.rb +10 -14
- data/lib/rack/handler.rb +2 -0
- data/lib/rack/handler/fastcgi.rb +4 -1
- data/lib/rack/handler/mongrel.rb +8 -2
- data/lib/rack/handler/scgi.rb +4 -1
- data/lib/rack/handler/thin.rb +8 -2
- data/lib/rack/handler/webrick.rb +46 -6
- data/lib/rack/head.rb +7 -2
- data/lib/rack/lint.rb +73 -25
- data/lib/rack/lobster.rb +8 -3
- data/lib/rack/methodoverride.rb +14 -3
- data/lib/rack/mime.rb +1 -15
- data/lib/rack/mock.rb +15 -7
- data/lib/rack/multipart.rb +2 -2
- data/lib/rack/multipart/parser.rb +107 -53
- data/lib/rack/multipart/uploaded_file.rb +2 -2
- data/lib/rack/nulllogger.rb +21 -2
- data/lib/rack/request.rb +38 -24
- data/lib/rack/response.rb +5 -0
- data/lib/rack/sendfile.rb +10 -5
- data/lib/rack/server.rb +45 -17
- data/lib/rack/session/abstract/id.rb +7 -6
- data/lib/rack/session/cookie.rb +17 -7
- data/lib/rack/session/memcache.rb +4 -4
- data/lib/rack/session/pool.rb +3 -6
- data/lib/rack/showexceptions.rb +20 -11
- data/lib/rack/showstatus.rb +1 -1
- data/lib/rack/static.rb +27 -30
- data/lib/rack/tempfile_reaper.rb +22 -0
- data/lib/rack/urlmap.rb +17 -3
- data/lib/rack/utils.rb +78 -47
- data/lib/rack/utils/okjson.rb +90 -91
- data/rack.gemspec +3 -3
- data/test/multipart/filename_and_no_name +6 -0
- data/test/multipart/invalid_character +6 -0
- data/test/spec_builder.rb +13 -4
- data/test/spec_chunked.rb +16 -0
- data/test/spec_commonlogger.rb +36 -0
- data/test/spec_content_length.rb +3 -1
- data/test/spec_deflater.rb +283 -148
- data/test/spec_etag.rb +11 -2
- data/test/spec_file.rb +11 -3
- data/test/spec_head.rb +2 -0
- data/test/spec_lobster.rb +1 -1
- data/test/spec_mock.rb +8 -0
- data/test/spec_multipart.rb +111 -49
- data/test/spec_request.rb +109 -25
- data/test/spec_response.rb +30 -0
- data/test/spec_server.rb +20 -5
- data/test/spec_session_cookie.rb +45 -2
- data/test/spec_session_memcache.rb +1 -1
- data/test/spec_showexceptions.rb +29 -36
- data/test/spec_showstatus.rb +19 -0
- data/test/spec_tempfile_reaper.rb +63 -0
- data/test/spec_urlmap.rb +23 -0
- data/test/spec_utils.rb +60 -10
- data/test/spec_webrick.rb +41 -0
- metadata +12 -9
- data/test/cgi/lighttpd.errors +0 -1
- data/test/multipart/three_files_three_fields +0 -31
    
        data/test/spec_content_length.rb
    CHANGED
    
    | @@ -62,7 +62,9 @@ describe Rack::ContentLength do | |
| 62 62 | 
             
                end.new(%w[one two three])
         | 
| 63 63 |  | 
| 64 64 | 
             
                app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
         | 
| 65 | 
            -
                content_length(app).call(request)
         | 
| 65 | 
            +
                response = content_length(app).call(request)
         | 
| 66 | 
            +
                body.closed.should.equal nil
         | 
| 67 | 
            +
                response[2].close
         | 
| 66 68 | 
             
                body.closed.should.equal true
         | 
| 67 69 | 
             
              end
         | 
| 68 70 |  | 
    
        data/test/spec_deflater.rb
    CHANGED
    
    | @@ -6,199 +6,334 @@ require 'rack/mock' | |
| 6 6 | 
             
            require 'zlib'
         | 
| 7 7 |  | 
| 8 8 | 
             
            describe Rack::Deflater do
         | 
| 9 | 
            -
              def deflater(app)
         | 
| 10 | 
            -
                Rack::Lint.new Rack::Deflater.new(app)
         | 
| 11 | 
            -
              end
         | 
| 12 9 |  | 
| 13 | 
            -
              def build_response(status, body, accept_encoding,  | 
| 14 | 
            -
                body = [body] | 
| 10 | 
            +
              def build_response(status, body, accept_encoding, options = {})
         | 
| 11 | 
            +
                body = [body] if body.respond_to? :to_str
         | 
| 15 12 | 
             
                app = lambda do |env|
         | 
| 16 | 
            -
                  res = [status, {}, body]
         | 
| 17 | 
            -
                  res[1][ | 
| 13 | 
            +
                  res = [status, options['response_headers'] || {}, body]
         | 
| 14 | 
            +
                  res[1]['Content-Type'] = 'text/plain' unless res[0] == 304
         | 
| 18 15 | 
             
                  res
         | 
| 19 16 | 
             
                end
         | 
| 20 | 
            -
                request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding))
         | 
| 21 | 
            -
                response = deflater(app).call(request)
         | 
| 22 17 |  | 
| 23 | 
            -
                 | 
| 24 | 
            -
             | 
| 18 | 
            +
                request = Rack::MockRequest.env_for('', (options['request_headers'] || {}).merge('HTTP_ACCEPT_ENCODING' => accept_encoding))
         | 
| 19 | 
            +
                deflater = Rack::Lint.new Rack::Deflater.new(app, options['deflater_options'] || {})
         | 
| 25 20 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
                inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
         | 
| 28 | 
            -
                inflater.inflate(buf) << inflater.finish
         | 
| 21 | 
            +
                deflater.call(request)
         | 
| 29 22 | 
             
              end
         | 
| 30 23 |  | 
| 31 | 
            -
               | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
               | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
                 | 
| 50 | 
            -
             | 
| 24 | 
            +
              ##
         | 
| 25 | 
            +
              # Constructs response object and verifies if it yields right results
         | 
| 26 | 
            +
              #
         | 
| 27 | 
            +
              # [expected_status] expected response status, e.g. 200, 304
         | 
| 28 | 
            +
              # [expected_body] expected response body
         | 
| 29 | 
            +
              # [accept_encoing] what Accept-Encoding header to send and expect, e.g.
         | 
| 30 | 
            +
              #                  'deflate' - accepts and expects deflate encoding in response
         | 
| 31 | 
            +
              #                  { 'gzip' => nil } - accepts gzip but expects no encoding in response
         | 
| 32 | 
            +
              # [options] hash of request options, i.e.
         | 
| 33 | 
            +
              #           'app_status' - what status dummy app should return (may be changed by deflater at some point)
         | 
| 34 | 
            +
              #           'app_body' - what body dummy app should return (may be changed by deflater at some point)
         | 
| 35 | 
            +
              #           'request_headers' - extra reqest headers to be sent
         | 
| 36 | 
            +
              #           'response_headers' - extra response headers to be returned
         | 
| 37 | 
            +
              #           'deflater_options' - options passed to deflater middleware
         | 
| 38 | 
            +
              # [block] useful for doing some extra verification
         | 
| 39 | 
            +
              def verify(expected_status, expected_body, accept_encoding, options = {}, &block)
         | 
| 40 | 
            +
                accept_encoding, expected_encoding = if accept_encoding.kind_of?(Hash)
         | 
| 41 | 
            +
                  [accept_encoding.keys.first, accept_encoding.values.first]
         | 
| 42 | 
            +
                else
         | 
| 43 | 
            +
                  [accept_encoding, accept_encoding.dup]
         | 
| 44 | 
            +
                end
         | 
| 51 45 |  | 
| 52 | 
            -
                 | 
| 46 | 
            +
                # build response
         | 
| 47 | 
            +
                status, headers, body = build_response(
         | 
| 48 | 
            +
                  options['app_status'] || expected_status,
         | 
| 49 | 
            +
                  options['app_body'] || expected_body,
         | 
| 50 | 
            +
                  accept_encoding,
         | 
| 51 | 
            +
                  options
         | 
| 52 | 
            +
                )
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # verify status
         | 
| 55 | 
            +
                status.should.equal(expected_status)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                # verify body
         | 
| 58 | 
            +
                unless options['skip_body_verify']
         | 
| 59 | 
            +
                  body_text = ''
         | 
| 60 | 
            +
                  body.each { |part| body_text << part }
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  deflated_body = case expected_encoding
         | 
| 63 | 
            +
                  when 'deflate'
         | 
| 64 | 
            +
                    inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
         | 
| 65 | 
            +
                    inflater.inflate(body_text) << inflater.finish
         | 
| 66 | 
            +
                  when 'gzip'
         | 
| 67 | 
            +
                    io = StringIO.new(body_text)
         | 
| 68 | 
            +
                    gz = Zlib::GzipReader.new(io)
         | 
| 69 | 
            +
                    tmp = gz.read
         | 
| 70 | 
            +
                    gz.close
         | 
| 71 | 
            +
                    tmp
         | 
| 72 | 
            +
                  else
         | 
| 73 | 
            +
                    body_text
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  deflated_body.should.equal(expected_body)
         | 
| 77 | 
            +
                end
         | 
| 53 78 |  | 
| 54 | 
            -
                response | 
| 55 | 
            -
                 | 
| 56 | 
            -
                  "Content-Encoding" => "deflate",
         | 
| 57 | 
            -
                  "Vary" => "Accept-Encoding",
         | 
| 58 | 
            -
                  "Content-Type" => "text/plain"
         | 
| 59 | 
            -
                })
         | 
| 60 | 
            -
                buf = []
         | 
| 61 | 
            -
                inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
         | 
| 62 | 
            -
                response[2].each { |part| buf << inflater.inflate(part) }
         | 
| 63 | 
            -
                buf << inflater.finish
         | 
| 64 | 
            -
                buf.delete_if { |part| part.empty? }
         | 
| 65 | 
            -
                buf.join.should.equal("foobar")
         | 
| 79 | 
            +
                # yield full response verification
         | 
| 80 | 
            +
                yield(status, headers, body) if block_given?
         | 
| 66 81 | 
             
              end
         | 
| 67 82 |  | 
| 68 | 
            -
               | 
| 69 | 
            -
             | 
| 70 | 
            -
                 | 
| 83 | 
            +
              should 'be able to deflate bodies that respond to each' do
         | 
| 84 | 
            +
                app_body = Object.new
         | 
| 85 | 
            +
                class << app_body; def each; yield('foo'); yield('bar'); end; end
         | 
| 71 86 |  | 
| 72 | 
            -
                 | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
                 | 
| 79 | 
            -
                response[2].each { |part| buf << part }
         | 
| 80 | 
            -
                inflate(buf).should.equal("Hello world!")
         | 
| 87 | 
            +
                verify(200, 'foobar', 'deflate', { 'app_body' => app_body }) do |status, headers, body|
         | 
| 88 | 
            +
                  headers.should.equal({
         | 
| 89 | 
            +
                    'Content-Encoding' => 'deflate',
         | 
| 90 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 91 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 92 | 
            +
                  })
         | 
| 93 | 
            +
                end
         | 
| 81 94 | 
             
              end
         | 
| 82 95 |  | 
| 83 | 
            -
              should  | 
| 84 | 
            -
                 | 
| 85 | 
            -
                class <<  | 
| 96 | 
            +
              should 'flush deflated chunks to the client as they become ready' do
         | 
| 97 | 
            +
                app_body = Object.new
         | 
| 98 | 
            +
                class << app_body; def each; yield('foo'); yield('bar'); end; end
         | 
| 86 99 |  | 
| 87 | 
            -
                 | 
| 100 | 
            +
                verify(200, app_body, 'deflate', { 'skip_body_verify' => true }) do |status, headers, body|
         | 
| 101 | 
            +
                  headers.should.equal({
         | 
| 102 | 
            +
                    'Content-Encoding' => 'deflate',
         | 
| 103 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 104 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 105 | 
            +
                  })
         | 
| 88 106 |  | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
                   | 
| 92 | 
            -
                   | 
| 93 | 
            -
                  "Content-Type" => "text/plain"
         | 
| 94 | 
            -
                })
         | 
| 107 | 
            +
                  buf = []
         | 
| 108 | 
            +
                  inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
         | 
| 109 | 
            +
                  body.each { |part| buf << inflater.inflate(part) }
         | 
| 110 | 
            +
                  buf << inflater.finish
         | 
| 95 111 |  | 
| 96 | 
            -
             | 
| 97 | 
            -
                 | 
| 98 | 
            -
                io = StringIO.new(buf)
         | 
| 99 | 
            -
                gz = Zlib::GzipReader.new(io)
         | 
| 100 | 
            -
                gz.read.should.equal("foobar")
         | 
| 101 | 
            -
                gz.close
         | 
| 112 | 
            +
                  buf.delete_if { |part| part.empty? }.join.should.equal('foobar')
         | 
| 113 | 
            +
                end
         | 
| 102 114 | 
             
              end
         | 
| 103 115 |  | 
| 104 | 
            -
               | 
| 105 | 
            -
             | 
| 106 | 
            -
                 | 
| 116 | 
            +
              # TODO: This is really just a special case of the above...
         | 
| 117 | 
            +
              should 'be able to deflate String bodies' do
         | 
| 118 | 
            +
                verify(200, 'Hello world!', 'deflate') do |status, headers, body|
         | 
| 119 | 
            +
                  headers.should.equal({
         | 
| 120 | 
            +
                    'Content-Encoding' => 'deflate',
         | 
| 121 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 122 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 123 | 
            +
                  })
         | 
| 124 | 
            +
                end
         | 
| 125 | 
            +
              end
         | 
| 107 126 |  | 
| 108 | 
            -
             | 
| 127 | 
            +
              should 'be able to gzip bodies that respond to each' do
         | 
| 128 | 
            +
                app_body = Object.new
         | 
| 129 | 
            +
                class << app_body; def each; yield('foo'); yield('bar'); end; end
         | 
| 109 130 |  | 
| 110 | 
            -
                 | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
                 | 
| 117 | 
            -
                inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
         | 
| 118 | 
            -
                response[2].each { |part| buf << inflater.inflate(part) }
         | 
| 119 | 
            -
                buf << inflater.finish
         | 
| 120 | 
            -
                buf.delete_if { |part| part.empty? }
         | 
| 121 | 
            -
                buf.join.should.equal("foobar")
         | 
| 131 | 
            +
                verify(200, 'foobar', 'gzip', { 'app_body' => app_body }) do |status, headers, body|
         | 
| 132 | 
            +
                  headers.should.equal({
         | 
| 133 | 
            +
                    'Content-Encoding' => 'gzip',
         | 
| 134 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 135 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 136 | 
            +
                  })
         | 
| 137 | 
            +
                end
         | 
| 122 138 | 
             
              end
         | 
| 123 139 |  | 
| 124 | 
            -
              should  | 
| 125 | 
            -
                 | 
| 140 | 
            +
              should 'flush gzipped chunks to the client as they become ready' do
         | 
| 141 | 
            +
                app_body = Object.new
         | 
| 142 | 
            +
                class << app_body; def each; yield('foo'); yield('bar'); end; end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                verify(200, app_body, 'gzip', { 'skip_body_verify' => true }) do |status, headers, body|
         | 
| 145 | 
            +
                  headers.should.equal({
         | 
| 146 | 
            +
                    'Content-Encoding' => 'gzip',
         | 
| 147 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 148 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 149 | 
            +
                  })
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                  buf = []
         | 
| 152 | 
            +
                  inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
         | 
| 153 | 
            +
                  body.each { |part| buf << inflater.inflate(part) }
         | 
| 154 | 
            +
                  buf << inflater.finish
         | 
| 126 155 |  | 
| 127 | 
            -
             | 
| 128 | 
            -
                 | 
| 129 | 
            -
                response[2].to_enum.to_a.should.equal(["Hello world!"])
         | 
| 156 | 
            +
                  buf.delete_if { |part| part.empty? }.join.should.equal('foobar')
         | 
| 157 | 
            +
                end
         | 
| 130 158 | 
             
              end
         | 
| 131 159 |  | 
| 132 | 
            -
              should  | 
| 133 | 
            -
                 | 
| 160 | 
            +
              should 'be able to fallback to no deflation' do
         | 
| 161 | 
            +
                verify(200, 'Hello world!', 'superzip') do |status, headers, body|
         | 
| 162 | 
            +
                  headers.should.equal({
         | 
| 163 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 164 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 165 | 
            +
                  })
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
              end
         | 
| 134 168 |  | 
| 135 | 
            -
             | 
| 136 | 
            -
                 | 
| 137 | 
            -
             | 
| 169 | 
            +
              should 'be able to skip when there is no response entity body' do
         | 
| 170 | 
            +
                verify(304, '', { 'gzip' => nil }, { 'app_body' => [] }) do |status, headers, body|
         | 
| 171 | 
            +
                  headers.should.equal({})
         | 
| 172 | 
            +
                end
         | 
| 138 173 | 
             
              end
         | 
| 139 174 |  | 
| 140 | 
            -
              should  | 
| 141 | 
            -
                 | 
| 142 | 
            -
                 | 
| 143 | 
            -
                 | 
| 144 | 
            -
                 | 
| 175 | 
            +
              should 'handle the lack of an acceptable encoding' do
         | 
| 176 | 
            +
                app_body = 'Hello world!'
         | 
| 177 | 
            +
                not_found_body1 = 'An acceptable encoding for the requested resource / could not be found.'
         | 
| 178 | 
            +
                not_found_body2 = 'An acceptable encoding for the requested resource /foo/bar could not be found.'
         | 
| 179 | 
            +
                options1 = {
         | 
| 180 | 
            +
                  'app_status' => 200,
         | 
| 181 | 
            +
                  'app_body' => app_body,
         | 
| 182 | 
            +
                  'request_headers' => {
         | 
| 183 | 
            +
                    'PATH_INFO' => '/'
         | 
| 184 | 
            +
                  }
         | 
| 185 | 
            +
                }
         | 
| 186 | 
            +
                options2 = {
         | 
| 187 | 
            +
                  'app_status' => 200,
         | 
| 188 | 
            +
                  'app_body' => app_body,
         | 
| 189 | 
            +
                  'request_headers' => {
         | 
| 190 | 
            +
                    'PATH_INFO' => '/foo/bar'
         | 
| 191 | 
            +
                  }
         | 
| 192 | 
            +
                }
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                verify(406, not_found_body1, 'identity;q=0', options1) do |status, headers, body|
         | 
| 195 | 
            +
                  headers.should.equal({
         | 
| 196 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 197 | 
            +
                    'Content-Length' => not_found_body1.length.to_s
         | 
| 198 | 
            +
                  })
         | 
| 199 | 
            +
                end
         | 
| 145 200 |  | 
| 146 | 
            -
                 | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 201 | 
            +
                verify(406, not_found_body2, 'identity;q=0', options2) do |status, headers, body|
         | 
| 202 | 
            +
                  headers.should.equal({
         | 
| 203 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 204 | 
            +
                    'Content-Length' => not_found_body2.length.to_s
         | 
| 205 | 
            +
                  })
         | 
| 206 | 
            +
                end
         | 
| 150 207 | 
             
              end
         | 
| 151 208 |  | 
| 152 | 
            -
              should  | 
| 209 | 
            +
              should 'handle gzip response with Last-Modified header' do
         | 
| 153 210 | 
             
                last_modified = Time.now.httpdate
         | 
| 211 | 
            +
                options = {
         | 
| 212 | 
            +
                  'response_headers' => {
         | 
| 213 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 214 | 
            +
                    'Last-Modified' => last_modified
         | 
| 215 | 
            +
                  }
         | 
| 216 | 
            +
                }
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                verify(200, 'Hello World!', 'gzip', options) do |status, headers, body|
         | 
| 219 | 
            +
                  headers.should.equal({
         | 
| 220 | 
            +
                    'Content-Encoding' => 'gzip',
         | 
| 221 | 
            +
                    'Vary' => 'Accept-Encoding',
         | 
| 222 | 
            +
                    'Last-Modified' => last_modified,
         | 
| 223 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 224 | 
            +
                  })
         | 
| 225 | 
            +
                end
         | 
| 226 | 
            +
              end
         | 
| 154 227 |  | 
| 155 | 
            -
             | 
| 156 | 
            -
                 | 
| 157 | 
            -
             | 
| 228 | 
            +
              should 'do nothing when no-transform Cache-Control directive present' do
         | 
| 229 | 
            +
                options = {
         | 
| 230 | 
            +
                  'response_headers' => {
         | 
| 231 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 232 | 
            +
                    'Cache-Control' => 'no-transform'
         | 
| 233 | 
            +
                  }
         | 
| 234 | 
            +
                }
         | 
| 235 | 
            +
                verify(200, 'Hello World!', { 'gzip' => nil }, options) do |status, headers, body|
         | 
| 236 | 
            +
                  headers.should.not.include 'Content-Encoding'
         | 
| 237 | 
            +
                end
         | 
| 238 | 
            +
              end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
              should 'do nothing when Content-Encoding already present' do
         | 
| 241 | 
            +
                options = {
         | 
| 242 | 
            +
                  'response_headers' => {
         | 
| 243 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 244 | 
            +
                    'Content-Encoding' => 'gzip'
         | 
| 245 | 
            +
                  }
         | 
| 246 | 
            +
                }
         | 
| 247 | 
            +
                verify(200, 'Hello World!', { 'gzip' => nil }, options)
         | 
| 248 | 
            +
              end
         | 
| 158 249 |  | 
| 159 | 
            -
             | 
| 160 | 
            -
                 | 
| 161 | 
            -
                   | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
                   | 
| 165 | 
            -
                } | 
| 250 | 
            +
              should 'deflate when Content-Encoding is identity' do
         | 
| 251 | 
            +
                options = {
         | 
| 252 | 
            +
                  'response_headers' => {
         | 
| 253 | 
            +
                    'Content-Type' => 'text/plain',
         | 
| 254 | 
            +
                    'Content-Encoding' => 'identity'
         | 
| 255 | 
            +
                  }
         | 
| 256 | 
            +
                }
         | 
| 257 | 
            +
                verify(200, 'Hello World!', 'deflate', options)
         | 
| 258 | 
            +
              end
         | 
| 166 259 |  | 
| 167 | 
            -
             | 
| 168 | 
            -
                 | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 260 | 
            +
              should "deflate if content-type matches :include" do
         | 
| 261 | 
            +
                options = {
         | 
| 262 | 
            +
                  'response_headers' => {
         | 
| 263 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 264 | 
            +
                  },
         | 
| 265 | 
            +
                  'deflater_options' => {
         | 
| 266 | 
            +
                    :include => %w(text/plain)
         | 
| 267 | 
            +
                  }
         | 
| 268 | 
            +
                }
         | 
| 269 | 
            +
                verify(200, 'Hello World!', 'gzip', options)
         | 
| 173 270 | 
             
              end
         | 
| 174 271 |  | 
| 175 | 
            -
              should " | 
| 176 | 
            -
                 | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 272 | 
            +
              should "deflate if content-type is included it :include" do
         | 
| 273 | 
            +
                options = {
         | 
| 274 | 
            +
                  'response_headers' => {
         | 
| 275 | 
            +
                    'Content-Type' => 'text/plain; charset=us-ascii'
         | 
| 276 | 
            +
                  },
         | 
| 277 | 
            +
                  'deflater_options' => {
         | 
| 278 | 
            +
                    :include => %w(text/plain)
         | 
| 279 | 
            +
                  }
         | 
| 280 | 
            +
                }
         | 
| 281 | 
            +
                verify(200, 'Hello World!', 'gzip', options)
         | 
| 282 | 
            +
              end
         | 
| 179 283 |  | 
| 180 | 
            -
             | 
| 181 | 
            -
                 | 
| 182 | 
            -
             | 
| 284 | 
            +
              should "not deflate if content-type is not set but given in :include" do
         | 
| 285 | 
            +
                options = {
         | 
| 286 | 
            +
                  'deflater_options' => {
         | 
| 287 | 
            +
                    :include => %w(text/plain)
         | 
| 288 | 
            +
                  }
         | 
| 289 | 
            +
                }
         | 
| 290 | 
            +
                verify(304, 'Hello World!', { 'gzip' => nil }, options)
         | 
| 183 291 | 
             
              end
         | 
| 184 292 |  | 
| 185 | 
            -
              should " | 
| 186 | 
            -
                 | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 293 | 
            +
              should "not deflate if content-type do not match :include" do
         | 
| 294 | 
            +
                options = {
         | 
| 295 | 
            +
                  'response_headers' => {
         | 
| 296 | 
            +
                    'Content-Type' => 'text/plain'
         | 
| 297 | 
            +
                  },
         | 
| 298 | 
            +
                  'deflater_options' => {
         | 
| 299 | 
            +
                    :include => %w(text/json)
         | 
| 300 | 
            +
                  }
         | 
| 301 | 
            +
                }
         | 
| 302 | 
            +
                verify(200, 'Hello World!', { 'gzip' => nil }, options)
         | 
| 303 | 
            +
              end
         | 
| 189 304 |  | 
| 190 | 
            -
             | 
| 191 | 
            -
                 | 
| 305 | 
            +
              should "deflate response if :if lambda evaluates to true" do
         | 
| 306 | 
            +
                options = {
         | 
| 307 | 
            +
                  'deflater_options' => {
         | 
| 308 | 
            +
                    :if => lambda { |env, status, headers, body| true }
         | 
| 309 | 
            +
                  }
         | 
| 310 | 
            +
                }
         | 
| 311 | 
            +
                verify(200, 'Hello World!', 'deflate', options)
         | 
| 192 312 | 
             
              end
         | 
| 193 313 |  | 
| 194 | 
            -
              should "deflate  | 
| 195 | 
            -
                 | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 314 | 
            +
              should "not deflate if :if lambda evaluates to false" do
         | 
| 315 | 
            +
                options = {
         | 
| 316 | 
            +
                  'deflater_options' => {
         | 
| 317 | 
            +
                    :if => lambda { |env, status, headers, body| false }
         | 
| 318 | 
            +
                  }
         | 
| 319 | 
            +
                }
         | 
| 320 | 
            +
                verify(200, 'Hello World!', { 'gzip' => nil }, options)
         | 
| 321 | 
            +
              end
         | 
| 198 322 |  | 
| 199 | 
            -
             | 
| 200 | 
            -
                 | 
| 201 | 
            -
                 | 
| 202 | 
            -
                 | 
| 323 | 
            +
              should "check for Content-Length via :if" do
         | 
| 324 | 
            +
                body = 'Hello World!'
         | 
| 325 | 
            +
                body_len = body.length
         | 
| 326 | 
            +
                options = {
         | 
| 327 | 
            +
                  'response_headers' => {
         | 
| 328 | 
            +
                    'Content-Length' => body_len.to_s
         | 
| 329 | 
            +
                  },
         | 
| 330 | 
            +
                  'deflater_options' => {
         | 
| 331 | 
            +
                    :if => lambda { |env, status, headers, body|
         | 
| 332 | 
            +
                      headers['Content-Length'].to_i >= body_len
         | 
| 333 | 
            +
                    }
         | 
| 334 | 
            +
                  }
         | 
| 335 | 
            +
                }
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                verify(200, body, 'gzip', options)
         | 
| 203 338 | 
             
              end
         | 
| 204 339 | 
             
            end
         |