rack 2.0.6 → 2.1.0

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY.md → CHANGELOG.md} +220 -155
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +77 -117
  5. data/Rakefile +25 -18
  6. data/SPEC +3 -4
  7. data/bin/rackup +1 -0
  8. data/example/lobster.ru +2 -0
  9. data/example/protectedlobster.rb +3 -1
  10. data/example/protectedlobster.ru +2 -0
  11. data/lib/rack/auth/abstract/handler.rb +3 -1
  12. data/lib/rack/auth/abstract/request.rb +2 -0
  13. data/lib/rack/auth/basic.rb +4 -1
  14. data/lib/rack/auth/digest/md5.rb +9 -7
  15. data/lib/rack/auth/digest/nonce.rb +6 -3
  16. data/lib/rack/auth/digest/params.rb +4 -2
  17. data/lib/rack/auth/digest/request.rb +2 -0
  18. data/lib/rack/body_proxy.rb +3 -6
  19. data/lib/rack/builder.rb +38 -15
  20. data/lib/rack/cascade.rb +6 -5
  21. data/lib/rack/chunked.rb +29 -6
  22. data/lib/rack/common_logger.rb +9 -8
  23. data/lib/rack/conditional_get.rb +3 -1
  24. data/lib/rack/config.rb +2 -0
  25. data/lib/rack/content_length.rb +3 -1
  26. data/lib/rack/content_type.rb +3 -1
  27. data/lib/rack/core_ext/regexp.rb +14 -0
  28. data/lib/rack/deflater.rb +28 -17
  29. data/lib/rack/directory.rb +17 -14
  30. data/lib/rack/etag.rb +3 -1
  31. data/lib/rack/events.rb +5 -3
  32. data/lib/rack/file.rb +5 -173
  33. data/lib/rack/files.rb +178 -0
  34. data/lib/rack/handler/cgi.rb +3 -1
  35. data/lib/rack/handler/fastcgi.rb +4 -2
  36. data/lib/rack/handler/lsws.rb +3 -1
  37. data/lib/rack/handler/scgi.rb +9 -6
  38. data/lib/rack/handler/thin.rb +3 -1
  39. data/lib/rack/handler/webrick.rb +4 -2
  40. data/lib/rack/handler.rb +7 -2
  41. data/lib/rack/head.rb +2 -0
  42. data/lib/rack/lint.rb +14 -11
  43. data/lib/rack/lobster.rb +7 -5
  44. data/lib/rack/lock.rb +2 -0
  45. data/lib/rack/logger.rb +2 -0
  46. data/lib/rack/media_type.rb +10 -5
  47. data/lib/rack/method_override.rb +4 -2
  48. data/lib/rack/mime.rb +9 -1
  49. data/lib/rack/mock.rb +74 -15
  50. data/lib/rack/multipart/generator.rb +6 -7
  51. data/lib/rack/multipart/parser.rb +55 -52
  52. data/lib/rack/multipart/uploaded_file.rb +2 -0
  53. data/lib/rack/multipart.rb +5 -3
  54. data/lib/rack/null_logger.rb +2 -0
  55. data/lib/rack/query_parser.rb +51 -25
  56. data/lib/rack/recursive.rb +7 -5
  57. data/lib/rack/reloader.rb +10 -4
  58. data/lib/rack/request.rb +80 -27
  59. data/lib/rack/response.rb +71 -31
  60. data/lib/rack/rewindable_input.rb +4 -2
  61. data/lib/rack/runtime.rb +4 -2
  62. data/lib/rack/sendfile.rb +15 -8
  63. data/lib/rack/server.rb +88 -16
  64. data/lib/rack/session/abstract/id.rb +104 -21
  65. data/lib/rack/session/cookie.rb +21 -11
  66. data/lib/rack/session/memcache.rb +4 -87
  67. data/lib/rack/session/pool.rb +17 -8
  68. data/lib/rack/show_exceptions.rb +15 -9
  69. data/lib/rack/show_status.rb +4 -2
  70. data/lib/rack/static.rb +15 -10
  71. data/lib/rack/tempfile_reaper.rb +2 -0
  72. data/lib/rack/urlmap.rb +11 -2
  73. data/lib/rack/utils.rb +55 -70
  74. data/lib/rack.rb +63 -60
  75. data/rack.gemspec +17 -7
  76. metadata +30 -171
  77. data/test/builder/an_underscore_app.rb +0 -5
  78. data/test/builder/anything.rb +0 -5
  79. data/test/builder/comment.ru +0 -4
  80. data/test/builder/end.ru +0 -5
  81. data/test/builder/line.ru +0 -1
  82. data/test/builder/options.ru +0 -2
  83. data/test/cgi/assets/folder/test.js +0 -1
  84. data/test/cgi/assets/fonts/font.eot +0 -1
  85. data/test/cgi/assets/images/image.png +0 -1
  86. data/test/cgi/assets/index.html +0 -1
  87. data/test/cgi/assets/javascripts/app.js +0 -1
  88. data/test/cgi/assets/stylesheets/app.css +0 -1
  89. data/test/cgi/lighttpd.conf +0 -26
  90. data/test/cgi/rackup_stub.rb +0 -6
  91. data/test/cgi/sample_rackup.ru +0 -5
  92. data/test/cgi/test +0 -9
  93. data/test/cgi/test+directory/test+file +0 -1
  94. data/test/cgi/test.fcgi +0 -9
  95. data/test/cgi/test.gz +0 -0
  96. data/test/cgi/test.ru +0 -5
  97. data/test/gemloader.rb +0 -10
  98. data/test/helper.rb +0 -34
  99. data/test/multipart/bad_robots +0 -259
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/content_type_and_no_filename +0 -6
  102. data/test/multipart/empty +0 -10
  103. data/test/multipart/fail_16384_nofile +0 -814
  104. data/test/multipart/file1.txt +0 -1
  105. data/test/multipart/filename_and_modification_param +0 -7
  106. data/test/multipart/filename_and_no_name +0 -6
  107. data/test/multipart/filename_with_encoded_words +0 -7
  108. data/test/multipart/filename_with_escaped_quotes +0 -6
  109. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  110. data/test/multipart/filename_with_null_byte +0 -7
  111. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_single_quote +0 -7
  113. data/test/multipart/filename_with_unescaped_percentages +0 -6
  114. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  116. data/test/multipart/filename_with_unescaped_quotes +0 -6
  117. data/test/multipart/ie +0 -6
  118. data/test/multipart/invalid_character +0 -6
  119. data/test/multipart/mixed_files +0 -21
  120. data/test/multipart/nested +0 -10
  121. data/test/multipart/none +0 -9
  122. data/test/multipart/quoted +0 -15
  123. data/test/multipart/rack-logo.png +0 -0
  124. data/test/multipart/semicolon +0 -6
  125. data/test/multipart/text +0 -15
  126. data/test/multipart/three_files_three_fields +0 -31
  127. data/test/multipart/unity3d_wwwform +0 -11
  128. data/test/multipart/webkit +0 -32
  129. data/test/rackup/config.ru +0 -31
  130. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  131. data/test/spec_auth_basic.rb +0 -89
  132. data/test/spec_auth_digest.rb +0 -260
  133. data/test/spec_body_proxy.rb +0 -85
  134. data/test/spec_builder.rb +0 -233
  135. data/test/spec_cascade.rb +0 -63
  136. data/test/spec_cgi.rb +0 -84
  137. data/test/spec_chunked.rb +0 -103
  138. data/test/spec_common_logger.rb +0 -95
  139. data/test/spec_conditional_get.rb +0 -103
  140. data/test/spec_config.rb +0 -23
  141. data/test/spec_content_length.rb +0 -86
  142. data/test/spec_content_type.rb +0 -46
  143. data/test/spec_deflater.rb +0 -375
  144. data/test/spec_directory.rb +0 -148
  145. data/test/spec_etag.rb +0 -108
  146. data/test/spec_events.rb +0 -133
  147. data/test/spec_fastcgi.rb +0 -85
  148. data/test/spec_file.rb +0 -264
  149. data/test/spec_handler.rb +0 -57
  150. data/test/spec_head.rb +0 -46
  151. data/test/spec_lint.rb +0 -515
  152. data/test/spec_lobster.rb +0 -59
  153. data/test/spec_lock.rb +0 -204
  154. data/test/spec_logger.rb +0 -24
  155. data/test/spec_media_type.rb +0 -42
  156. data/test/spec_method_override.rb +0 -110
  157. data/test/spec_mime.rb +0 -51
  158. data/test/spec_mock.rb +0 -359
  159. data/test/spec_multipart.rb +0 -722
  160. data/test/spec_null_logger.rb +0 -21
  161. data/test/spec_recursive.rb +0 -75
  162. data/test/spec_request.rb +0 -1398
  163. data/test/spec_response.rb +0 -510
  164. data/test/spec_rewindable_input.rb +0 -128
  165. data/test/spec_runtime.rb +0 -50
  166. data/test/spec_sendfile.rb +0 -125
  167. data/test/spec_server.rb +0 -193
  168. data/test/spec_session_abstract_id.rb +0 -31
  169. data/test/spec_session_abstract_session_hash.rb +0 -45
  170. data/test/spec_session_cookie.rb +0 -442
  171. data/test/spec_session_memcache.rb +0 -320
  172. data/test/spec_session_pool.rb +0 -210
  173. data/test/spec_show_exceptions.rb +0 -93
  174. data/test/spec_show_status.rb +0 -104
  175. data/test/spec_static.rb +0 -184
  176. data/test/spec_tempfile_reaper.rb +0 -64
  177. data/test/spec_thin.rb +0 -96
  178. data/test/spec_urlmap.rb +0 -237
  179. data/test/spec_utils.rb +0 -742
  180. data/test/spec_version.rb +0 -11
  181. data/test/spec_webrick.rb +0 -206
  182. data/test/static/another/index.html +0 -1
  183. data/test/static/foo.html +0 -1
  184. data/test/static/index.html +0 -1
  185. data/test/testrequest.rb +0 -78
  186. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  187. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/file.rb CHANGED
