rack 1.6.13 → 2.1.4.3

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +105 -141
  5. data/Rakefile +27 -28
  6. data/SPEC +6 -7
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +7 -1
  14. data/lib/rack/auth/basic.rb +4 -1
  15. data/lib/rack/auth/digest/md5.rb +9 -7
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +3 -1
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +42 -18
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +33 -10
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +14 -10
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +5 -3
  27. data/lib/rack/content_type.rb +3 -1
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +33 -53
  30. data/lib/rack/directory.rb +75 -60
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -149
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +17 -16
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +22 -19
  39. data/lib/rack/handler/thin.rb +6 -1
  40. data/lib/rack/handler/webrick.rb +28 -28
  41. data/lib/rack/handler.rb +9 -26
  42. data/lib/rack/head.rb +17 -17
  43. data/lib/rack/lint.rb +55 -52
  44. data/lib/rack/lobster.rb +8 -6
  45. data/lib/rack/lock.rb +17 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  49. data/lib/rack/mime.rb +27 -6
  50. data/lib/rack/mock.rb +101 -60
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +292 -161
  53. data/lib/rack/multipart/uploaded_file.rb +3 -2
  54. data/lib/rack/multipart.rb +38 -8
  55. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +11 -9
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +447 -305
  60. data/lib/rack/response.rb +196 -83
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +12 -18
  63. data/lib/rack/sendfile.rb +19 -14
  64. data/lib/rack/server.rb +118 -41
  65. data/lib/rack/session/abstract/id.rb +139 -94
  66. data/lib/rack/session/cookie.rb +34 -26
  67. data/lib/rack/session/memcache.rb +4 -93
  68. data/lib/rack/session/pool.rb +12 -10
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +7 -5
  71. data/lib/rack/static.rb +41 -11
  72. data/lib/rack/tempfile_reaper.rb +4 -2
  73. data/lib/rack/urlmap.rb +25 -15
  74. data/lib/rack/utils.rb +203 -277
  75. data/lib/rack.rb +76 -24
  76. data/rack.gemspec +25 -14
  77. metadata +62 -183
  78. data/HISTORY.md +0 -375
  79. data/KNOWN-ISSUES +0 -44
  80. data/lib/rack/backports/uri/common_18.rb +0 -56
  81. data/lib/rack/backports/uri/common_192.rb +0 -52
  82. data/lib/rack/backports/uri/common_193.rb +0 -29
  83. data/lib/rack/handler/evented_mongrel.rb +0 -8
  84. data/lib/rack/handler/mongrel.rb +0 -106
  85. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  86. data/lib/rack/showexceptions.rb +0 -387
  87. data/lib/rack/utils/okjson.rb +0 -600
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/rackup_stub.rb +0 -6
  101. data/test/cgi/sample_rackup.ru +0 -5
  102. data/test/cgi/test +0 -9
  103. data/test/cgi/test+directory/test+file +0 -1
  104. data/test/cgi/test.fcgi +0 -8
  105. data/test/cgi/test.ru +0 -5
  106. data/test/gemloader.rb +0 -10
  107. data/test/multipart/bad_robots +0 -259
  108. data/test/multipart/binary +0 -0
  109. data/test/multipart/content_type_and_no_filename +0 -6
  110. data/test/multipart/empty +0 -10
  111. data/test/multipart/fail_16384_nofile +0 -814
  112. data/test/multipart/file1.txt +0 -1
  113. data/test/multipart/filename_and_modification_param +0 -7
  114. data/test/multipart/filename_and_no_name +0 -6
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_null_byte +0 -7
  118. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  121. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  122. data/test/multipart/filename_with_unescaped_quotes +0 -6
  123. data/test/multipart/ie +0 -6
  124. data/test/multipart/invalid_character +0 -6
  125. data/test/multipart/mixed_files +0 -21
  126. data/test/multipart/nested +0 -10
  127. data/test/multipart/none +0 -9
  128. data/test/multipart/semicolon +0 -6
  129. data/test/multipart/text +0 -15
  130. data/test/multipart/three_files_three_fields +0 -31
  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 -81
  135. data/test/spec_auth_digest.rb +0 -259
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -223
  138. data/test/spec_cascade.rb +0 -61
  139. data/test/spec_cgi.rb +0 -102
  140. data/test/spec_chunked.rb +0 -101
  141. data/test/spec_commonlogger.rb +0 -93
  142. data/test/spec_conditionalget.rb +0 -102
  143. data/test/spec_config.rb +0 -22
  144. data/test/spec_content_length.rb +0 -85
  145. data/test/spec_content_type.rb +0 -45
  146. data/test/spec_deflater.rb +0 -339
  147. data/test/spec_directory.rb +0 -88
  148. data/test/spec_etag.rb +0 -107
  149. data/test/spec_fastcgi.rb +0 -107
  150. data/test/spec_file.rb +0 -221
  151. data/test/spec_handler.rb +0 -72
  152. data/test/spec_head.rb +0 -45
  153. data/test/spec_lint.rb +0 -550
  154. data/test/spec_lobster.rb +0 -58
  155. data/test/spec_lock.rb +0 -164
  156. data/test/spec_logger.rb +0 -23
  157. data/test/spec_methodoverride.rb +0 -111
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -297
  160. data/test/spec_mongrel.rb +0 -182
  161. data/test/spec_multipart.rb +0 -600
  162. data/test/spec_nulllogger.rb +0 -20
  163. data/test/spec_recursive.rb +0 -72
  164. data/test/spec_request.rb +0 -1232
  165. data/test/spec_response.rb +0 -407
  166. data/test/spec_rewindable_input.rb +0 -118
  167. data/test/spec_runtime.rb +0 -49
  168. data/test/spec_sendfile.rb +0 -130
  169. data/test/spec_server.rb +0 -167
  170. data/test/spec_session_abstract_id.rb +0 -53
  171. data/test/spec_session_cookie.rb +0 -410
  172. data/test/spec_session_memcache.rb +0 -358
  173. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  174. data/test/spec_session_pool.rb +0 -246
  175. data/test/spec_showexceptions.rb +0 -98
  176. data/test/spec_showstatus.rb +0 -103
  177. data/test/spec_static.rb +0 -145
  178. data/test/spec_tempfile_reaper.rb +0 -63
  179. data/test/spec_thin.rb +0 -91
  180. data/test/spec_urlmap.rb +0 -236
  181. data/test/spec_utils.rb +0 -647
  182. data/test/spec_version.rb +0 -17
  183. data/test/spec_webrick.rb +0 -184
  184. data/test/static/another/index.html +0 -1
  185. data/test/static/index.html +0 -1
  186. data/test/testrequest.rb +0 -78
  187. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  188. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
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) if 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
@@ -13,22 +15,21 @@ module Rack
13
15
  env = ENV.to_hash
