rack 2.2.8.1 → 3.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +301 -81
  3. data/CONTRIBUTING.md +63 -55
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +328 -0
  6. data/SPEC.rdoc +204 -131
  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 +1 -4
  10. data/lib/rack/bad_request.rb +8 -0
  11. data/lib/rack/body_proxy.rb +21 -3
  12. data/lib/rack/builder.rb +102 -69
  13. data/lib/rack/cascade.rb +2 -3
  14. data/lib/rack/common_logger.rb +23 -18
  15. data/lib/rack/conditional_get.rb +18 -15
  16. data/lib/rack/constants.rb +67 -0
  17. data/lib/rack/content_length.rb +12 -16
  18. data/lib/rack/content_type.rb +8 -5
  19. data/lib/rack/deflater.rb +40 -26
  20. data/lib/rack/directory.rb +9 -3
  21. data/lib/rack/etag.rb +14 -23
  22. data/lib/rack/events.rb +4 -0
  23. data/lib/rack/files.rb +15 -17
  24. data/lib/rack/head.rb +9 -8
  25. data/lib/rack/headers.rb +238 -0
  26. data/lib/rack/lint.rb +838 -644
  27. data/lib/rack/lock.rb +2 -5
  28. data/lib/rack/logger.rb +3 -0
  29. data/lib/rack/method_override.rb +5 -1
  30. data/lib/rack/mime.rb +14 -5
  31. data/lib/rack/mock.rb +1 -271
  32. data/lib/rack/mock_request.rb +171 -0
  33. data/lib/rack/mock_response.rb +124 -0
  34. data/lib/rack/multipart/generator.rb +7 -5
  35. data/lib/rack/multipart/parser.rb +215 -90
  36. data/lib/rack/multipart/uploaded_file.rb +4 -0
  37. data/lib/rack/multipart.rb +53 -40
  38. data/lib/rack/null_logger.rb +9 -0
  39. data/lib/rack/query_parser.rb +81 -102
  40. data/lib/rack/recursive.rb +2 -0
  41. data/lib/rack/reloader.rb +0 -2
  42. data/lib/rack/request.rb +250 -123
  43. data/lib/rack/response.rb +146 -66
  44. data/lib/rack/rewindable_input.rb +24 -5
  45. data/lib/rack/runtime.rb +7 -6
  46. data/lib/rack/sendfile.rb +30 -25
  47. data/lib/rack/show_exceptions.rb +21 -4
  48. data/lib/rack/show_status.rb +17 -7
  49. data/lib/rack/static.rb +8 -8
  50. data/lib/rack/tempfile_reaper.rb +15 -4
  51. data/lib/rack/urlmap.rb +3 -1
  52. data/lib/rack/utils.rb +232 -233
  53. data/lib/rack/version.rb +1 -9
  54. data/lib/rack.rb +13 -89
  55. metadata +15 -41
  56. data/README.rdoc +0 -320
  57. data/Rakefile +0 -130
  58. data/bin/rackup +0 -5
  59. data/contrib/rack.png +0 -0
  60. data/contrib/rack.svg +0 -150
  61. data/contrib/rack_logo.svg +0 -164
  62. data/contrib/rdoc.css +0 -412
  63. data/example/lobster.ru +0 -6
  64. data/example/protectedlobster.rb +0 -16
  65. data/example/protectedlobster.ru +0 -10
  66. data/lib/rack/auth/digest/md5.rb +0 -131
  67. data/lib/rack/auth/digest/nonce.rb +0 -54
  68. data/lib/rack/auth/digest/params.rb +0 -54
  69. data/lib/rack/auth/digest/request.rb +0 -43
  70. data/lib/rack/chunked.rb +0 -117
  71. data/lib/rack/core_ext/regexp.rb +0 -14
  72. data/lib/rack/file.rb +0 -7
  73. data/lib/rack/handler/cgi.rb +0 -59
  74. data/lib/rack/handler/fastcgi.rb +0 -100
  75. data/lib/rack/handler/lsws.rb +0 -61
  76. data/lib/rack/handler/scgi.rb +0 -71
  77. data/lib/rack/handler/thin.rb +0 -36
  78. data/lib/rack/handler/webrick.rb +0 -129
  79. data/lib/rack/handler.rb +0 -104
  80. data/lib/rack/lobster.rb +0 -70
  81. data/lib/rack/server.rb +0 -466
  82. data/lib/rack/session/abstract/id.rb +0 -523
  83. data/lib/rack/session/cookie.rb +0 -204
  84. data/lib/rack/session/memcache.rb +0 -10
  85. data/lib/rack/session/pool.rb +0 -85
  86. data/rack.gemspec +0 -46
