rack 2.0.9.3 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +681 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +152 -162
  6. data/Rakefile +37 -23
  7. data/{SPEC → SPEC.rdoc} +35 -10
  8. data/bin/rackup +1 -0
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +3 -1
  11. data/example/protectedlobster.ru +2 -0
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +1 -1
  14. data/lib/rack/auth/basic.rb +7 -4
  15. data/lib/rack/auth/digest/md5.rb +13 -11
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +4 -2
  18. data/lib/rack/auth/digest/request.rb +5 -3
  19. data/lib/rack/body_proxy.rb +15 -14
  20. data/lib/rack/builder.rb +116 -23
  21. data/lib/rack/cascade.rb +28 -12
  22. data/lib/rack/chunked.rb +68 -20
  23. data/lib/rack/common_logger.rb +33 -28
  24. data/lib/rack/conditional_get.rb +20 -16
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +8 -7
  27. data/lib/rack/content_type.rb +5 -4
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +59 -34
  30. data/lib/rack/directory.rb +84 -64
  31. data/lib/rack/etag.rb +5 -4
  32. data/lib/rack/events.rb +19 -20
  33. data/lib/rack/file.rb +4 -173
  34. data/lib/rack/files.rb +218 -0
  35. data/lib/rack/handler/cgi.rb +2 -3
  36. data/lib/rack/handler/fastcgi.rb +4 -4
  37. data/lib/rack/handler/lsws.rb +3 -3
  38. data/lib/rack/handler/scgi.rb +9 -8
  39. data/lib/rack/handler/thin.rb +17 -11
  40. data/lib/rack/handler/webrick.rb +15 -6
  41. data/lib/rack/handler.rb +7 -2
  42. data/lib/rack/head.rb +1 -1
  43. data/lib/rack/lint.rb +72 -26
  44. data/lib/rack/lobster.rb +10 -10
  45. data/lib/rack/lock.rb +2 -1
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +10 -5
  48. data/lib/rack/method_override.rb +4 -2
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +97 -20
  51. data/lib/rack/multipart/generator.rb +17 -13
  52. data/lib/rack/multipart/parser.rb +58 -73
  53. data/lib/rack/multipart/uploaded_file.rb +15 -7
  54. data/lib/rack/multipart.rb +7 -4
  55. data/lib/rack/null_logger.rb +2 -0
  56. data/lib/rack/query_parser.rb +53 -28
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +8 -4
  59. data/lib/rack/request.rb +220 -61
  60. data/lib/rack/response.rb +127 -44
  61. data/lib/rack/rewindable_input.rb +4 -3
  62. data/lib/rack/runtime.rb +6 -4
  63. data/lib/rack/sendfile.rb +13 -9
  64. data/lib/rack/server.rb +95 -24
  65. data/lib/rack/session/abstract/id.rb +33 -21
  66. data/lib/rack/session/cookie.rb +12 -12
  67. data/lib/rack/session/memcache.rb +4 -93
  68. data/lib/rack/session/pool.rb +5 -3
  69. data/lib/rack/show_exceptions.rb +17 -13
  70. data/lib/rack/show_status.rb +5 -5
  71. data/lib/rack/static.rb +23 -11
  72. data/lib/rack/tempfile_reaper.rb +1 -1
  73. data/lib/rack/urlmap.rb +12 -6
  74. data/lib/rack/utils.rb +105 -130
  75. data/lib/rack/version.rb +29 -0
  76. data/lib/rack.rb +67 -73
  77. data/rack.gemspec +40 -28
  78. metadata +39 -182
  79. data/HISTORY.md +0 -520
  80. data/test/builder/an_underscore_app.rb +0 -5
  81. data/test/builder/anything.rb +0 -5
  82. data/test/builder/comment.ru +0 -4
  83. data/test/builder/end.ru +0 -5
  84. data/test/builder/line.ru +0 -1
  85. data/test/builder/options.ru +0 -2
  86. data/test/cgi/assets/folder/test.js +0 -1
  87. data/test/cgi/assets/fonts/font.eot +0 -1
  88. data/test/cgi/assets/images/image.png +0 -1
  89. data/test/cgi/assets/index.html +0 -1
  90. data/test/cgi/assets/javascripts/app.js +0 -1
  91. data/test/cgi/assets/stylesheets/app.css +0 -1
  92. data/test/cgi/lighttpd.conf +0 -26
  93. data/test/cgi/rackup_stub.rb +0 -6
  94. data/test/cgi/sample_rackup.ru +0 -5
  95. data/test/cgi/test +0 -9
  96. data/test/cgi/test+directory/test+file +0 -1
  97. data/test/cgi/test.fcgi +0 -9
  98. data/test/cgi/test.gz +0 -0
  99. data/test/cgi/test.ru +0 -5
  100. data/test/gemloader.rb +0 -10
  101. data/test/helper.rb +0 -34
  102. data/test/multipart/bad_robots +0 -259
  103. data/test/multipart/binary +0 -0
  104. data/test/multipart/content_type_and_no_filename +0 -6
  105. data/test/multipart/empty +0 -10
  106. data/test/multipart/fail_16384_nofile +0 -814
  107. data/test/multipart/file1.txt +0 -1
  108. data/test/multipart/filename_and_modification_param +0 -7
  109. data/test/multipart/filename_and_no_name +0 -6
  110. data/test/multipart/filename_with_encoded_words +0 -7
  111. data/test/multipart/filename_with_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  113. data/test/multipart/filename_with_null_byte +0 -7
  114. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  115. data/test/multipart/filename_with_single_quote +0 -7
  116. data/test/multipart/filename_with_unescaped_percentages +0 -6
  117. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  119. data/test/multipart/filename_with_unescaped_quotes +0 -6
  120. data/test/multipart/ie +0 -6
  121. data/test/multipart/invalid_character +0 -6
  122. data/test/multipart/mixed_files +0 -21
  123. data/test/multipart/nested +0 -10
  124. data/test/multipart/none +0 -9
  125. data/test/multipart/quoted +0 -15
  126. data/test/multipart/rack-logo.png +0 -0
  127. data/test/multipart/semicolon +0 -6
  128. data/test/multipart/text +0 -15
  129. data/test/multipart/three_files_three_fields +0 -31
  130. data/test/multipart/unity3d_wwwform +0 -11
  131. data/test/multipart/webkit +0 -32
  132. data/test/rackup/config.ru +0 -31
  133. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  134. data/test/spec_auth_basic.rb +0 -89
  135. data/test/spec_auth_digest.rb +0 -260
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -233
  138. data/test/spec_cascade.rb +0 -63
  139. data/test/spec_cgi.rb +0 -84
  140. data/test/spec_chunked.rb +0 -103
  141. data/test/spec_common_logger.rb +0 -107
  142. data/test/spec_conditional_get.rb +0 -103
  143. data/test/spec_config.rb +0 -23
  144. data/test/spec_content_length.rb +0 -86
  145. data/test/spec_content_type.rb +0 -46
  146. data/test/spec_deflater.rb +0 -375
  147. data/test/spec_directory.rb +0 -148
  148. data/test/spec_etag.rb +0 -108
  149. data/test/spec_events.rb +0 -133
  150. data/test/spec_fastcgi.rb +0 -85
  151. data/test/spec_file.rb +0 -264
  152. data/test/spec_handler.rb +0 -57
  153. data/test/spec_head.rb +0 -46
  154. data/test/spec_lint.rb +0 -520
  155. data/test/spec_lobster.rb +0 -59
  156. data/test/spec_lock.rb +0 -204
  157. data/test/spec_logger.rb +0 -24
  158. data/test/spec_media_type.rb +0 -42
  159. data/test/spec_method_override.rb +0 -110
  160. data/test/spec_mime.rb +0 -51
  161. data/test/spec_mock.rb +0 -359
  162. data/test/spec_multipart.rb +0 -721
  163. data/test/spec_null_logger.rb +0 -21
  164. data/test/spec_recursive.rb +0 -75
  165. data/test/spec_request.rb +0 -1423
  166. data/test/spec_response.rb +0 -528
  167. data/test/spec_rewindable_input.rb +0 -128
  168. data/test/spec_runtime.rb +0 -50
  169. data/test/spec_sendfile.rb +0 -125
  170. data/test/spec_server.rb +0 -193
  171. data/test/spec_session_abstract_id.rb +0 -31
  172. data/test/spec_session_abstract_session_hash.rb +0 -45
  173. data/test/spec_session_cookie.rb +0 -442
  174. data/test/spec_session_memcache.rb +0 -357
  175. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  176. data/test/spec_session_pool.rb +0 -247
  177. data/test/spec_show_exceptions.rb +0 -93
  178. data/test/spec_show_status.rb +0 -104
  179. data/test/spec_static.rb +0 -184
  180. data/test/spec_tempfile_reaper.rb +0 -64
  181. data/test/spec_thin.rb +0 -96
  182. data/test/spec_urlmap.rb +0 -237
  183. data/test/spec_utils.rb +0 -742
  184. data/test/spec_version.rb +0 -11
  185. data/test/spec_webrick.rb +0 -206
  186. data/test/static/another/index.html +0 -1
  187. data/test/static/foo.html +0 -1
  188. data/test/static/index.html +0 -1
  189. data/test/testrequest.rb +0 -78
  190. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  191. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/file.rb CHANGED