@@ -1,176 +1,8 @@
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 'rack/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
+ warn "Rack::File is deprecated, please use Rack::Files instead."
7
+ File = Files
176
8
  end
data/lib/rack/files.rb ADDED
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'rack/utils'
5
+ require 'rack/mime'
6
+ require 'rack/request'
7
+ require 'rack/head'
8
+
9
+ module Rack
10
+ # Rack::Files serves files below the +root+ directory given, according to the
11
+ # path info of the Rack request.
12
+ # e.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file
13
+ # as http://localhost:9292/passwd
14
+ #
15
+ # Handlers can detect if bodies are a Rack::Files, and use mechanisms
16
+ # like sendfile on the +path+.
17
+
18
+ class Files
19
+ ALLOWED_VERBS = %w[GET HEAD OPTIONS]
20
+ ALLOW_HEADER = ALLOWED_VERBS.join(', ')
21
+
22
+ attr_reader :root
23
+
24
+ def initialize(root, headers = {}, default_mime = 'text/plain')
25
+ @root = ::File.expand_path root
26
+ @headers = headers
27
+ @default_mime = default_mime
28
+ @head = Rack::Head.new(lambda { |env| get env })
29
+ end
30
+
31
+ def call(env)
32
+ # HEAD requests drop the response body, including 4xx error messages.
33
+ @head.call env
34
+ end
35
+
36
+ def get(env)
37
+ request = Rack::Request.new env
38
+ unless ALLOWED_VERBS.include? request.request_method
39
+ return fail(405, "Method Not Allowed", { 'Allow' => ALLOW_HEADER })
40
+ end
41
+
42
+ path_info = Utils.unescape_path request.path_info
43
+ return fail(400, "Bad Request") unless Utils.valid_path?(path_info)
44
+
45
+ clean_path_info = Utils.clean_path_info(path_info)
46
+ path = ::File.join(@root, clean_path_info)
47
+
48
+ available = begin
49
+ ::File.file?(path) && ::File.readable?(path)
50
+ rescue SystemCallError
51
+ false
52
+ end
53
+
54
+ if available
55
+ serving(request, path)
56
+ else
57
+ fail(404, "File not found: #{path_info}")
58
+ end
59
+ end
60
+
61
+ def serving(request, path)
62
+ if request.options?
63
+ return [200, { 'Allow' => ALLOW_HEADER, CONTENT_LENGTH => '0' }, []]
64
+ end
65
+ last_modified = ::File.mtime(path).httpdate
66
+ return [304, {}, []] if request.get_header('HTTP_IF_MODIFIED_SINCE') == last_modified
67
+
68
+ headers = { "Last-Modified" => last_modified }
69
+ mime_type = mime_type path, @default_mime
70
+ headers[CONTENT_TYPE] = mime_type if mime_type
71
+
72
+ # Set custom headers
73
+ @headers.each { |field, content| headers[field] = content } if @headers
74
+
75
+ response = [ 200, headers ]
76
+
77
+ size = filesize path
78
+
79
+ range = nil
80
+ ranges = Rack::Utils.get_byte_ranges(request.get_header('HTTP_RANGE'), size)
81
+ if ranges.nil? || ranges.length > 1
82
+ # No ranges, or multiple ranges (which we don't support):
83
+ # TODO: Support multiple byte-ranges
84
+ response[0] = 200
85
+ range = 0..size - 1
86
+ elsif ranges.empty?
87
+ # Unsatisfiable. Return error, and file size:
88
+ response = fail(416, "Byte range unsatisfiable")
89
+ response[1]["Content-Range"] = "bytes */#{size}"
90
+ return response
91
+ else
92
+ # Partial content:
93
+ range = ranges[0]
94
+ response[0] = 206
95
+ response[1]["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{size}"
96
+ size = range.end - range.begin + 1
97
+ end
98
+
99
+ response[2] = [response_body] unless response_body.nil?
100
+
101
+ response[1][CONTENT_LENGTH] = size.to_s
102
+ response[2] = make_body request, path, range
103
+ response
104
+ end
105
+
106
+ class Iterator
107
+ attr_reader :path, :range
108
+ alias :to_path :path
109
+
110
+ def initialize path, range
111
+ @path = path
112
+ @range = range
113
+ end
114
+
115
+ def each
116
+ ::File.open(path, "rb") do |file|
117
+ file.seek(range.begin)
118
+ remaining_len = range.end - range.begin + 1
119
+ while remaining_len > 0
120
+ part = file.read([8192, remaining_len].min)
121
+ break unless part
122
+ remaining_len -= part.length
123
+
124
+ yield part
125
+ end
126
+ end
127
+ end
128
+
129
+ def close; end
130
+ end
131
+
132
+ private
133
+
134
+ def make_body request, path, range
135
+ if request.head?
136
+ []
137
+ else
138
+ Iterator.new path, range
139
+ end
140
+ end
141
+
142
+ def fail(status, body, headers = {})
143
+ body += "\n"
144
+
145
+ [
146
+ status,
147
+ {
148
+ CONTENT_TYPE => "text/plain",
149
+ CONTENT_LENGTH => body.size.to_s,
150
+ "X-Cascade" => "pass"
151
+ }.merge!(headers),
152
+ [body]
153
+ ]
154
+ end
155
+
156
+ # The MIME type for the contents of the file located at @path
157
+ def mime_type path, default_mime
158
+ Mime.mime_type(::File.extname(path), default_mime)
159
+ end
160
+
161
+ def filesize path
162
+ # If response_body is present, use its size.
163
+ return response_body.bytesize if response_body
164
+
165
+ # We check via File::size? whether this file provides size info
166
+ # via stat (e.g. /proc files often don't), otherwise we have to
167
+ # figure it out by reading the whole file into memory.
168
+ ::File.size?(path) || ::File.read(path).bytesize
169
+ end
170
+
171
+ # By default, the response body for file requests is nil.
172
+ # In this case, the response body will be generated later
173
+ # from the file at @path
174
+ def response_body
175
+ nil
176
+ end
177
+ end
178
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/content_length'
2
4
  require 'rack/rewindable_input'
3
5
 
4
6
  module Rack
5
7
  module Handler
6
8
  class CGI
7
- def self.run(app, options=nil)
9
+ def self.run(app, options = nil)
8
10
  $stdin.binmode
9
11
  serve app
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fcgi'
2
4
  require 'socket'
3
5
  require 'rack/content_length'
@@ -7,7 +9,7 @@ if defined? FCGI::Stream
7
9
  class FCGI::Stream
8
10
  alias _rack_read_without_buffer read
9
11
 
10
- def read(n, buffer=nil)
12
+ def read(n, buffer = nil)
11
13
  buf = _rack_read_without_buffer n
12
14
  buffer.replace(buf.to_s) if buffer
13
15
  buf
@@ -18,7 +20,7 @@ end
18
20
  module Rack
19
21
  module Handler
20
22
  class FastCGI
21
- def self.run(app, options={})
23
+ def self.run(app, options = {})
22
24
  if options[:File]
23
25
  STDIN.reopen(UNIXServer.new(options[:File]))
24
26
  elsif options[:Port]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'lsapi'
2
4
  require 'rack/content_length'
3
5
  require 'rack/rewindable_input'
@@ -5,7 +7,7 @@ require 'rack/rewindable_input'
5
7
  module Rack
6
8
  module Handler
7
9
  class LSWS
8
- def self.run(app, options=nil)
10
+ def self.run(app, options = nil)
9
11
  while LSAPI.accept != nil
10
12
  serve app
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'scgi'
2
4
  require 'stringio'
3
5
  require 'rack/content_length'
@@ -8,12 +10,12 @@ module Rack
8
10
  class SCGI < ::SCGI::Processor
9
11
  attr_accessor :app
10
12
 
11
- def self.run(app, options=nil)
13
+ def self.run(app, options = nil)
12
14
  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
15
+ new(options.merge(app: app,
16
+ host: options[:Host],
17
+ port: options[:Port],
18
+ socket: options[:Socket])).listen
17
19
  end
18
20
 
19
21
  def self.valid_options
@@ -41,7 +43,8 @@ module Rack
41
43
  env[QUERY_STRING] ||= ""
42
44
  env[SCRIPT_NAME] = ""
43
45
 
44
- rack_input = StringIO.new(input_body, encoding: Encoding::BINARY)
46
+ rack_input = StringIO.new(input_body)
47
+ rack_input.set_encoding(Encoding::BINARY)
45
48
 
46
49
  env.update(
47
50
  RACK_VERSION => Rack::VERSION,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thin"
2
4
  require "thin/server"
3
5
  require "thin/logging"
@@ -8,7 +10,7 @@ require "rack/chunked"
8
10
  module Rack
9
11
  module Handler
10
12
  class Thin
11
- def self.run(app, options={})
13
+ def self.run(app, options = {})
12
14
  environment = ENV['RACK_ENV'] || 'development'
13
15
  default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
14
16
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webrick'
2
4
  require 'stringio'
3
5
  require 'rack/content_length'
@@ -22,7 +24,7 @@ end
22
24
  module Rack
23
25
  module Handler
24
26
  class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
25
- def self.run(app, options={})
27
+ def self.run(app, options = {})
26
28
  environment = ENV['RACK_ENV'] || 'development'
27
29
  default_host = environment == 'development' ? 'localhost' : nil
28
30
 
@@ -79,7 +81,7 @@ module Rack
79
81
  env[QUERY_STRING] ||= ""
80
82
  unless env[PATH_INFO] == ""
81
83
  path, n = req.request_uri.path, env[SCRIPT_NAME].length
82
- env[PATH_INFO] = path[n, path.length-n]
84
+ env[PATH_INFO] = path[n, path.length - n]
83
85
  end
84
86
  env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
85
87
 
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/body_proxy'
2
4
 
3
5
  module Rack
data/lib/rack/lint.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/utils'
2
4
  require 'forwardable'
3
5
 
@@ -33,7 +35,7 @@ module Rack
33
35
 
34
36
  ## A Rack application is a Ruby object (not a class) that
35
37
  ## responds to +call+.
36
- def call(env=nil)
38
+ def call(env = nil)
37
39
  dup._call(env)
38
40
  end
39
41
 
@@ -123,9 +125,8 @@ module Rack
123
125
  ## the presence or absence of the
124
126
  ## appropriate HTTP header in the
125
127
  ## request. See
126
- ## <a href="https://tools.ietf.org/html/rfc3875#section-4.1.18">
127
- ## RFC3875 section 4.1.18</a> for
128
- ## specific behavior.
128
+ ## {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18]
129
+ ## for specific behavior.
129
130
 
130
131
  ## In addition to this, the Rack environment must include these
131
132
  ## Rack-specific variables:
@@ -263,7 +264,7 @@ module Rack
263
264
  ## <tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
264
265
  ## (use the versions without <tt>HTTP_</tt>).
265
266
  %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header|
266
- assert("env contains #{header}, must use #{header[5,-1]}") {
267
+ assert("env contains #{header}, must use #{header[5, -1]}") {
267
268
  not env.include? header
268
269
  }
269
270
  }
@@ -626,15 +627,17 @@ module Rack
626
627
  assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
627
628
  header.respond_to? :each
628
629
  }
629
- header.each { |key, value|
630
- ## Special headers starting "rack." are for communicating with the
631
- ## server, and must not be sent back to the client.
632
- next if key =~ /^rack\..+$/
633
630
 
631
+ header.each { |key, value|
634
632
  ## The header keys must be Strings.
635
633
  assert("header key must be a string, was #{key.class}") {
636
634
  key.kind_of? String
637
635
  }
636
+
637
+ ## Special headers starting "rack." are for communicating with the
638
+ ## server, and must not be sent back to the client.
639
+ next if key =~ /^rack\..+$/
640
+
638
641
  ## The header must not contain a +Status+ key.
639
642
  assert("header must not contain Status") { key.downcase != "status" }
640
643
  ## The header must conform to RFC7230 token specification, i.e. cannot
@@ -662,7 +665,7 @@ module Rack
662
665
  ## 204 or 304.
663
666
  if key.downcase == "content-type"
664
667
  assert("Content-Type header found in #{status} response, not allowed") {
665
- not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
668
+ not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
666
669
  }
667
670
  return
668
671
  end
@@ -676,7 +679,7 @@ module Rack
676
679
  ## There must not be a <tt>Content-Length</tt> header when the
677
680
  ## +Status+ is 1xx, 204 or 304.
678
681
  assert("Content-Length header found in #{status} response, not allowed") {
679
- not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
682
+ not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
680
683
  }
681
684
  @content_length = value
682
685
  end
data/lib/rack/lobster.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zlib'
2
4
 
3
5
  require 'rack/request'
@@ -25,8 +27,8 @@ module Rack
25
27
  content = ["<title>Lobstericious!</title>",
26
28
  "<pre>", lobster, "</pre>",
27
29
  "<a href='#{href}'>flip!</a>"]
28
- length = content.inject(0) { |a,e| a+e.size }.to_s
29
- [200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content]
30
+ length = content.inject(0) { |a, e| a + e.size }.to_s
31
+ [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
30
32
  }
31
33
 
32
34
  def call(env)
@@ -37,8 +39,8 @@ module Rack
37
39
  gsub('\\', 'TEMP').
38
40
  gsub('/', '\\').
39
41
  gsub('TEMP', '/').
40
- gsub('{','}').
41
- gsub('(',')')
42
+ gsub('{', '}').
43
+ gsub('(', ')')
42
44
  end.join("\n")
43
45
  href = "?flip=right"
44
46
  elsif req.GET["flip"] == "crash"
@@ -65,6 +67,6 @@ if $0 == __FILE__
65
67
  require 'rack'
66
68
  require 'rack/show_exceptions'
67
69
  Rack::Server.start(
68
- :app => Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292
70
+ app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
69
71
  )
70
72
  end
data/lib/rack/lock.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
  require 'rack/body_proxy'
3
5
 
data/lib/rack/logger.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module Rack
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  # Rack::MediaType parse media type and parameters out of content_type string
3
5
 
@@ -13,7 +15,7 @@ module Rack
13
15
  # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
14
16
  def type(content_type)
15
17
  return nil unless content_type
16
- content_type.split(SPLIT_PATTERN, 2).first.downcase
18
+ content_type.split(SPLIT_PATTERN, 2).first.tap &:downcase!
17
19
  end
18
20
 
19
21
  # The media type parameters provided in CONTENT_TYPE as a Hash, or
@@ -23,15 +25,18 @@ module Rack
23
25
  # { 'charset' => 'utf-8' }
24
26
  def params(content_type)
25
27
  return {} if content_type.nil?
26
- Hash[*content_type.split(SPLIT_PATTERN)[1..-1].
27
- collect { |s| s.split('=', 2) }.
28
- map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
28
+
29
+ content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
30
+ k, v = s.split('=', 2)
31
+
32
+ hsh[k.tap(&:downcase!)] = strip_doublequotes(v)
33
+ end
29
34
  end
30
35
 
31
36
  private
32
37
 
33
38
  def strip_doublequotes(str)
34
- (str[0] == ?" && str[-1] == ?") ? str[1..-2] : str
39
+ (str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str
35
40
  end
36
41
  end
37
42
  end