data/lib/rack/handler.rb DELETED
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rack
4
- # *Handlers* connect web servers with Rack.
5
- #
6
- # Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI
7
- # and LiteSpeed.
8
- #
9
- # Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
10
- # A second optional hash can be passed to include server-specific
11
- # configuration.
12
- module Handler
13
- def self.get(server)
14
- return unless server
15
- server = server.to_s
16
-
17
- unless @handlers.include? server
18
- load_error = try_require('rack/handler', server)
19
- end
20
-
21
- if klass = @handlers[server]
22
- const_get(klass)
23
- else
24
- const_get(server, false)
25
- end
26
-
27
- rescue NameError => name_error
28
- raise load_error || name_error
29
- end
30
-
31
- # Select first available Rack handler given an `Array` of server names.
32
- # Raises `LoadError` if no handler was found.
33
- #
34
- # > pick ['thin', 'webrick']
35
- # => Rack::Handler::WEBrick
36
- def self.pick(server_names)
37
- server_names = Array(server_names)
38
- server_names.each do |server_name|
39
- begin
40
- return get(server_name.to_s)
41
- rescue LoadError, NameError
42
- end
43
- end
44
-
45
- raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
46
- end
47
-
48
- SERVER_NAMES = %w(puma thin falcon webrick).freeze
49
- private_constant :SERVER_NAMES
50
-
51
- def self.default
52
- # Guess.
53
- if ENV.include?("PHP_FCGI_CHILDREN")
54
- Rack::Handler::FastCGI
55
- elsif ENV.include?(REQUEST_METHOD)
56
- Rack::Handler::CGI
57
- elsif ENV.include?("RACK_HANDLER")
58
- self.get(ENV["RACK_HANDLER"])
59
- else
60
- pick SERVER_NAMES
61
- end
62
- end
63
-
64
- # Transforms server-name constants to their canonical form as filenames,
65
- # then tries to require them but silences the LoadError if not found
66
- #
67
- # Naming convention:
68
- #
69
- # Foo # => 'foo'
70
- # FooBar # => 'foo_bar.rb'
71
- # FooBAR # => 'foobar.rb'
72
- # FOObar # => 'foobar.rb'
73
- # FOOBAR # => 'foobar.rb'
74
- # FooBarBaz # => 'foo_bar_baz.rb'
75
- def self.try_require(prefix, const_name)
76
- file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
77
- gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
78
-
79
- require(::File.join(prefix, file))
80
- nil
81
- rescue LoadError => error
82
- error
83
- end
84
-
85
- def self.register(server, klass)
86
- @handlers ||= {}
87
- @handlers[server.to_s] = klass.to_s
88
- end
89
-
90
- autoload :CGI, "rack/handler/cgi"
91
- autoload :FastCGI, "rack/handler/fastcgi"
92
- autoload :WEBrick, "rack/handler/webrick"
93
- autoload :LSWS, "rack/handler/lsws"
94
- autoload :SCGI, "rack/handler/scgi"
95
- autoload :Thin, "rack/handler/thin"
96
-
97
- register 'cgi', 'Rack::Handler::CGI'
98
- register 'fastcgi', 'Rack::Handler::FastCGI'
99
- register 'webrick', 'Rack::Handler::WEBrick'
100
- register 'lsws', 'Rack::Handler::LSWS'
101
- register 'scgi', 'Rack::Handler::SCGI'
102
- register 'thin', 'Rack::Handler::Thin'
103
- end
104
- end
data/lib/rack/lobster.rb DELETED
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'zlib'
4
-
5
- module Rack
6
- # Paste has a Pony, Rack has a Lobster!
7
- class Lobster
8
- LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2
9
- P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0
10
- t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ
11
- I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0])
12
-
13
- LambdaLobster = lambda { |env|
14
- if env[QUERY_STRING].include?("flip")
15
- lobster = LobsterString.split("\n").
16
- map { |line| line.ljust(42).reverse }.
17
- join("\n")
18
- href = "?"
19
- else
20
- lobster = LobsterString
21
- href = "?flip"
22
- end
23
-
24
- content = ["<title>Lobstericious!</title>",
25
- "<pre>", lobster, "</pre>",
26
- "<a href='#{href}'>flip!</a>"]
27
- length = content.inject(0) { |a, e| a + e.size }.to_s
28
- [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
29
- }
30
-
31
- def call(env)
32
- req = Request.new(env)
33
- if req.GET["flip"] == "left"
34
- lobster = LobsterString.split("\n").map do |line|
35
- line.ljust(42).reverse.
36
- gsub('\\', 'TEMP').
37
- gsub('/', '\\').
38
- gsub('TEMP', '/').
39
- gsub('{', '}').
40
- gsub('(', ')')
41
- end.join("\n")
42
- href = "?flip=right"
43
- elsif req.GET["flip"] == "crash"
44
- raise "Lobster crashed"
45
- else
46
- lobster = LobsterString
47
- href = "?flip=left"
48
- end
49
-
50
- res = Response.new
51
- res.write "<title>Lobstericious!</title>"
52
- res.write "<pre>"
53
- res.write lobster
54
- res.write "</pre>"
55
- res.write "<p><a href='#{href}'>flip!</a></p>"
56
- res.write "<p><a href='?flip=crash'>crash!</a></p>"
57
- res.finish
58
- end
59
-
60
- end
61
- end
62
-
63
- if $0 == __FILE__
64
- # :nocov:
65
- require_relative '../rack'
66
- Rack::Server.start(
67
- app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
68
- )
69
- # :nocov:
70
- end
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