@@ -1,176 +1,7 @@
1
- require 'time'
2
- require 'rack/utils'
3
- require 'rack/mime'
4
- require 'rack/request'
5
- require 'rack/head'
1
+ # frozen_string_literal: true
6
2
 
7
- module Rack
8
- # Rack::File serves files below the +root+ directory given, according to the
9
- # path info of the Rack request.
10
- # e.g. when Rack::File.new("/etc") is used, you can access 'passwd' file
11
- # as http://localhost:9292/passwd
12
- #
13
- # Handlers can detect if bodies are a Rack::File, and use mechanisms
14
- # like sendfile on the +path+.
15
-
16
- class File
17
- ALLOWED_VERBS = %w[GET HEAD OPTIONS]
18
- ALLOW_HEADER = ALLOWED_VERBS.join(', ')
19
-
20
- attr_reader :root
21
-
22
- def initialize(root, headers={}, default_mime = 'text/plain')
23
- @root = root
24
- @headers = headers
25
- @default_mime = default_mime
26
- @head = Rack::Head.new(lambda { |env| get env })
27
- end
28
-
29
- def call(env)
30
- # HEAD requests drop the response body, including 4xx error messages.
31
- @head.call env
32
- end
33
-
34
- def get(env)
35
- request = Rack::Request.new env
36
- unless ALLOWED_VERBS.include? request.request_method
37
- return fail(405, "Method Not Allowed", {'Allow' => ALLOW_HEADER})
38
- end
39
-
40
- path_info = Utils.unescape_path request.path_info
41
- return fail(400, "Bad Request") unless Utils.valid_path?(path_info)
42
-
43
- clean_path_info = Utils.clean_path_info(path_info)
44
- path = ::File.join(@root, clean_path_info)
45
-
46
- available = begin
47
- ::File.file?(path) && ::File.readable?(path)
48
- rescue SystemCallError
49
- false
50
- end
51
-
52
- if available
53
- serving(request, path)
54
- else
55
- fail(404, "File not found: #{path_info}")
56
- end
57
- end
58
-
59
- def serving(request, path)
60
- if request.options?
61
- return [200, {'Allow' => ALLOW_HEADER, CONTENT_LENGTH => '0'}, []]
62
- end
63
- last_modified = ::File.mtime(path).httpdate
64
- return [304, {}, []] if request.get_header('HTTP_IF_MODIFIED_SINCE') == last_modified
65
-
66
- headers = { "Last-Modified" => last_modified }
67
- mime_type = mime_type path, @default_mime
68
- headers[CONTENT_TYPE] = mime_type if mime_type
69
-
70
- # Set custom headers
71
- @headers.each { |field, content| headers[field] = content } if @headers
72
-
73
- response = [ 200, headers ]
74
-
75
- size = filesize path
76
-
77
- range = nil
78
- ranges = Rack::Utils.get_byte_ranges(request.get_header('HTTP_RANGE'), size)
79
- if ranges.nil? || ranges.length > 1
80
- # No ranges, or multiple ranges (which we don't support):
81
- # TODO: Support multiple byte-ranges
82
- response[0] = 200
83
- range = 0..size-1
84
- elsif ranges.empty?
85
- # Unsatisfiable. Return error, and file size:
86
- response = fail(416, "Byte range unsatisfiable")
87
- response[1]["Content-Range"] = "bytes */#{size}"
88
- return response
89
- else
90
- # Partial content:
91
- range = ranges[0]
92
- response[0] = 206
93
- response[1]["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{size}"
94
- size = range.end - range.begin + 1
95
- end
3
+ require_relative 'files'
96
4
 
97
- response[2] = [response_body] unless response_body.nil?
98
-
99
- response[1][CONTENT_LENGTH] = size.to_s
100
- response[2] = make_body request, path, range
101
- response
102
- end
103
-
104
- class Iterator
105
- attr_reader :path, :range
106
- alias :to_path :path
107
-
108
- def initialize path, range
109
- @path = path
110
- @range = range
111
- end
112
-
113
- def each
114
- ::File.open(path, "rb") do |file|
115
- file.seek(range.begin)
116
- remaining_len = range.end-range.begin+1
117
- while remaining_len > 0
118
- part = file.read([8192, remaining_len].min)
119
- break unless part
120
- remaining_len -= part.length
121
-
122
- yield part
123
- end
124
- end
125
- end
126
-
127
- def close; end
128
- end
129
-
130
- private
131
-
132
- def make_body request, path, range
133
- if request.head?
134
- []
135
- else
136
- Iterator.new path, range
137
- end
138
- end
139
-
140
- def fail(status, body, headers = {})
141
- body += "\n"
142
-
143
- [
144
- status,
145
- {
146
- CONTENT_TYPE => "text/plain",
147
- CONTENT_LENGTH => body.size.to_s,
148
- "X-Cascade" => "pass"
149
- }.merge!(headers),
150
- [body]
151
- ]
152
- end
153
-
154
- # The MIME type for the contents of the file located at @path
155
- def mime_type path, default_mime
156
- Mime.mime_type(::File.extname(path), default_mime)
157
- end
158
-
159
- def filesize path
160
- # If response_body is present, use its size.
161
- return response_body.bytesize if response_body
162
-
163
- # We check via File::size? whether this file provides size info
164
- # via stat (e.g. /proc files often don't), otherwise we have to
165
- # figure it out by reading the whole file into memory.
166
- ::File.size?(path) || ::File.read(path).bytesize
167
- end
168
-
169
- # By default, the response body for file requests is nil.
170
- # In this case, the response body will be generated later
171
- # from the file at @path
172
- def response_body
173
- nil
174
- end
175
- end
5
+ module Rack
6
+ File = Files
176
7
  end
data/lib/rack/files.rb ADDED
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
5
+ module Rack
6
+ # Rack::Files serves files below the +root+ directory given, according to the
7
+ # path info of the Rack request.
8
+ # e.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file
9
+ # as http://localhost:9292/passwd
10
+ #
11
+ # Handlers can detect if bodies are a Rack::Files, and use mechanisms
12
+ # like sendfile on the +path+.
13
+
14
+ class Files
15
+ ALLOWED_VERBS = %w[GET HEAD OPTIONS]
16
+ ALLOW_HEADER = ALLOWED_VERBS.join(', ')
17
+ MULTIPART_BOUNDARY = 'AaB03x'
18
+
19
+ # @todo remove in 3.0
20
+ def self.method_added(name)
21
+ if name == :response_body
22
+ raise "#{self.class}\#response_body is no longer supported."
23
+ end
24
+ super
25
+ end
26
+
27
+ attr_reader :root
28
+
29
+ def initialize(root, headers = {}, default_mime = 'text/plain')
30
+ @root = (::File.expand_path(root) if root)
31
+ @headers = headers
32
+ @default_mime = default_mime
33
+ @head = Rack::Head.new(lambda { |env| get env })
34
+ end
35
+
36
+ def call(env)
37
+ # HEAD requests drop the response body, including 4xx error messages.
38
+ @head.call env
39
+ end
40
+
41
+ def get(env)
42
+ request = Rack::Request.new env
43
+ unless ALLOWED_VERBS.include? request.request_method
44
+ return fail(405, "Method Not Allowed", { 'Allow' => ALLOW_HEADER })
45
+ end
46
+
47
+ path_info = Utils.unescape_path request.path_info
48
+ return fail(400, "Bad Request") unless Utils.valid_path?(path_info)
49
+
50
+ clean_path_info = Utils.clean_path_info(path_info)
51
+ path = ::File.join(@root, clean_path_info)
52
+
53
+ available = begin
54
+ ::File.file?(path) && ::File.readable?(path)
55
+ rescue SystemCallError
56
+ # Not sure in what conditions this exception can occur, but this
57
+ # is a safe way to handle such an error.
58
+ # :nocov:
59
+ false
60
+ # :nocov:
61
+ end
62
+
63
+ if available
64
+ serving(request, path)
65
+ else
66
+ fail(404, "File not found: #{path_info}")
67
+ end
68
+ end
69
+
70
+ def serving(request, path)
71
+ if request.options?
72
+ return [200, { 'Allow' => ALLOW_HEADER, CONTENT_LENGTH => '0' }, []]
73
+ end
74
+ last_modified = ::File.mtime(path).httpdate
75
+ return [304, {}, []] if request.get_header('HTTP_IF_MODIFIED_SINCE') == last_modified
76
+
77
+ headers = { "Last-Modified" => last_modified }
78
+ mime_type = mime_type path, @default_mime
79
+ headers[CONTENT_TYPE] = mime_type if mime_type
80
+
81
+ # Set custom headers
82
+ headers.merge!(@headers) if @headers
83
+
84
+ status = 200
85
+ size = filesize path
86
+
87
+ ranges = Rack::Utils.get_byte_ranges(request.get_header('HTTP_RANGE'), size)
88
+ if ranges.nil?
89
+ # No ranges:
90
+ ranges = [0..size - 1]
91
+ elsif ranges.empty?
92
+ # Unsatisfiable. Return error, and file size:
93
+ response = fail(416, "Byte range unsatisfiable")
94
+ response[1]["Content-Range"] = "bytes */#{size}"
95
+ return response
96
+ elsif ranges.size >= 1
97
+ # Partial content
98
+ partial_content = true
99
+
100
+ if ranges.size == 1
101
+ range = ranges[0]
102
+ headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{size}"
103
+ else
104
+ headers[CONTENT_TYPE] = "multipart/byteranges; boundary=#{MULTIPART_BOUNDARY}"
105
+ end
106
+
107
+ status = 206
108
+ body = BaseIterator.new(path, ranges, mime_type: mime_type, size: size)
109
+ size = body.bytesize
110
+ end
111
+
112
+ headers[CONTENT_LENGTH] = size.to_s
113
+
114
+ if request.head?
115
+ body = []
116
+ elsif !partial_content
117
+ body = Iterator.new(path, ranges, mime_type: mime_type, size: size)
118
+ end
119
+
120
+ [status, headers, body]
121
+ end
122
+
123
+ class BaseIterator
124
+ attr_reader :path, :ranges, :options
125
+
126
+ def initialize(path, ranges, options)
127
+ @path = path
128
+ @ranges = ranges
129
+ @options = options
130
+ end
131
+
132
+ def each
133
+ ::File.open(path, "rb") do |file|
134
+ ranges.each do |range|
135
+ yield multipart_heading(range) if multipart?
136
+
137
+ each_range_part(file, range) do |part|
138
+ yield part
139
+ end
140
+ end
141
+
142
+ yield "\r\n--#{MULTIPART_BOUNDARY}--\r\n" if multipart?
143
+ end
144
+ end
145
+
146
+ def bytesize
147
+ size = ranges.inject(0) do |sum, range|
148
+ sum += multipart_heading(range).bytesize if multipart?
149
+ sum += range.size
150
+ end
151
+ size += "\r\n--#{MULTIPART_BOUNDARY}--\r\n".bytesize if multipart?
152
+ size
153
+ end
154
+
155
+ def close; end
156
+
157
+ private
158
+
159
+ def multipart?
160
+ ranges.size > 1
161
+ end
162
+
163
+ def multipart_heading(range)
164
+ <<-EOF
165
+ \r
166
+ --#{MULTIPART_BOUNDARY}\r
167
+ Content-Type: #{options[:mime_type]}\r
168
+ Content-Range: bytes #{range.begin}-#{range.end}/#{options[:size]}\r
169
+ \r
170
+ EOF
171
+ end
172
+
173
+ def each_range_part(file, range)
174
+ file.seek(range.begin)
175
+ remaining_len = range.end - range.begin + 1
176
+ while remaining_len > 0
177
+ part = file.read([8192, remaining_len].min)
178
+ break unless part
179
+ remaining_len -= part.length
180
+
181
+ yield part
182
+ end
183
+ end
184
+ end
185
+
186
+ class Iterator < BaseIterator
187
+ alias :to_path :path
188
+ end
189
+
190
+ private
191
+
192
+ def fail(status, body, headers = {})
193
+ body += "\n"
194
+
195
+ [
196
+ status,
197
+ {
198
+ CONTENT_TYPE => "text/plain",
199
+ CONTENT_LENGTH => body.size.to_s,
200
+ "X-Cascade" => "pass"
201
+ }.merge!(headers),
202
+ [body]
203
+ ]
204
+ end
205
+
206
+ # The MIME type for the contents of the file located at @path
207
+ def mime_type(path, default_mime)
208
+ Mime.mime_type(::File.extname(path), default_mime)
209
+ end
210
+
211
+ def filesize(path)
212
+ # We check via File::size? whether this file provides size info
213
+ # via stat (e.g. /proc files often don't), otherwise we have to
214
+ # figure it out by reading the whole file into memory.
215
+ ::File.size?(path) || ::File.read(path).bytesize
216
+ end
217
+ end
218
+ end
@@ -1,10 +1,9 @@
1
- require 'rack/content_length'
2
- require 'rack/rewindable_input'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Rack
5
4
  module Handler
6
5
  class CGI
7
- def self.run(app, options=nil)
6
+ def self.run(app, **options)
8
7
  $stdin.binmode
9
8
  serve app
10
9
  end
@@ -1,13 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fcgi'
2
4
  require 'socket'
3
- require 'rack/content_length'
4
- require 'rack/rewindable_input'
5
5
 
6
6
  if defined? FCGI::Stream
7
7
  class FCGI::Stream
8
8
  alias _rack_read_without_buffer read
9
9
 
10
- def read(n, buffer=nil)
10
+ def read(n, buffer = nil)
11
11
  buf = _rack_read_without_buffer n
12
12
  buffer.replace(buf.to_s) if buffer
13
13
  buf
@@ -18,7 +18,7 @@ end
18
18
  module Rack
19
19
  module Handler
20
20
  class FastCGI
21
- def self.run(app, options={})
21
+ def self.run(app, **options)
22
22
  if options[:File]
23
23
  STDIN.reopen(UNIXServer.new(options[:File]))
24
24
  elsif options[:Port]
@@ -1,11 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'lsapi'
2
- require 'rack/content_length'
3
- require 'rack/rewindable_input'
4
4
 
5
5
  module Rack
6
6
  module Handler
7
7
  class LSWS
8
- def self.run(app, options=nil)
8
+ def self.run(app, **options)
9
9
  while LSAPI.accept != nil
10
10
  serve app
11
11
  end
@@ -1,19 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'scgi'
2
4
  require 'stringio'
3
- require 'rack/content_length'
4
- require 'rack/chunked'
5
5
 
6
6
  module Rack
7
7
  module Handler
8
8
  class SCGI < ::SCGI::Processor
9
9
  attr_accessor :app
10
10
 
11
- def self.run(app, options=nil)
11
+ def self.run(app, **options)
12
12
  options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
13
- new(options.merge(:app=>app,
14
- :host=>options[:Host],
15
- :port=>options[:Port],
16
- :socket=>options[:Socket])).listen
13
+ new(options.merge(app: app,
14
+ host: options[:Host],
15
+ port: options[:Port],
16
+ socket: options[:Socket])).listen
17
17
  end
18
18
 
19
19
  def self.valid_options
@@ -41,7 +41,8 @@ module Rack
41
41
  env[QUERY_STRING] ||= ""
42
42
  env[SCRIPT_NAME] = ""
43
43
 
44
- rack_input = StringIO.new(input_body, encoding: Encoding::BINARY)
44
+ rack_input = StringIO.new(input_body)
45
+ rack_input.set_encoding(Encoding::BINARY)
45
46
 
46
47
  env.update(
47
48
  RACK_VERSION => Rack::VERSION,
@@ -1,25 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thin"
2
4
  require "thin/server"
3
5
  require "thin/logging"
4
6
  require "thin/backends/tcp_server"
5
- require "rack/content_length"
6
- require "rack/chunked"
7
7
 
8
8
  module Rack
9
9
  module Handler
10
10
  class Thin
11
- def self.run(app, options={})
11
+ def self.run(app, **options)
12
12
  environment = ENV['RACK_ENV'] || 'development'
13
13
  default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
14
14
 
15
- host = options.delete(:Host) || default_host
16
- port = options.delete(:Port) || 8080
17
- args = [host, port, app, options]
18
- # Thin versions below 0.8.0 do not support additional options
19
- args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
20
- server = ::Thin::Server.new(*args)
21
- yield server if block_given?
22
- server.start
15
+ if block_given?
16
+ host = options.delete(:Host) || default_host
17
+ port = options.delete(:Port) || 8080
18
+ args = [host, port, app, options]
19
+ # Thin versions below 0.8.0 do not support additional options
20
+ args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
21
+ server = ::Thin::Server.new(*args)
22
+ yield server
23
+ server.start
24
+ else
25
+ options[:address] = options[:Host] || default_host
26
+ options[:port] = options[:Port] || 8080
27
+ ::Thin::Controllers::Controller.new(options).start
28
+ end
23
29
  end
24
30
 
25
31
  def self.valid_options
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webrick'
2
4
  require 'stringio'
3
- require 'rack/content_length'
4
5
 
5
6
  # This monkey patch allows for applications to perform their own chunking
6
7
  # through WEBrick::HTTPResponse if rack is set to true.
@@ -22,12 +23,18 @@ end
22
23
  module Rack
23
24
  module Handler
24
25
  class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
25
- def self.run(app, options={})
26
+ def self.run(app, **options)
26
27
  environment = ENV['RACK_ENV'] || 'development'
27
28
  default_host = environment == 'development' ? 'localhost' : nil
28
29
 
29
- options[:BindAddress] = options.delete(:Host) || default_host
30
+ if !options[:BindAddress] || options[:Host]
31
+ options[:BindAddress] = options.delete(:Host) || default_host
32
+ end
30
33
  options[:Port] ||= 8080
34
+ if options[:SSLEnable]
35
+ require 'webrick/https'
36
+ end
37
+
31
38
  @server = ::WEBrick::HTTPServer.new(options)
32
39
  @server.mount "/", Rack::Handler::WEBrick, app
33
40
  yield @server if block_given?
@@ -45,8 +52,10 @@ module Rack
45
52
  end
46
53
 
47
54
  def self.shutdown
48
- @server.shutdown
49
- @server = nil
55
+ if @server
56
+ @server.shutdown
57
+ @server = nil
58
+ end
50
59
  end
51
60
 
52
61
  def initialize(server, app)
@@ -79,7 +88,7 @@ module Rack
79
88
  env[QUERY_STRING] ||= ""
80
89
  unless env[PATH_INFO] == ""
81
90
  path, n = req.request_uri.path, env[SCRIPT_NAME].length
82
- env[PATH_INFO] = path[n, path.length-n]
91
+ env[PATH_INFO] = path[n, path.length - n]
83
92
  end
84
93
  env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
85
94
 
data/lib/rack/handler.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  # *Handlers* connect web servers with Rack.
3
5
  #
@@ -17,7 +19,7 @@ module Rack
17
19
  end
18
20
 
19
21
  if klass = @handlers[server]
20
- klass.split("::").inject(Object) { |o, x| o.const_get(x) }
22
+ const_get(klass)
21
23
  else
22
24
  const_get(server, false)
23
25
  end
@@ -43,6 +45,9 @@ module Rack
43
45
  raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
44
46
  end
45
47
 
48
+ SERVER_NAMES = %w(puma thin falcon webrick).freeze
49
+ private_constant :SERVER_NAMES
50
+
46
51
  def self.default
47
52
  # Guess.
48
53
  if ENV.include?("PHP_FCGI_CHILDREN")
@@ -52,7 +57,7 @@ module Rack
52
57
  elsif ENV.include?("RACK_HANDLER")
53
58
  self.get(ENV["RACK_HANDLER"])
54
59
  else
55
- pick ['puma', 'thin', 'webrick']
60
+ pick SERVER_NAMES
56
61
  end
57
62
  end
58
63
 
data/lib/rack/head.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'rack/body_proxy'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Rack
4
4
  # Rack::Head returns an empty body for all HEAD requests. It leaves