rack 2.2.22 → 3.2.6

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +588 -71
  3. data/CONTRIBUTING.md +63 -55
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +384 -0
  6. data/SPEC.rdoc +243 -277
  7. data/lib/rack/auth/abstract/handler.rb +3 -1
  8. data/lib/rack/auth/abstract/request.rb +5 -1
  9. data/lib/rack/auth/basic.rb +1 -3
  10. data/lib/rack/bad_request.rb +8 -0
  11. data/lib/rack/body_proxy.rb +21 -3
  12. data/lib/rack/builder.rb +108 -69
  13. data/lib/rack/cascade.rb +2 -3
  14. data/lib/rack/common_logger.rb +22 -17
  15. data/lib/rack/conditional_get.rb +20 -16
  16. data/lib/rack/constants.rb +68 -0
  17. data/lib/rack/content_length.rb +12 -16
  18. data/lib/rack/content_type.rb +8 -5
  19. data/lib/rack/deflater.rb +40 -26
  20. data/lib/rack/directory.rb +10 -4
  21. data/lib/rack/etag.rb +17 -23
  22. data/lib/rack/events.rb +25 -6
  23. data/lib/rack/files.rb +16 -18
  24. data/lib/rack/head.rb +8 -8
  25. data/lib/rack/headers.rb +238 -0
  26. data/lib/rack/lint.rb +817 -648
  27. data/lib/rack/lock.rb +2 -5
  28. data/lib/rack/media_type.rb +6 -7
  29. data/lib/rack/method_override.rb +5 -1
  30. data/lib/rack/mime.rb +14 -5
  31. data/lib/rack/mock.rb +1 -300
  32. data/lib/rack/mock_request.rb +161 -0
  33. data/lib/rack/mock_response.rb +156 -0
  34. data/lib/rack/multipart/generator.rb +7 -5
  35. data/lib/rack/multipart/parser.rb +282 -101
  36. data/lib/rack/multipart/uploaded_file.rb +45 -4
  37. data/lib/rack/multipart.rb +53 -40
  38. data/lib/rack/null_logger.rb +9 -0
  39. data/lib/rack/query_parser.rb +116 -121
  40. data/lib/rack/recursive.rb +2 -0
  41. data/lib/rack/reloader.rb +0 -2
  42. data/lib/rack/request.rb +272 -144
  43. data/lib/rack/response.rb +151 -66
  44. data/lib/rack/rewindable_input.rb +27 -5
  45. data/lib/rack/runtime.rb +7 -6
  46. data/lib/rack/sendfile.rb +37 -32
  47. data/lib/rack/show_exceptions.rb +25 -6
  48. data/lib/rack/show_status.rb +17 -9
  49. data/lib/rack/static.rb +15 -11
  50. data/lib/rack/tempfile_reaper.rb +15 -4
  51. data/lib/rack/urlmap.rb +3 -1
  52. data/lib/rack/utils.rb +326 -244
  53. data/lib/rack/version.rb +3 -15
  54. data/lib/rack.rb +13 -90
  55. metadata +15 -41
  56. data/README.rdoc +0 -355
  57. data/Rakefile +0 -130
  58. data/bin/rackup +0 -5
  59. data/contrib/rack.png +0 -0
  60. data/contrib/rack.svg +0 -150
  61. data/contrib/rack_logo.svg +0 -164
  62. data/contrib/rdoc.css +0 -412
  63. data/example/lobster.ru +0 -6
  64. data/example/protectedlobster.rb +0 -16
  65. data/example/protectedlobster.ru +0 -10
  66. data/lib/rack/auth/digest/md5.rb +0 -131
  67. data/lib/rack/auth/digest/nonce.rb +0 -53
  68. data/lib/rack/auth/digest/params.rb +0 -54
  69. data/lib/rack/auth/digest/request.rb +0 -43
  70. data/lib/rack/chunked.rb +0 -117
  71. data/lib/rack/core_ext/regexp.rb +0 -14
  72. data/lib/rack/file.rb +0 -7
  73. data/lib/rack/handler/cgi.rb +0 -59
  74. data/lib/rack/handler/fastcgi.rb +0 -100
  75. data/lib/rack/handler/lsws.rb +0 -61
  76. data/lib/rack/handler/scgi.rb +0 -71
  77. data/lib/rack/handler/thin.rb +0 -34
  78. data/lib/rack/handler/webrick.rb +0 -129
  79. data/lib/rack/handler.rb +0 -104
  80. data/lib/rack/lobster.rb +0 -70
  81. data/lib/rack/logger.rb +0 -20
  82. data/lib/rack/server.rb +0 -466
  83. data/lib/rack/session/abstract/id.rb +0 -523
  84. data/lib/rack/session/cookie.rb +0 -203
  85. data/lib/rack/session/memcache.rb +0 -10
  86. data/lib/rack/session/pool.rb +0 -90
  87. data/rack.gemspec +0 -46
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+ require 'time'
5
+
6
+ require_relative 'response'
7
+
8
+ module Rack
9
+ # Rack::MockResponse provides useful helpers for testing your apps.
10
+ # Usually, you don't create the MockResponse on your own, but use
11
+ # MockRequest.
12
+
13
+ class MockResponse < Rack::Response
14
+ class Cookie
15
+ attr_reader :name, :value, :path, :domain, :expires, :secure
16
+
17
+ def initialize(args)
18
+ @name = args["name"]
19
+ @value = args["value"]
20
+ @path = args["path"]
21
+ @domain = args["domain"]
22
+ @expires = args["expires"]
23
+ @secure = args["secure"]
24
+ end
25
+
26
+ def method_missing(method_name, *args, &block)
27
+ @value.send(method_name, *args, &block)
28
+ end
29
+ # :nocov:
30
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
31
+ # :nocov:
32
+
33
+ def respond_to_missing?(method_name, include_all = false)
34
+ @value.respond_to?(method_name, include_all) || super
35
+ end
36
+ end
37
+
38
+ class << self
39
+ alias [] new
40
+ end
41
+
42
+ # Headers
43
+ attr_reader :original_headers, :cookies
44
+
45
+ # Errors
46
+ attr_accessor :errors
47
+
48
+ def initialize(status, headers, body, errors = nil)
49
+ @original_headers = headers
50
+
51
+ if errors
52
+ @errors = errors.string if errors.respond_to?(:string)
53
+ else
54
+ @errors = ""
55
+ end
56
+
57
+ super(body, status, headers)
58
+
59
+ @cookies = parse_cookies_from_header
60
+ buffered_body!
61
+ end
62
+
63
+ def =~(other)
64
+ body =~ other
65
+ end
66
+
67
+ def match(other)
68
+ body.match other
69
+ end
70
+
71
+ def body
72
+ return @buffered_body if defined?(@buffered_body)
73
+
74
+ # FIXME: apparently users of MockResponse expect the return value of
75
+ # MockResponse#body to be a string. However, the real response object
76
+ # returns the body as a list.
77
+ #
78
+ # See spec_showstatus.rb:
79
+ #
80
+ # should "not replace existing messages" do
81
+ # ...
82
+ # res.body.should == "foo!"
83
+ # end
84
+ buffer = @buffered_body = String.new
85
+
86
+ begin
87
+ if @body.respond_to?(:each)
88
+ @body.each do |chunk|
89
+ buffer << chunk
90
+ end
91
+ else
92
+ @body.call(StringIO.new(buffer))
93
+ end
94
+ ensure
95
+ @body.close if @body.respond_to?(:close)
96
+ end
97
+
98
+ return buffer
99
+ end
100
+
101
+ def empty?
102
+ [201, 204, 304].include? status
103
+ end
104
+
105
+ def cookie(name)
106
+ cookies.fetch(name, nil)
107
+ end
108
+
109
+ private
110
+
111
+ def parse_cookies_from_header
112
+ cookies = Hash.new
113
+ set_cookie_header = headers['set-cookie']
114
+ if set_cookie_header && !set_cookie_header.empty?
115
+ Array(set_cookie_header).each do |cookie|
116
+ cookie_name, cookie_filling = cookie.split('=', 2)
117
+ cookie_attributes = identify_cookie_attributes cookie_filling
118
+ parsed_cookie = Cookie.new(
119
+ 'name' => cookie_name.strip,
120
+ 'value' => cookie_attributes.fetch('value'),
121
+ 'path' => cookie_attributes.fetch('path', nil),
122
+ 'domain' => cookie_attributes.fetch('domain', nil),
123
+ 'expires' => cookie_attributes.fetch('expires', nil),
124
+ 'secure' => cookie_attributes.fetch('secure', false)
125
+ )
126
+ cookies.store(cookie_name, parsed_cookie)
127
+ end
128
+ end
129
+ cookies
130
+ end
131
+
132
+ def identify_cookie_attributes(cookie_filling)
133
+ cookie_bits = cookie_filling.split(';')
134
+ cookie_attributes = Hash.new
135
+ cookie_attributes.store('value', Array(cookie_bits[0].strip))
136
+ cookie_bits.drop(1).each do |bit|
137
+ if bit.include? '='
138
+ cookie_attribute, attribute_value = bit.split('=', 2)
139
+ cookie_attributes.store(cookie_attribute.strip.downcase, attribute_value.strip)
140
+ end
141
+ if bit.include? 'secure'
142
+ cookie_attributes.store('secure', true)
143
+ end
144
+ end
145
+
146
+ if cookie_attributes.key? 'max-age'
147
+ cookie_attributes.store('expires', Time.now + cookie_attributes['max-age'].to_i)
148
+ elsif cookie_attributes.key? 'expires'
149
+ cookie_attributes.store('expires', Time.httpdate(cookie_attributes['expires']))
150
+ end
151
+
152
+ cookie_attributes
153
+ end
154
+
155
+ end
156
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'uploaded_file'
4
+
3
5
  module Rack
