rack-contrib 2.3.0 → 2.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-contrib might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf14e9cb70d9701bc1f3fe5ce036a0667f4ba6c9411e0e6ded73ef958228ec45
4
- data.tar.gz: d0c2abe31908dd0d49dec3635cca17c720c94d098a04e9485adf917c469e0ee5
3
+ metadata.gz: '0328244bd18e70963a841937904e3bf27eebfef5de80a4d3e1e09328e4c93ff8'
4
+ data.tar.gz: 2ab61dc5347ad251d9654e3b94f705358081b8dd932b62a07cc95f42d611c3b3
5
5
  SHA512:
6
- metadata.gz: f352f5eac5008e79d645460cd9b17dcc7231fe55edb63a0540c6c0991c06ba5f989cd70c23453e854a8189bcd02ad1be96366bb4d24efdaccefc5fe823a9eed5
7
- data.tar.gz: 379d6d0190a63d1df9c615e2fdd53bfebcac0cf506407e1e8a11c734ffc955f066a2aa56e79db21458b62efbb6603e1749f1bdddaed1c35fb84a69cd494dba8f
6
+ metadata.gz: 6a877560e6bfb9df7779a324fcbd803294fe9939563cd1360f27a93f377f567d35bb3ca28e9935e5f7d5babbb221082ba13abb4edf1819cc9e204f229840f41f
7
+ data.tar.gz: f657d4a1f6846c3e426dea6f5ef3dcb62369c23ae36f4eaa1abe689b6210327fa78aa102058399397f1e1731d60f2070915479578026fa78c8e98470f1b5f843
@@ -40,7 +40,7 @@ module Rack
40
40
  raise ArgumentError, "paths need to start with /"
41
41
  end
42
42
  location = location.chomp('/')
43
- match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
43
+ match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", Regexp::NOENCODING)
44
44
 
45
45
  ipmasks.collect! do |ipmask|
46
46
  ipmask.is_a?(IPAddr) ? ipmask : IPAddr.new(ipmask)
@@ -72,7 +72,7 @@ module Rack
72
72
  end
73
73
 
74
74
  def forbidden!