14
16
  env.delete "HTTP_CONTENT_LENGTH"
15
17
 
16
- env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
17
-
18
- env.update({"rack.version" => Rack::VERSION,
19
- "rack.input" => Rack::RewindableInput.new($stdin),
20
- "rack.errors" => $stderr,
21
-
22
- "rack.multithread" => false,
23
- "rack.multiprocess" => true,
24
- "rack.run_once" => true,
25
-
26
- "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
27
- })
28
-
29
- env[QUERY_STRING] ||= ""
30
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
31
- env["REQUEST_PATH"] ||= "/"
18
+ env[SCRIPT_NAME] = "" if env[SCRIPT_NAME] == "/"
19
+
20
+ env.update(
21
+ RACK_VERSION => Rack::VERSION,
22
+ RACK_INPUT => Rack::RewindableInput.new($stdin),
23
+ RACK_ERRORS => $stderr,
24
+ RACK_MULTITHREAD => false,
25
+ RACK_MULTIPROCESS => true,
26
+ RACK_RUNONCE => true,
27
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(ENV[HTTPS]) ? "https" : "http"
28
+ )
29
+
30
+ env[QUERY_STRING] ||= ""
31
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
32
+ env[REQUEST_PATH] ||= "/"
32
33
 
33
34
  status, headers, body = app.call(env)
34
35
  begin