4
6
  module Multipart
5
7
  class Generator
@@ -74,12 +76,12 @@ module Rack
74
76
 
75
77
  def content_for_tempfile(io, file, name)
76
78
  length = ::File.stat(file.path).size if file.path
77
- filename = "; filename=\"#{Utils.escape(file.original_filename)}\"" if file.original_filename
79
+ filename = "; filename=\"#{Utils.escape_path(file.original_filename)}\""
78
80
  <<-EOF
79
81
  --#{MULTIPART_BOUNDARY}\r
80
- Content-Disposition: form-data; name="#{name}"#{filename}\r
81
- Content-Type: #{file.content_type}\r
82
- #{"Content-Length: #{length}\r\n" if length}\r
82
+ content-disposition: form-data; name="#{name}"#{filename}\r
83
+ content-type: #{file.content_type}\r
84
+ #{"content-length: #{length}\r\n" if length}\r
83
85
  #{io.read}\r
84
86
  EOF
85
87
  end
@@ -87,7 +89,7 @@ EOF
87
89
  def content_for_other(file, name)
88
90
  <<-EOF
89
91
  --#{MULTIPART_BOUNDARY}\r
90
- Content-Disposition: form-data; name="#{name}"\r
92
+ content-disposition: form-data; name="#{name}"\r
91
93
  \r
92
94
  #{file}\r
93
95
  EOF