75
- [403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
75
+ [403, { 'content-type' => 'text/html', 'content-length' => '0' }, []]
76
76
  end
77
77
 
78
78
  def ip_authorized?(request, ipmasks)
@@ -10,10 +10,10 @@ module Rack
10
10
  end
11
11
 
12
12
  def call(env)
13
- if File.exists?(@file)
13
+ if File.exist?(@file)
14
14
  content = File.read(@file)
15
15
  length = content.bytesize.to_s
16
- [503, {'Content-Type' => 'text/html', 'Content-Length' => length}, [content]]
16
+ [503, {'content-type' => 'text/html', 'content-length' => length}, [content]]
17
17
  else
18
18
  @app.call(env)
19
19
  end
@@ -9,7 +9,7 @@ module Rack
9
9
 
10
10
  def call(env)
11
11
  if env["PATH_INFO"] == "/favicon.ico"
12
- [404, {"Content-Type" => "text/html", "Content-Length" => "0"}, []]
12
+ [404, {"content-type" => "text/html", "content-length" => "0"}, []]
13
13
  else
14
14
  @app.call(env)
15
15
  end
@@ -7,13 +7,16 @@ module Rack
7
7
  LOCALHOST_OR_IP_REGEXP = /^([\d.]+|localhost)$/
8
8
  PORT = /:\d+$/
9
9
 
10
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
11
+ private_constant :HEADERS_KLASS
12
+
10
13
  def initialize(app)
11
14
  @app = app
12
15
  end
13
16
 
14
17
  def call(env)
15
18
  status, headers, body = @app.call(env)
16
- headers = Utils::HeaderHash.new(headers)
19
+ headers = HEADERS_KLASS.new.merge(headers)
17
20
 
18
21
  host = env['HTTP_HOST'].sub PORT, ''
19
22
  share_cookie(headers, host)
@@ -6,6 +6,8 @@ module Rack
6
6
 
7
7
  # A Rack middleware for providing CSSHTTPRequest responses.
8
8
  class CSSHTTPRequest
9
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
10
+ private_constant :HEADERS_KLASS
9
11
 
10
12
  def initialize(app)
11
13
  @app = app
@@ -15,7 +17,7 @@ module Rack
15
17
  # the CSSHTTPRequest encoder
16
18
  def call(env)
17
19
  status, headers, response = @app.call(env)
18
- headers = Utils::HeaderHash.new(headers)
20
+ headers = HEADERS_KLASS.new.merge(headers)
19
21
 
20
22
  if chr_request?(env)
21
23
  encoded_response = encode(response)
@@ -65,7 +65,7 @@ module Rack
65
65
  end
66
66
 
67
67
  def deflect!
68
- [403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
68
+ [403, { 'content-type' => 'text/html', 'content-length' => '0' }, []]
69
69
  end
70
70
 
71
71
  def deflect? env
@@ -18,7 +18,7 @@ module Rack
18
18
  Rack::Utils.unescape(full_path).valid_encoding?
19
19
  @app.call env
20
20
  else
21
- [400, {'Content-Type'=>'text/plain'}, ['Bad Request']]
21
+ [400, {'content-type'=>'text/plain'}, ['Bad Request']]
22
22
  end
23
23
  end
24
24
  end
@@ -5,8 +5,8 @@ module Rack
5
5
  Expect = "HTTP_EXPECT".freeze
6
6
  ContinueExpectation = "100-continue".freeze
7
7
 
8
- ExpectationFailed = [417, {"Content-Type" => "text/html"}, []].freeze
9
- NotFound = [404, {"Content-Type" => "text/html"}, []].freeze
8
+ ExpectationFailed = [417, {"content-type" => "text/html"}, []]
9
+ NotFound = [404, {"content-type" => "text/html"}, []]
10
10
 
11
11
  attr_reader :apps
12
12
 
@@ -30,7 +30,7 @@ module Rack
30
30
 
31
31
  def call(env)
32
32
  if env['PATH_INFO'] == '/host-meta'
33
- [200, {'Content-Type' => 'application/host-meta'}, [@response]]
33
+ [200, {'content-type' => 'application/host-meta'}, [@response]]
34
34
  else
35
35
  @app.call(env)
36
36
  end
@@ -14,10 +14,10 @@ module Rack
14
14
  # === Parse POST and GET requests only
15
15
  # use Rack::JSONBodyParser, verbs: ['POST', 'GET']
16
16
  #
17
- # === Parse POST|PATCH|PUT requests whose Content-Type matches 'json'
17
+ # === Parse POST|PATCH|PUT requests whose content-type matches 'json'
18
18
  # use Rack::JSONBodyParser, media: /json/
19
19
  #
20
- # === Parse POST requests whose Content-Type is 'application/json' or 'application/vnd+json'
20
+ # === Parse POST requests whose content-type is 'application/json' or 'application/vnd+json'
21
21
  # use Rack::JSONBodyParser, verbs: ['POST'], media: ['application/json', 'application/vnd.api+json']
22
22
  #
23
23
  class JSONBodyParser
@@ -61,9 +61,9 @@ module Rack
61
61
 
62
62
  update_form_hash_with_json_body(env)
63
63
  end
64
- rescue JSON::ParserError
64
+ rescue ParserError
65
65
  body = { error: 'Failed to parse body as JSON' }.to_json
66
- header = { 'Content-Type' => 'application/json' }
66
+ header = { 'content-type' => 'application/json' }
67
67
  return Rack::Response.new(body, 400, header).finish
68
68
  end
69
69
  @app.call(env)
@@ -71,13 +71,22 @@ module Rack
71
71
 
72
72
  private
73
73
 
74
+ class ParserError < StandardError; end
75
+
74
76
  def update_form_hash_with_json_body(env)
75
77
  body = env[Rack::RACK_INPUT]
76
78
  return unless (body_content = body.read) && !body_content.empty?
77
79
 
78
- body.rewind # somebody might try to read this stream
80
+ body.rewind if body.respond_to?(:rewind) # somebody might try to read this stream
81
+
82
+ begin
83
+ parsed_body = @parser.call(body_content)
84
+ rescue StandardError
85
+ raise ParserError
86
+ end
87
+
79
88
  env.update(
80
- Rack::RACK_REQUEST_FORM_HASH => @parser.call(body_content),
89
+ Rack::RACK_REQUEST_FORM_HASH => parsed_body,
81
90
  Rack::RACK_REQUEST_FORM_INPUT => body
82
91
  )
83
92
  end
@@ -23,6 +23,9 @@ module Rack
23
23
  # "\342\200\251" # => "\u2029"
24
24
  U2028, U2029 = ("\u2028" == 'u2028') ? ["\342\200\250", "\342\200\251"] : ["\u2028", "\u2029"]
25
25
 
26
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
27
+ private_constant :HEADERS_KLASS
28
+
26
29
  def initialize(app)
27
30
  @app = app
28
31
  end
@@ -42,7 +45,7 @@ module Rack
42
45
  return status, headers, response
43
46
  end
44
47
 
45
- headers = HeaderHash.new(headers)
48
+ headers = HEADERS_KLASS.new.merge(headers)
46
49
 
47
50
  if is_json?(headers) && has_callback?(request)
48
51
  callback = request.params['callback']
@@ -108,7 +111,7 @@ module Rack
108
111
  end
109
112
 
110
113
  def bad_request(body = "Bad Request")
111
- [ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }, [body] ]
114
+ [ 400, { 'content-type' => 'text/plain', 'content-length' => body.bytesize.to_s }, [body] ]
112
115
  end
113
116
 
114
117
  end
@@ -74,14 +74,14 @@ module Rack
74
74
 
75
75
  def call env
76
76
  if reading? env and fresh? env
77
- return [304, {'Last-Modified' => env['HTTP_IF_MODIFIED_SINCE']}, []]
77
+ return [304, {'last-modified' => env['HTTP_IF_MODIFIED_SINCE']}, []]
78
78
  end
79
79
 
80
80
  status, headers, body = @app.call env
81
- headers = Utils::HeaderHash.new(headers)
81
+ headers = Rack.release < "3" ? Utils::HeaderHash.new(headers) : headers
82
82
 
83
83
  update_cache unless (reading?(env) or skipping?(headers))
84
- headers['Last-Modified'] = cached_value if stampable? headers
84
+ headers['last-modified'] = cached_value if stampable? headers
85
85
  [status, headers, body]
86
86
  end
87
87
 
@@ -96,11 +96,11 @@ module Rack
96
96
  end
97
97
 
98
98
  def skipping? headers
99
- headers['Rack-Lazy-Conditional-Get'] == 'skip'
99
+ headers['rack-lazy-conditional-get'] == 'skip'
100
100
  end
101
101
 
102
102
  def stampable? headers
103
- !headers.has_key?('Last-Modified') and headers['Rack-Lazy-Conditional-Get'] == 'yes'
103
+ !headers.has_key?('last-modified') and headers['rack-lazy-conditional-get'] == 'yes'
104
104
  end
105
105
 
106
106
  def update_cache
@@ -4,6 +4,9 @@ require 'i18n'
4
4
 
5
5
  module Rack
6
6
  class Locale
7
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
8
+ private_constant :HEADERS_KLASS
9
+
7
10
  def initialize(app)
8
11
  @app = app
9
12
  end
@@ -16,7 +19,7 @@ module Rack
16
19
 
17
20
  env['rack.locale'] = I18n.locale = locale.to_s
18
21
  status, headers, body = @app.call(env)
19
- headers = Utils::HeaderHash.new(headers)
22
+ headers = HEADERS_KLASS.new.merge(headers)
20
23
 
21
24
  unless headers['Content-Language']
22
25
  headers['Content-Language'] = locale.to_s
@@ -106,7 +106,7 @@ module Rack
106
106
 
107
107
  def extract_body(env)
108
108
  if io = env['rack.input']
109
- io.rewind
109
+ io.rewind if io.respond_to?(:rewind)
110
110
  io.read
111
111
  end
112
112
  end
@@ -27,7 +27,7 @@ module Rack
27
27
  end
28
28
 
29
29
  def call(env)
30
- [404, {'Content-Type' => @content_type, 'Content-Length' => @length}, [@content]]
30
+ [404, {'content-type' => @content_type, 'content-length' => @length}, [@content]]
31
31
  end
32
32
  end
33
33
  end
@@ -75,7 +75,7 @@ module Rack
75
75
 
76
76
  def call(env)
77
77
  if Rack::Request.new(env).media_type == APPLICATION_JSON && (body = env[POST_BODY].read).length != 0
78
- env[POST_BODY].rewind # somebody might try to read this stream
78
+ env[POST_BODY].rewind if env[POST_BODY].respond_to?(:rewind) # somebody might try to read this stream
79
79
  env.update(FORM_HASH => @block.call(body), FORM_INPUT => env[POST_BODY])
80
80
  end
81
81
  @app.call(env)
@@ -84,7 +84,7 @@ module Rack
84
84
  end
85
85
 
86
86
  def bad_request(body = 'Bad Request')
87
- [ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }, [body] ]
87
+ [ 400, { 'content-type' => 'text/plain', 'content-length' => body.bytesize.to_s }, [body] ]
88
88
  end