@@ -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]
@@ -44,24 +46,23 @@ module Rack
44
46
  env = request.env
45
47
  env.delete "HTTP_CONTENT_LENGTH"
46
48
 
47
- env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
49
+ env[SCRIPT_NAME] = "" if env[SCRIPT_NAME] == "/"
48
50
 
49
51
  rack_input = RewindableInput.new(request.in)
50
52
 
51
- env.update({"rack.version" => Rack::VERSION,
52
- "rack.input" => rack_input,
53
- "rack.errors" => request.err,
54
-
55
- "rack.multithread" => false,
56
- "rack.multiprocess" => true,
57
- "rack.run_once" => false,
58
-
59
- "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
60
- })
53
+ env.update(
54
+ RACK_VERSION => Rack::VERSION,
55
+ RACK_INPUT => rack_input,
56
+ RACK_ERRORS => request.err,
57
+ RACK_MULTITHREAD => false,
58
+ RACK_MULTIPROCESS => true,
59
+ RACK_RUNONCE => false,
60
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
61
+ )
61
62
 
62
- env[QUERY_STRING] ||= ""
63
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
64
- env["REQUEST_PATH"] ||= "/"
63
+ env[QUERY_STRING] ||= ""
64
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
65
+ env[REQUEST_PATH] ||= "/"
65
66
  env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == ""
66
67
  env.delete "CONTENT_LENGTH" if env["CONTENT_LENGTH"] == ""
67
68
 
@@ -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
@@ -13,23 +15,23 @@ module Rack
13
15
  def self.serve(app)
14
16
  env = ENV.to_hash
15
17
  env.delete "HTTP_CONTENT_LENGTH"
16
- env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
18
+ env[SCRIPT_NAME] = "" if env[SCRIPT_NAME] == "/"
17
19
 
18
20
  rack_input = RewindableInput.new($stdin.read.to_s)
19
21
 
20
22
  env.update(
21
- "rack.version" => Rack::VERSION,
22
- "rack.input" => rack_input,
23
- "rack.errors" => $stderr,
24
- "rack.multithread" => false,
25
- "rack.multiprocess" => true,
26
- "rack.run_once" => false,
27
- "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http"
23
+ RACK_VERSION => Rack::VERSION,
24
+ RACK_INPUT => rack_input,
25
+ RACK_ERRORS => $stderr,
26
+ RACK_MULTITHREAD => false,
27
+ RACK_MULTIPROCESS => true,
28
+ RACK_RUNONCE => false,
29
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(ENV[HTTPS]) ? "https" : "http"
28
30
  )
29
31
 
30
- env[QUERY_STRING] ||= ""
31
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
32
- env["REQUEST_PATH"] ||= "/"
32
+ env[QUERY_STRING] ||= ""
33
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
34
+ env[REQUEST_PATH] ||= "/"
33
35
  status, headers, body = app.call(env)
34
36
  begin
35
37
  send_headers status, headers
@@ -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
@@ -35,24 +37,25 @@ module Rack
35
37
  env = Hash[request]
36
38
  env.delete "HTTP_CONTENT_TYPE"
37
39
  env.delete "HTTP_CONTENT_LENGTH"
38
- env["REQUEST_PATH"], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
39
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
40
- env[PATH_INFO] = env["REQUEST_PATH"]
41
- env["QUERY_STRING"] ||= ""
42
- env["SCRIPT_NAME"] = ""
40
+ env[REQUEST_PATH], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
41
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
42
+ env[PATH_INFO] = env[REQUEST_PATH]
43
+ env[QUERY_STRING] ||= ""
44
+ env[SCRIPT_NAME] = ""
43
45
 
44
46
  rack_input = StringIO.new(input_body)
45
- rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
47
+ rack_input.set_encoding(Encoding::BINARY)
46
48
 
47
- env.update({"rack.version" => Rack::VERSION,
48
- "rack.input" => rack_input,
49
- "rack.errors" => $stderr,
50
- "rack.multithread" => true,
51
- "rack.multiprocess" => true,
52
- "rack.run_once" => false,
49
+ env.update(
50
+ RACK_VERSION => Rack::VERSION,
51
+ RACK_INPUT => rack_input,
52
+ RACK_ERRORS => $stderr,
53
+ RACK_MULTITHREAD => true,
54
+ RACK_MULTIPROCESS => true,
55
+ RACK_RUNONCE => false,
56
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
57
+ )
53
58
 
54
- "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
55
- })
56
59
  status, headers, body = app.call(env)
