rack 2.2.8 → 3.0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +213 -83
  3. data/CONTRIBUTING.md +53 -47
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +309 -0
  6. data/SPEC.rdoc +174 -126
  7. data/lib/rack/auth/abstract/handler.rb +3 -1
  8. data/lib/rack/auth/abstract/request.rb +3 -1
  9. data/lib/rack/auth/basic.rb +0 -2
  10. data/lib/rack/auth/digest/md5.rb +1 -131
  11. data/lib/rack/auth/digest/nonce.rb +1 -54
  12. data/lib/rack/auth/digest/params.rb +1 -54
  13. data/lib/rack/auth/digest/request.rb +1 -43
  14. data/lib/rack/auth/digest.rb +256 -0
  15. data/lib/rack/body_proxy.rb +3 -1
  16. data/lib/rack/builder.rb +83 -63
  17. data/lib/rack/cascade.rb +2 -0
  18. data/lib/rack/chunked.rb +16 -13
  19. data/lib/rack/common_logger.rb +23 -18
  20. data/lib/rack/conditional_get.rb +18 -15
  21. data/lib/rack/constants.rb +64 -0
  22. data/lib/rack/content_length.rb +12 -16
  23. data/lib/rack/content_type.rb +8 -5
  24. data/lib/rack/deflater.rb +40 -26
  25. data/lib/rack/directory.rb +9 -3
  26. data/lib/rack/etag.rb +14 -23
  27. data/lib/rack/events.rb +4 -0
  28. data/lib/rack/file.rb +2 -0
  29. data/lib/rack/files.rb +15 -17
  30. data/lib/rack/head.rb +9 -8
  31. data/lib/rack/headers.rb +154 -0
  32. data/lib/rack/lint.rb +758 -646
  33. data/lib/rack/lock.rb +2 -5
  34. data/lib/rack/logger.rb +2 -0
  35. data/lib/rack/media_type.rb +9 -4
  36. data/lib/rack/method_override.rb +5 -1
  37. data/lib/rack/mime.rb +8 -0
  38. data/lib/rack/mock.rb +1 -271
  39. data/lib/rack/mock_request.rb +166 -0
  40. data/lib/rack/mock_response.rb +126 -0
  41. data/lib/rack/multipart/generator.rb +7 -5
  42. data/lib/rack/multipart/parser.rb +120 -64
  43. data/lib/rack/multipart/uploaded_file.rb +4 -0
  44. data/lib/rack/multipart.rb +20 -40
  45. data/lib/rack/null_logger.rb +9 -0
  46. data/lib/rack/query_parser.rb +78 -46
  47. data/lib/rack/recursive.rb +2 -0
  48. data/lib/rack/reloader.rb +0 -2
  49. data/lib/rack/request.rb +224 -106
  50. data/lib/rack/response.rb +138 -61
  51. data/lib/rack/rewindable_input.rb +24 -5
  52. data/lib/rack/runtime.rb +7 -6
  53. data/lib/rack/sendfile.rb +30 -25
  54. data/lib/rack/show_exceptions.rb +15 -2
  55. data/lib/rack/show_status.rb +17 -7
  56. data/lib/rack/static.rb +8 -8
  57. data/lib/rack/tempfile_reaper.rb +15 -4
  58. data/lib/rack/urlmap.rb +3 -1
  59. data/lib/rack/utils.rb +208 -178
  60. data/lib/rack/version.rb +9 -4
  61. data/lib/rack.rb +6 -76
  62. metadata +14 -34
  63. data/README.rdoc +0 -320
  64. data/Rakefile +0 -130
  65. data/bin/rackup +0 -5
  66. data/contrib/rack.png +0 -0
  67. data/contrib/rack.svg +0 -150
  68. data/contrib/rack_logo.svg +0 -164
  69. data/contrib/rdoc.css +0 -412
  70. data/example/lobster.ru +0 -6
  71. data/example/protectedlobster.rb +0 -16
  72. data/example/protectedlobster.ru +0 -10
  73. data/lib/rack/core_ext/regexp.rb +0 -14
  74. data/lib/rack/handler/cgi.rb +0 -59
  75. data/lib/rack/handler/fastcgi.rb +0 -100
  76. data/lib/rack/handler/lsws.rb +0 -61
  77. data/lib/rack/handler/scgi.rb +0 -71
  78. data/lib/rack/handler/thin.rb +0 -36
  79. data/lib/rack/handler/webrick.rb +0 -129
  80. data/lib/rack/handler.rb +0 -104
  81. data/lib/rack/lobster.rb +0 -70
  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 -204
  85. data/lib/rack/session/memcache.rb +0 -10
  86. data/lib/rack/session/pool.rb +0 -85
  87. data/rack.gemspec +0 -46