89
89
  end
90
90
  end
@@ -8,7 +8,7 @@ module Rack
8
8
  end
9
9
 
10
10
  def call(env)
11
- # See http://rack.rubyforge.org/doc/SPEC.html for details
11
+ # See https://github.com/rack/rack/blob/main/SPEC.rdoc for details
12
12
  puts "**********\n Environment\n **************"
13
13
  puts env.inspect
14
14
 
@@ -32,6 +32,7 @@ module Rack
32
32
  # option defaulting to :call_stack.
33
33
  def initialize(app, options = {})
34
34
  @app = app
35
+ @profile = nil
35
36
  @printer = parse_printer(options[:printer] || DEFAULT_PRINTER)
36
37
  @times = (options[:times] || 1).to_i
37
38
  end
@@ -46,27 +47,27 @@ module Rack
46
47
 
47
48
  private
48
49
  def profiling?(env)
49
- unless ::RubyProf.running?
50
- request = Rack::Request.new(env.clone)
51
- if mode = request.params.delete('profile')
52
- if ::RubyProf.const_defined?(mode.upcase)
53
- mode
54
- else
55
- env['rack.errors'].write "Invalid RubyProf measure_mode: " +
56
- "#{mode}. Use one of #{MODES.to_a.join(', ')}"
57
- false
58
- end
50
+ return if @profile && @profile.running?
51
+
52
+ request = Rack::Request.new(env.clone)
53
+ if mode = request.params.delete('profile')
54
+ if ::RubyProf.const_defined?(mode.upcase)
55
+ mode
56
+ else
57
+ env['rack.errors'].write "Invalid RubyProf measure_mode: " +
58
+ "#{mode}. Use one of #{MODES.to_a.join(', ')}"
59
+ false
59
60
  end