57
60
  begin
58
61
  socket.write("Status: #{status}\r\n")
@@ -1,11 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thin"
4
+ require "thin/server"
5
+ require "thin/logging"
6
+ require "thin/backends/tcp_server"
2
7
  require "rack/content_length"
3
8
  require "rack/chunked"
4
9
 
5
10
  module Rack
6
11
  module Handler
7
12
  class Thin
8
- def self.run(app, options={})
13
+ def self.run(app, options = {})
9
14
  environment = ENV['RACK_ENV'] || 'development'
10
15
  default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
11
16
 
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webrick'
2
4
  require 'stringio'
3
5
  require 'rack/content_length'
4
6
 
5
7
  # This monkey patch allows for applications to perform their own chunking
6
- # through WEBrick::HTTPResponse iff rack is set to true.
8
+ # through WEBrick::HTTPResponse if rack is set to true.
7
9
  class WEBrick::HTTPResponse
8
10
  attr_accessor :rack
9
11
 
@@ -22,9 +24,9 @@ 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
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
29
+ default_host = environment == 'development' ? 'localhost' : nil
28
30
 
29
31
  options[:BindAddress] = options.delete(:Host) || default_host
30
32
  options[:Port] ||= 8080
@@ -60,38 +62,37 @@ module Rack
60
62
  env.delete_if { |k, v| v.nil? }
61
63
 
62
64
  rack_input = StringIO.new(req.body.to_s)
63
- rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
64
-
65
- env.update({"rack.version" => Rack::VERSION,
66
- "rack.input" => rack_input,
67
- "rack.errors" => $stderr,
68
-
69
- "rack.multithread" => true,
70
- "rack.multiprocess" => false,
71
- "rack.run_once" => false,
72
-
73
- "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http",
74
-
75
- "rack.hijack?" => true,
76
- "rack.hijack" => lambda { raise NotImplementedError, "only partial hijack is supported."},
77
- "rack.hijack_io" => nil,
78
- })
79
-
80
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
65
+ rack_input.set_encoding(Encoding::BINARY)
66
+
67
+ env.update(
68
+ RACK_VERSION => Rack::VERSION,
69
+ RACK_INPUT => rack_input,
70
+ RACK_ERRORS => $stderr,
71
+ RACK_MULTITHREAD => true,
72
+ RACK_MULTIPROCESS => false,
73
+ RACK_RUNONCE => false,
74
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http",
75
+ RACK_IS_HIJACK => true,
76
+ RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."},
77
+ RACK_HIJACK_IO => nil
78
+ )
79
+
80
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
81
81
  env[QUERY_STRING] ||= ""
82
82
  unless env[PATH_INFO] == ""
83
- path, n = req.request_uri.path, env["SCRIPT_NAME"].length
84
- env[PATH_INFO] = path[n, path.length-n]
83
+ path, n = req.request_uri.path, env[SCRIPT_NAME].length
84
+ env[PATH_INFO] = path[n, path.length - n]
85
85
  end
86
- env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join
86
+ env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
87
87
 
88
88
  status, headers, body = @app.call(env)
89
89
  begin
90
90
  res.status = status.to_i
91
+ io_lambda = nil
91
92
  headers.each { |k, vs|
92
- next if k.downcase == "rack.hijack"
93
-
94
- if k.downcase == "set-cookie"
93
+ if k == RACK_HIJACK
94
+ io_lambda = vs
95
+ elsif k.downcase == "set-cookie"
95
96
  res.cookies.concat vs.split("\n")
96
97
  else
97
98
  # Since WEBrick won't accept repeated headers,
@@ -100,7 +101,6 @@ module Rack
100
101
  end
101
102
  }
102
103
 
103
- io_lambda = headers["rack.hijack"]
104
104
  if io_lambda