data/lib/rack/server.rb DELETED
@@ -1,466 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'optparse'
4
- require 'fileutils'
5
-
6
- module Rack
7
-
8
- class Server
9
- (require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
10
-
11
- class Options
12
- def parse!(args)
13
- options = {}
14
- opt_parser = OptionParser.new("", 24, ' ') do |opts|
15
- opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]"
16
-
17
- opts.separator ""
18
- opts.separator "Ruby options:"
19
-
20
- lineno = 1
21
- opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
22
- eval line, TOPLEVEL_BINDING, "-e", lineno
23
- lineno += 1
24
- }
25
-
26
- opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
27
- options[:debug] = true
28
- }
29
- opts.on("-w", "--warn", "turn warnings on for your script") {
30
- options[:warn] = true
31
- }
32
- opts.on("-q", "--quiet", "turn off logging") {
33
- options[:quiet] = true
34
- }
35
-
36
- opts.on("-I", "--include PATH",
37
- "specify $LOAD_PATH (may be used more than once)") { |path|
38
- (options[:include] ||= []).concat(path.split(":"))
39
- }
40
-
41
- opts.on("-r", "--require LIBRARY",
42
- "require the library, before executing your script") { |library|
43
- (options[:require] ||= []) << library
44
- }
45
-
46
- opts.separator ""
47
- opts.separator "Rack options:"
48
- opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line|
49
- options[:builder] = line
50
- }
51
-
52
- opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick)") { |s|
53
- options[:server] = s
54
- }
55
-
56
- opts.on("-o", "--host HOST", "listen on HOST (default: localhost)") { |host|
57
- options[:Host] = host
58
- }
59
-
60
- opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port|
61
- options[:Port] = port
62
- }
63
-
64
- opts.on("-O", "--option NAME[=VALUE]", "pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} -s SERVER -h' to get a list of options for SERVER") { |name|
65
- name, value = name.split('=', 2)
66
- value = true if value.nil?
67
- options[name.to_sym] = value
68
- }
69
-
70
- opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e|
71
- options[:environment] = e
72
- }
73
-
74
- opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
75
- options[:daemonize] = d ? true : false
76
- }
77
-
78
- opts.on("-P", "--pid FILE", "file to store PID") { |f|
79
- options[:pid] = ::File.expand_path(f)
80
- }
81
-
82
- opts.separator ""
83
- opts.separator "Profiling options:"
84
-
85
- opts.on("--heap HEAPFILE", "Build the application, then dump the heap to HEAPFILE") do |e|
86
- options[:heapfile] = e
87
- end
88
-
89
- opts.on("--profile PROFILE", "Dump CPU or Memory profile to PROFILE (defaults to a tempfile)") do |e|
90
- options[:profile_file] = e
91
- end
92
-
93
- opts.on("--profile-mode MODE", "Profile mode (cpu|wall|object)") do |e|
94
- { cpu: true, wall: true, object: true }.fetch(e.to_sym) do
95
- raise OptionParser::InvalidOption, "unknown profile mode: #{e}"
96
- end
97
- options[:profile_mode] = e.to_sym
98
- end
99
-
100
- opts.separator ""
101
- opts.separator "Common options:"
102
-
103
- opts.on_tail("-h", "-?", "--help", "Show this message") do
104
- puts opts
105
- puts handler_opts(options)
106
-
107
- exit
108
- end
109
-
110
- opts.on_tail("--version", "Show version") do
111
- puts "Rack #{Rack.version} (Release: #{Rack.release})"
112
- exit
113
- end
114
- end
115
-
116
- begin
117
- opt_parser.parse! args
118
- rescue OptionParser::InvalidOption => e
119
- warn e.message
120
- abort opt_parser.to_s
121
- end
122
-
123
- options[:config] = args.last if args.last && !args.last.empty?
124
- options
125
- end
126
-
127
- def handler_opts(options)
128
- begin
129
- info = []
130
- server = Rack::Handler.get(options[:server]) || Rack::Handler.default
131
- if server && server.respond_to?(:valid_options)
132
- info << ""
133
- info << "Server-specific options for #{server.name}:"
134
-
135
- has_options = false
136
- server.valid_options.each do |name, description|
137
- next if /^(Host|Port)[^a-zA-Z]/.match?(name.to_s) # ignore handler's host and port options, we do our own.
138
- info << " -O %-21s %s" % [name, description]
139
- has_options = true
140
- end
141
- return "" if !has_options
142
- end
143
- info.join("\n")
144
- rescue NameError, LoadError
145
- return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options"
146
- end
147
- end
148
- end
149
-
150
- # Start a new rack server (like running rackup). This will parse ARGV and
151
- # provide standard ARGV rackup options, defaulting to load 'config.ru'.
152
- #
153
- # Providing an options hash will prevent ARGV parsing and will not include
154
- # any default options.
155
- #
156
- # This method can be used to very easily launch a CGI application, for
157
- # example:
158
- #
159
- # Rack::Server.start(
160
- # :app => lambda do |e|
161
- # [200, {'Content-Type' => 'text/html'}, ['hello world']]
162
- # end,
163
- # :server => 'cgi'
164
- # )
165
- #
166
- # Further options available here are documented on Rack::Server#initialize
167
- def self.start(options = nil)
168
- new(options).start
169
- end
170
-
171
- attr_writer :options
172
-
173
- # Options may include:
174
- # * :app
175
- # a rack application to run (overrides :config and :builder)
176
- # * :builder
177
- # a string to evaluate a Rack::Builder from
178
- # * :config
179
- # a rackup configuration file path to load (.ru)
180
- # * :environment
181
- # this selects the middleware that will be wrapped around
182
- # your application. Default options available are:
183
- # - development: CommonLogger, ShowExceptions, and Lint
184
- # - deployment: CommonLogger
185
- # - none: no extra middleware
186
- # note: when the server is a cgi server, CommonLogger is not included.
187
- # * :server
188
- # choose a specific Rack::Handler, e.g. cgi, fcgi, webrick
189
- # * :daemonize
190
- # if true, the server will daemonize itself (fork, detach, etc)
191
- # * :pid
192
- # path to write a pid file after daemonize
193
- # * :Host
194
- # the host address to bind to (used by supporting Rack::Handler)
195
- # * :Port
196
- # the port to bind to (used by supporting Rack::Handler)
197
- # * :AccessLog
198
- # webrick access log options (or supporting Rack::Handler)
199
- # * :debug
200
- # turn on debug output ($DEBUG = true)
201
- # * :warn
202
- # turn on warnings ($-w = true)
203
- # * :include
204
- # add given paths to $LOAD_PATH
205
- # * :require
206
- # require the given libraries
207
- #
208
- # Additional options for profiling app initialization include:
209
- # * :heapfile
210
- # location for ObjectSpace.dump_all to write the output to
211
- # * :profile_file
212
- # location for CPU/Memory (StackProf) profile output (defaults to a tempfile)
213
- # * :profile_mode
214
- # StackProf profile mode (cpu|wall|object)
215
- def initialize(options = nil)
216
- @ignore_options = []
217
-
218
- if options
219
- @use_default_options = false
220
- @options = options
221
- @app = options[:app] if options[:app]
222
- else
223
- argv = defined?(SPEC_ARGV) ? SPEC_ARGV : ARGV
224
- @use_default_options = true
225
- @options = parse_options(argv)
226
- end
227
- end
228
-
229
- def options
230
- merged_options = @use_default_options ? default_options.merge(@options) : @options
231
- merged_options.reject { |k, v| @ignore_options.include?(k) }
232
- end
233
-
234
- def default_options
235
- environment = ENV['RACK_ENV'] || 'development'
236
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
237
-
238
- {
239
- environment: environment,
240
- pid: nil,
241
- Port: 9292,
242
- Host: default_host,
243
- AccessLog: [],
244
- config: "config.ru"
245
- }
246
- end
247
-
248
- def app
249
- @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
250
- end
251
-
252
- class << self
253
- def logging_middleware
254
- lambda { |server|
255
- /CGI/.match?(server.server.name) || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
256
- }
257
- end
258
-
259
- def default_middleware_by_environment
260
- m = Hash.new {|h, k| h[k] = []}
261
- m["deployment"] = [
262
- [Rack::ContentLength],
263
- logging_middleware,
264
- [Rack::TempfileReaper]
265
- ]
266
- m["development"] = [
267
- [Rack::ContentLength],
268
- logging_middleware,
269
- [Rack::ShowExceptions],
270
- [Rack::Lint],
271
- [Rack::TempfileReaper]
272
- ]
273
-
274
- m
275
- end
276
-
277
- def middleware
278
- default_middleware_by_environment
279
- end
280
- end
281
-
282
- def middleware
283
- self.class.middleware
284
- end
285
-
286
- def start(&block)
287
- if options[:warn]
288
- $-w = true
289
- end
290
-
291
- if includes = options[:include]
292
- $LOAD_PATH.unshift(*includes)
293
- end
294
-
295
- Array(options[:require]).each do |library|
296
- require library
297
- end
298
-
299
- if options[:debug]
300
- $DEBUG = true
301
- require 'pp'
302
- p options[:server]
303
- pp wrapped_app
304
- pp app
305
- end
306
-
307
- check_pid! if options[:pid]
308
-
309
- # Touch the wrapped app, so that the config.ru is loaded before
310
- # daemonization (i.e. before chdir, etc).
311
- handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do
312
- wrapped_app
313
- end
314
-
315
- daemonize_app if options[:daemonize]
316
-
317
- write_pid if options[:pid]
318
-
319
- trap(:INT) do
320
- if server.respond_to?(:shutdown)
321
- server.shutdown
322
- else
323
- exit
324
- end
325
- end
326
-
327
- server.run(wrapped_app, **options, &block)
328
- end
329
-
330
- def server
331
- @_server ||= Rack::Handler.get(options[:server])
332
-
333
- unless @_server
334
- @_server = Rack::Handler.default
335
-
336
- # We already speak FastCGI
337
- @ignore_options = [:File, :Port] if @_server.to_s == 'Rack::Handler::FastCGI'
338
- end
339
-
340
- @_server
341
- end
342
-
343
- private
344
- def build_app_and_options_from_config
345
- if !::File.exist? options[:config]
346
- abort "configuration #{options[:config]} not found"
347
- end
348
-
349
- app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
350
- @options.merge!(options) { |key, old, new| old }
351
- app
352
- end
353
-
354
- def handle_profiling(heapfile, profile_mode, filename)
355
- if heapfile
356
- require "objspace"
357
- ObjectSpace.trace_object_allocations_start
358
- yield
359
- GC.start
360
- ::File.open(heapfile, "w") { |f| ObjectSpace.dump_all(output: f) }
361
- exit
362
- end
363
-
364
- if profile_mode
365
- require "stackprof"
366
- require "tempfile"
367
-
368
- make_profile_name(filename) do |filename|
369
- ::File.open(filename, "w") do |f|
370
- StackProf.run(mode: profile_mode, out: f) do
371
- yield
372
- end
373
- puts "Profile written to: #{filename}"
374
- end
375
- end
376
- exit
377
- end
378
-
379
- yield
380
- end
381
-
382
- def make_profile_name(filename)
383
- if filename
384
- yield filename
385
- else
386
- ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _|
387
- yield tmpname
388
- end
389
- end
390
- end
391
-
392
- def build_app_from_string
393
- Rack::Builder.new_from_string(self.options[:builder])
394
- end
395
-
396
- def parse_options(args)
397
- # Don't evaluate CGI ISINDEX parameters.
398
- # http://www.meb.uni-bonn.de/docs/cgi/cl.html
399
- args.clear if ENV.include?(REQUEST_METHOD)
400
-
401
- @options = opt_parser.parse!(args)
402
- @options[:config] = ::File.expand_path(options[:config])
403
- ENV["RACK_ENV"] = options[:environment]
404
- @options
405
- end
406
-
407
- def opt_parser
408
- Options.new
409
- end
410
-
411
- def build_app(app)
412
- middleware[options[:environment]].reverse_each do |middleware|
413
- middleware = middleware.call(self) if middleware.respond_to?(:call)
414
- next unless middleware
415
- klass, *args = middleware
416
- app = klass.new(app, *args)
417
- end
418
- app
419
- end
420
-
421
- def wrapped_app
422
- @wrapped_app ||= build_app app
423
- end
424
-
425
- def daemonize_app
426
- # Cannot be covered as it forks
427
- # :nocov:
428
- Process.daemon
429
- # :nocov:
430
- end
431
-
432
- def write_pid
433
- ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") }
434
- at_exit { ::FileUtils.rm_f(options[:pid]) }
435
- rescue Errno::EEXIST
436
- check_pid!
437
- retry
438
- end
439
-
440
- def check_pid!
441
- case pidfile_process_status
442
- when :running, :not_owned
443
- $stderr.puts "A server is already running. Check #{options[:pid]}."
444
- exit(1)
445
- when :dead
446
- ::File.delete(options[:pid])
447
- end
448
- end
449
-
450
- def pidfile_process_status
451
- return :exited unless ::File.exist?(options[:pid])
452
-
453
- pid = ::File.read(options[:pid]).to_i
454
- return :dead if pid == 0
455
-
456
- Process.kill(0, pid)
457
- :running
458
- rescue Errno::ESRCH
459
- :dead
460
- rescue Errno::EPERM
461
- :not_owned
462
- end
463
-
464
- end
465
-
466
- end