60
61
  end
61
62
  end
62
63
 
63
64
  def profile(env, mode)
64
- ::RubyProf.measure_mode = ::RubyProf.const_get(mode.upcase)
65
+ @profile = ::RubyProf::Profile.new(measure_mode: ::RubyProf.const_get(mode.upcase))
65
66
 
66
67
  GC.enable_stats if GC.respond_to?(:enable_stats)
67
68
  request = Rack::Request.new(env.clone)
68
69
  runs = (request.params['profiler_runs'] || @times).to_i
69
- result = ::RubyProf.profile do
70
+ result = @profile.profile do
70
71
  runs.times { @app.call(env) }
71
72
  end
72
73
  GC.disable_stats if GC.respond_to?(:disable_stats)
@@ -82,10 +83,10 @@ module Rack
82
83
  end
83
84
 
84
85
  def headers(printer, env, mode)
85
- headers = { 'Content-Type' => CONTENT_TYPES[printer.name] }
86
+ headers = { 'content-type' => CONTENT_TYPES[printer.name] }
86
87
  if printer == ::RubyProf::CallTreePrinter
87
88
  filename = ::File.basename(env['PATH_INFO'])
88
- headers['Content-Disposition'] =
89
+ headers['content-disposition'] =
89
90
  %(attachment; filename="#{filename}.#{mode}.tree")