105
105
  rd, wr = IO.pipe
106
106
  res.body = rd
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,27 +19,15 @@ 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
- _const_get(server, false)
24
+ const_get(server, false)
23
25
  end
24
26
 
25
27
  rescue NameError => name_error
26
28
  raise load_error || name_error
27
29
  end
28
30
 
29
- begin
30
- ::Object.const_get("Object", false)
31
- def self._const_get(str, inherit = true)
32
- const_get(str, inherit)
33
- end
34
- rescue
35
- def self._const_get(str, inherit = true)
36
- const_get(str)
37
- end
38
- end
39
-
40
-
41
31
  # Select first available Rack handler given an `Array` of server names.
42
32
  # Raises `LoadError` if no handler was found.
43
33
  #
@@ -55,20 +45,19 @@ module Rack
55
45
  raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
56
46
  end
57
47
 
58
- def self.default(options = {})
48
+ SERVER_NAMES = %w(puma thin falcon webrick).freeze
49
+ private_constant :SERVER_NAMES
50
+
51
+ def self.default
59
52
  # Guess.
60
53
  if ENV.include?("PHP_FCGI_CHILDREN")
61
- # We already speak FastCGI
62
- options.delete :File
63
- options.delete :Port
64
-
65
54
  Rack::Handler::FastCGI
66
55
  elsif ENV.include?(REQUEST_METHOD)
67
56
  Rack::Handler::CGI
68
57
  elsif ENV.include?("RACK_HANDLER")
69
58
  self.get(ENV["RACK_HANDLER"])
70
59
  else
71
- pick ['thin', 'puma', 'webrick']
60
+ pick SERVER_NAMES
72
61
  end
73
62
  end
74
63
 
@@ -100,9 +89,6 @@ module Rack
100
89
 
101
90
  autoload :CGI, "rack/handler/cgi"
102
91
  autoload :FastCGI, "rack/handler/fastcgi"
103
- autoload :Mongrel, "rack/handler/mongrel"
104
- autoload :EventedMongrel, "rack/handler/evented_mongrel"
105
- autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel"
106
92
  autoload :WEBrick, "rack/handler/webrick"
107
93
  autoload :LSWS, "rack/handler/lsws"
108
94
  autoload :SCGI, "rack/handler/scgi"
@@ -110,9 +96,6 @@ module Rack
110
96
 
111
97
  register 'cgi', 'Rack::Handler::CGI'
112
98
  register 'fastcgi', 'Rack::Handler::FastCGI'
113
- register 'mongrel', 'Rack::Handler::Mongrel'
114
- register 'emongrel', 'Rack::Handler::EventedMongrel'
115
- register 'smongrel', 'Rack::Handler::SwiftipliedMongrel'
116
99
  register 'webrick', 'Rack::Handler::WEBrick'
117
100
  register 'lsws', 'Rack::Handler::LSWS'
118
101
  register 'scgi', 'Rack::Handler::SCGI'
data/lib/rack/head.rb CHANGED
@@ -1,27 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/body_proxy'
2
4
 
3
5
  module Rack
4
-
5
- class Head
6
6
  # Rack::Head returns an empty body for all HEAD requests. It leaves
7
7
  # all other requests unchanged.
8
- def initialize(app)
9
- @app = app
10
- end
8
+ class Head
9
+ def initialize(app)
10
+ @app = app
11
+ end
11
12
 
12
- def call(env)
13
- status, headers, body = @app.call(env)
13
+ def call(env)
14
+ status, headers, body = @app.call(env)
14
15
 
15
- if env[REQUEST_METHOD] == HEAD
16
- [
17
- status, headers, Rack::BodyProxy.new([]) do
18
- body.close if body.respond_to? :close
19
- end
20
- ]
21
- else
22
- [status, headers, body]
16
+ if env[REQUEST_METHOD] == HEAD
17
+ [
18
+ status, headers, Rack::BodyProxy.new([]) do
19
+ body.close if body.respond_to? :close
20
+ end
21
+ ]
22
+ else
23
+ [status, headers, body]
24
+ end
23
25
  end
24
26
  end
25
27
  end
26
-
27
- end