90
91
  end
91
92
  headers
@@ -33,7 +33,8 @@ class Rack::RelativeRedirect
33
33
  # does not start with a slash, make location relative to the path requested.
34
34
  def call(env)
35
35
  status, headers, body = @app.call(env)
36
- headers = Rack::Utils::HeaderHash.new(headers)
36
+ headers_klass = Rack.release < "3" ? Rack::Utils::HeaderHash : Rack::Headers
37
+ headers = headers_klass.new.merge(headers)
37
38
 
38
39
  if [301,302,303, 307,308].include?(status) and loc = headers['Location'] and !%r{\Ahttps?://}o.match(loc)
39
40
  absolute = @absolute_proc.call(env, [status, headers, body])
@@ -53,7 +53,8 @@ class Rack::ResponseCache
53
53
  # subdirectory of cache. Otherwise, cache the body of the response as the value with the path as the key.
54
54
  def call(env)
55
55
  status, headers, body = @app.call(env)
56
- headers = Rack::Utils::HeaderHash.new(headers)
56
+ headers_klass = Rack.release < "3" ? Rack::Utils::HeaderHash : Rack::Headers
57
+ headers = headers_klass.new.merge(headers)
57
58
 
58
59
  if env['REQUEST_METHOD'] == 'GET' and env['QUERY_STRING'] == '' and status == 200 and path = @path_proc.call(env, [status, headers, body])
59
60
  if @cache.is_a?(String)
@@ -2,7 +2,8 @@
2
2
 
3
3
  module Rack
4
4
  # Allows you to tap into the response headers. Yields a Rack::Utils::HeaderHash
5
- # of current response headers to the block. Example:
5
+ # (Rack 2) or a Rack::Headers (Rack 3) of current response headers to the block.
6
+ # Example:
6
7
  #
7
8
  # use Rack::ResponseHeaders do |headers|
8
9
  # headers['X-Foo'] = 'bar'
@@ -10,6 +11,9 @@ module Rack
10
11
  # end
11
12
  #
12
13
  class ResponseHeaders
14
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
15
+ private_constant :HEADERS_KLASS
16
+
13
17
  def initialize(app, &block)
14
18
  @app = app
15
19
  @block = block
@@ -17,7 +21,7 @@ module Rack
17
21
 
18
22
  def call(env)
19
23
  response = @app.call(env)
20
- headers = Utils::HeaderHash.new(response[1])
24
+ headers = HEADERS_KLASS.new.merge(response[1])
21
25
  @block.call(headers)
22
26
  response[1] = headers
23
27
  response
@@ -52,6 +52,8 @@ module Rack
52
52
 
53
53
 
54
54
  class StaticCache
55
+ HEADERS_KLASS = Rack.release < "3" ? Utils::HeaderHash : Headers
56
+ private_constant :HEADERS_KLASS
55
57
 
56
58
  def initialize(app, options={})
57
59
  @app = app
@@ -67,7 +69,7 @@ module Rack
67
69
  end
68
70
  end
69
71
  root = options[:root] || Dir.pwd
70
- @file_server = Rack::File.new(root)
72
+ @file_server = Rack::Files.new(root)
71
73
  @cache_duration = options[:duration] || 1
72
74
  @versioning_enabled = options.fetch(:versioning, true)
73
75
  if @versioning_enabled
@@ -87,7 +89,7 @@ module Rack
87
89
  end
88
90
 
89
91
  status, headers, body = @file_server.call(env)
90
- headers = Utils::HeaderHash.new(headers)
92
+ headers = HEADERS_KLASS.new.merge(headers)
91
93
 
92
94
  if @no_cache[url].nil?
93
95
  headers['Cache-Control'] ="max-age=#{@duration_in_seconds}, public"
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ module Contrib
3
+ VERSION = '2.4.0'
4
+ end
5
+ end
metadata CHANGED
@@ -1,249 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-contrib
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rack-devel
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-24 00:00:00.000000000 Z
11
+ date: 2023-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '1.0'
34
17
  - - "<"
35
18
  - !ruby/object:Gem::Version
36
- version: '3'
37
- type: :development
19
+ version: '4'
20
+ type: :runtime
38
21
  prerelease: false
39
22
  version_requirements: !ruby/object:Gem::Requirement
40
23
  requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: '1.0'
44
24
  - - "<"
45
25
  - !ruby/object:Gem::Version
46
- version: '3'
47
- - !ruby/object:Gem::Dependency
48
- name: git-version-bump
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '0.15'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '0.15'
61
- - !ruby/object:Gem::Dependency
62
- name: github-release
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '0.1'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '0.1'
75
- - !ruby/object:Gem::Dependency
76
- name: i18n
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.6'
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: 0.6.8
85
- type: :development
86
- prerelease: false
87
- version_requirements: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - "~>"
90
- - !ruby/object:Gem::Version
91
- version: '0.6'
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: 0.6.8
95
- - !ruby/object:Gem::Dependency
96
- name: json
97
- requirement: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - "~>"
100
- - !ruby/object:Gem::Version
101
- version: '2.0'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - "~>"
107
- - !ruby/object:Gem::Version
108
- version: '2.0'
109
- - !ruby/object:Gem::Dependency
110
- name: mime-types
111
- requirement: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: '3.0'
116
- type: :development
117
- prerelease: false
118
- version_requirements: !ruby/object:Gem::Requirement
119
- requirements:
120
- - - "~>"
121
- - !ruby/object:Gem::Version
122
- version: '3.0'
123
- - !ruby/object:Gem::Dependency
124
- name: minitest
125
- requirement: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - "~>"
128
- - !ruby/object:Gem::Version
129
- version: '5.6'
130
- type: :development
131
- prerelease: false
132
- version_requirements: !ruby/object:Gem::Requirement
133
- requirements:
134
- - - "~>"
135
- - !ruby/object:Gem::Version
136
- version: '5.6'
137
- - !ruby/object:Gem::Dependency
138
- name: minitest-hooks
139
- requirement: !ruby/object:Gem::Requirement
140
- requirements:
141
- - - "~>"
142
- - !ruby/object:Gem::Version
143
- version: '1.0'
144
- type: :development
145
- prerelease: false
146
- version_requirements: !ruby/object:Gem::Requirement
147
- requirements:
148
- - - "~>"
149
- - !ruby/object:Gem::Version
150
- version: '1.0'
151
- - !ruby/object:Gem::Dependency
152
- name: mail
153
- requirement: !ruby/object:Gem::Requirement
154
- requirements:
155
- - - "~>"
156
- - !ruby/object:Gem::Version
157
- version: '2.3'
158
- - - ">="
159
- - !ruby/object:Gem::Version
160
- version: 2.6.4
161
- type: :development
162
- prerelease: false
163
- version_requirements: !ruby/object:Gem::Requirement
164
- requirements:
165
- - - "~>"
166
- - !ruby/object:Gem::Version
167
- version: '2.3'
168
- - - ">="
169
- - !ruby/object:Gem::Version
170
- version: 2.6.4
171
- - !ruby/object:Gem::Dependency
172
- name: nbio-csshttprequest
173
- requirement: !ruby/object:Gem::Requirement
174
- requirements:
175
- - - "~>"
176
- - !ruby/object:Gem::Version
177
- version: '1.0'
178
- type: :development
179
- prerelease: false
180
- version_requirements: !ruby/object:Gem::Requirement
181
- requirements:
182
- - - "~>"
183
- - !ruby/object:Gem::Version
184
- version: '1.0'
185
- - !ruby/object:Gem::Dependency
186
- name: rake
187
- requirement: !ruby/object:Gem::Requirement
188
- requirements:
189
- - - "~>"
190
- - !ruby/object:Gem::Version
191
- version: '10.4'
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: 10.4.2
195
- type: :development
196
- prerelease: false
197
- version_requirements: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '10.4'
202
- - - ">="
203
- - !ruby/object:Gem::Version
204
- version: 10.4.2
205
- - !ruby/object:Gem::Dependency
206
- name: rdoc
207
- requirement: !ruby/object:Gem::Requirement
208
- requirements:
209
- - - "~>"
210
- - !ruby/object:Gem::Version
211
- version: '5.0'
212
- type: :development
213
- prerelease: false
214
- version_requirements: !ruby/object:Gem::Requirement
215
- requirements:
216
- - - "~>"
217
- - !ruby/object:Gem::Version
218
- version: '5.0'
219
- - !ruby/object:Gem::Dependency
220
- name: ruby-prof
221
- requirement: !ruby/object:Gem::Requirement
222
- requirements:
223
- - - "~>"
224
- - !ruby/object:Gem::Version
225
- version: '0.17'
226
- type: :development
227
- prerelease: false
228
- version_requirements: !ruby/object:Gem::Requirement
229
- requirements:
230
- - - "~>"
231
- - !ruby/object:Gem::Version
232
- version: '0.17'
233
- - !ruby/object:Gem::Dependency
234
- name: timecop
235
- requirement: !ruby/object:Gem::Requirement
236
- requirements:
237
- - - "~>"
238
- - !ruby/object:Gem::Version
239
- version: '0.9'
240
- type: :development
241
- prerelease: false
242
- version_requirements: !ruby/object:Gem::Requirement
243
- requirements:
244
- - - "~>"
245
- - !ruby/object:Gem::Version
246
- version: '0.9'
26
+ version: '4'
247
27
  description: Contributed Rack Middleware and Utilities
248
28
  email: rack-devel@googlegroups.com
249
29
  executables: []
@@ -292,11 +72,12 @@ files:
292
72
  - lib/rack/contrib/static_cache.rb
293
73
  - lib/rack/contrib/time_zone.rb
294
74
  - lib/rack/contrib/try_static.rb
75
+ - lib/rack/contrib/version.rb
295
76
  homepage: https://github.com/rack/rack-contrib/
296
77
  licenses:
297
78
  - MIT
298
79
  metadata: {}
299
- post_install_message:
80
+ post_install_message:
300
81
  rdoc_options:
301
82
  - "--line-numbers"
302
83
  - "--inline-source"
@@ -317,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
317
98
  - !ruby/object:Gem::Version
318
99
  version: '0'
319
100
  requirements: []
320
- rubygems_version: 3.0.3
321
- signing_key:
101
+ rubygems_version: 3.4.10
102
+ signing_key:
322
103
  specification_version: 2
323
104
  summary: Contributed Rack Middleware and Utilities
324
105
  test_files: []