piesync-puma 3.12.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1429 -0
  3. data/LICENSE +26 -0
  4. data/README.md +280 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +31 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +36 -0
  9. data/docs/deployment.md +91 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/nginx.md +80 -0
  14. data/docs/plugins.md +28 -0
  15. data/docs/restart.md +39 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +272 -0
  18. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  19. data/ext/puma_http11/ext_help.h +15 -0
  20. data/ext/puma_http11/extconf.rb +15 -0
  21. data/ext/puma_http11/http11_parser.c +1071 -0
  22. data/ext/puma_http11/http11_parser.h +65 -0
  23. data/ext/puma_http11/http11_parser.java.rl +161 -0
  24. data/ext/puma_http11/http11_parser.rl +149 -0
  25. data/ext/puma_http11/http11_parser_common.rl +54 -0
  26. data/ext/puma_http11/io_buffer.c +155 -0
  27. data/ext/puma_http11/mini_ssl.c +494 -0
  28. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +470 -0
  30. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +352 -0
  31. data/ext/puma_http11/puma_http11.c +500 -0
  32. data/lib/puma.rb +23 -0
  33. data/lib/puma/accept_nonblock.rb +23 -0
  34. data/lib/puma/app/status.rb +74 -0
  35. data/lib/puma/binder.rb +413 -0
  36. data/lib/puma/cli.rb +235 -0
  37. data/lib/puma/client.rb +480 -0
  38. data/lib/puma/cluster.rb +531 -0
  39. data/lib/puma/commonlogger.rb +108 -0
  40. data/lib/puma/compat.rb +14 -0
  41. data/lib/puma/configuration.rb +361 -0
  42. data/lib/puma/const.rb +239 -0
  43. data/lib/puma/control_cli.rb +264 -0
  44. data/lib/puma/convenient.rb +25 -0
  45. data/lib/puma/daemon_ext.rb +33 -0
  46. data/lib/puma/delegation.rb +13 -0
  47. data/lib/puma/detect.rb +15 -0
  48. data/lib/puma/dsl.rb +518 -0
  49. data/lib/puma/events.rb +153 -0
  50. data/lib/puma/io_buffer.rb +9 -0
  51. data/lib/puma/java_io_buffer.rb +47 -0
  52. data/lib/puma/jruby_restart.rb +84 -0
  53. data/lib/puma/launcher.rb +433 -0
  54. data/lib/puma/minissl.rb +285 -0
  55. data/lib/puma/null_io.rb +44 -0
  56. data/lib/puma/plugin.rb +117 -0
  57. data/lib/puma/plugin/tmp_restart.rb +34 -0
  58. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  59. data/lib/puma/rack/builder.rb +299 -0
  60. data/lib/puma/rack/urlmap.rb +91 -0
  61. data/lib/puma/rack_default.rb +7 -0
  62. data/lib/puma/reactor.rb +347 -0
  63. data/lib/puma/runner.rb +184 -0
  64. data/lib/puma/server.rb +1072 -0
  65. data/lib/puma/single.rb +123 -0
  66. data/lib/puma/state_file.rb +31 -0
  67. data/lib/puma/tcp_logger.rb +41 -0
  68. data/lib/puma/thread_pool.rb +346 -0
  69. data/lib/puma/util.rb +129 -0
  70. data/lib/rack/handler/puma.rb +115 -0
  71. data/tools/jungle/README.md +19 -0
  72. data/tools/jungle/init.d/README.md +61 -0
  73. data/tools/jungle/init.d/puma +421 -0
  74. data/tools/jungle/init.d/run-puma +18 -0
  75. data/tools/jungle/rc.d/README.md +74 -0
  76. data/tools/jungle/rc.d/puma +61 -0
  77. data/tools/jungle/rc.d/puma.conf +10 -0
  78. data/tools/jungle/upstart/README.md +61 -0
  79. data/tools/jungle/upstart/puma-manager.conf +31 -0
  80. data/tools/jungle/upstart/puma.conf +69 -0
  81. data/tools/trickletest.rb +45 -0
  82. metadata +131 -0
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/launcher'
4
+ require 'puma/configuration'
5
+
6
+ module Puma
7
+ def self.run(opts={})
8
+ cfg = Puma::Configuration.new do |user_config|
9
+ if port = opts[:port]
10
+ user_config.port port
11
+ end
12
+
13
+ user_config.quiet
14
+
15
+ yield c
16
+ end
17
+
18
+ cfg.clamp
19
+
20
+ events = Puma::Events.null
21
+
22
+ launcher = Puma::Launcher.new cfg, :events => events
23
+ launcher.run
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Process
4
+
5
+ # This overrides the default version because it is broken if it
6
+ # exists.
7
+
8
+ if respond_to? :daemon
9
+ class << self
10
+ remove_method :daemon
11
+ end
12
+ end
13
+
14
+ def self.daemon(nochdir=false, noclose=false)
15
+ exit if fork # Parent exits, child continues.
16
+
17
+ Process.setsid # Become session leader.
18
+
19
+ exit if fork # Zap session leader. See [1].
20
+
21
+ Dir.chdir "/" unless nochdir # Release old working directory.
22
+
23
+ if !noclose
24
+ STDIN.reopen File.open("/dev/null", "r")
25
+
26
+ null_out = File.open "/dev/null", "w"
27
+ STDOUT.reopen null_out
28
+ STDERR.reopen null_out
29
+ end
30
+
31
+ 0
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Puma
4
+ module Delegation
5
+ def forward(what, who)
6
+ module_eval <<-CODE
7
+ def #{what}(*args, &block)
8
+ #{who}.#{what}(*args, &block)
9
+ end
10
+ CODE
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Puma
4
+ IS_JRUBY = defined?(JRUBY_VERSION)
5
+
6
+ def self.jruby?
7
+ IS_JRUBY
8
+ end
9
+
10
+ IS_WINDOWS = RUBY_PLATFORM =~ /mswin|ming|cygwin/
11
+
12
+ def self.windows?
13
+ IS_WINDOWS
14
+ end
15
+ end
@@ -0,0 +1,518 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Puma
4
+ # The methods that are available for use inside the config file.
5
+ # These same methods are used in Puma cli and the rack handler
6
+ # internally.
7
+ #
8
+ # Used manually (via CLI class):
9
+ #
10
+ # config = Configuration.new({}) do |user_config|
11
+ # user_config.port 3001
12
+ # end
13
+ # config.load
14
+ #
15
+ # puts config.options[:binds]
16
+ # "tcp://127.0.0.1:3001"
17
+ #
18
+ # Used to load file:
19
+ #
20
+ # $ cat puma_config.rb
21
+ # port 3002
22
+ #
23
+ # config = Configuration.new(config_file: "puma_config.rb")
24
+ # config.load
25
+ #
26
+ # puts config.options[:binds]
27
+ # # => "tcp://127.0.0.1:3002"
28
+ #
29
+ # Detailed docs can be found in `examples/config.rb`
30
+ class DSL
31
+ include ConfigDefault
32
+
33
+ def initialize(options, config)
34
+ @config = config
35
+ @options = options
36
+
37
+ @plugins = []
38
+ end
39
+
40
+ def _load_from(path)
41
+ if path
42
+ @path = path
43
+ instance_eval(File.read(path), path, 1)
44
+ end
45
+ ensure
46
+ _offer_plugins
47
+ end
48
+
49
+ def _offer_plugins
50
+ @plugins.each do |o|
51
+ if o.respond_to? :config
52
+ @options.shift
53
+ o.config self
54
+ end
55
+ end
56
+
57
+ @plugins.clear
58
+ end
59
+
60
+ def set_default_host(host)
61
+ @options[:default_host] = host
62
+ end
63
+
64
+ def default_host
65
+ @options[:default_host] || Configuration::DefaultTCPHost
66
+ end
67
+
68
+ def inject(&blk)
69
+ instance_eval(&blk)
70
+ end
71
+
72
+ def get(key,default=nil)
73
+ @options[key.to_sym] || default
74
+ end
75
+
76
+ # Load the named plugin for use by this configuration
77
+ #
78
+ def plugin(name)
79
+ @plugins << @config.load_plugin(name)
80
+ end
81
+
82
+ # Use +obj+ or +block+ as the Rack app. This allows a config file to
83
+ # be the app itself.
84
+ #
85
+ def app(obj=nil, &block)
86
+ obj ||= block
87
+
88
+ raise "Provide either a #call'able or a block" unless obj
89
+
90
+ @options[:app] = obj
91
+ end
92
+
93
+ # Start the Puma control rack app on +url+. This app can be communicated
94
+ # with to control the main server.
95
+ #
96
+ def activate_control_app(url="auto", opts={})
97
+ if url == "auto"
98
+ path = Configuration.temp_path
99
+ @options[:control_url] = "unix://#{path}"
100
+ @options[:control_url_temp] = path
101
+ else
102
+ @options[:control_url] = url
103
+ end
104
+
105
+ if opts[:no_token]
106
+ auth_token = :none
107
+ else
108
+ auth_token = opts[:auth_token]
109
+ auth_token ||= Configuration.random_token
110
+ end
111
+
112
+ @options[:control_auth_token] = auth_token
113
+ @options[:control_url_umask] = opts[:umask] if opts[:umask]
114
+ end
115
+
116
+ # Load additional configuration from a file
117
+ # Files get loaded later via Configuration#load
118
+ def load(file)
119
+ @options[:config_files] ||= []
120
+ @options[:config_files] << file
121
+ end
122
+
123
+ # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
124
+ # protocols. Use query parameters within the url to specify options.
125
+ #
126
+ # @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
127
+ #
128
+ # @example Explicitly the socket backlog depth (default is 1024)
129
+ # bind('unix:///var/run/puma.sock?backlog=2048')
130
+ #
131
+ # @example Set up ssl cert
132
+ # bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
133
+ #
134
+ # @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
135
+ # bind('tcp://0.0.0.0:9292?low_latency=true')
136
+ #
137
+ # @example Set socket permissions
138
+ # bind('unix:///var/run/puma.sock?umask=0111')
139
+ def bind(url)
140
+ @options[:binds] ||= []
141
+ @options[:binds] << url
142
+ end
143
+
144
+ def clear_binds!
145
+ @options[:binds] = []
146
+ end
147
+
148
+ # Define the TCP port to bind to. Use +bind+ for more advanced options.
149
+ #
150
+ def port(port, host=nil)
151
+ host ||= default_host
152
+ bind "tcp://#{host}:#{port}"
153
+ end
154
+
155
+ # Define how long persistent connections can be idle before puma closes
156
+ # them
157
+ #
158
+ def persistent_timeout(seconds)
159
+ @options[:persistent_timeout] = Integer(seconds)
160
+ end
161
+
162
+ # Define how long the tcp socket stays open, if no data has been received
163
+ #
164
+ def first_data_timeout(seconds)
165
+ @options[:first_data_timeout] = Integer(seconds)
166
+ end
167
+
168
+ # Work around leaky apps that leave garbage in Thread locals
169
+ # across requests
170
+ #
171
+ def clean_thread_locals(which=true)
172
+ @options[:clean_thread_locals] = which
173
+ end
174
+
175
+ # Daemonize the server into the background. Highly suggest that
176
+ # this be combined with +pidfile+ and +stdout_redirect+.
177
+ def daemonize(which=true)
178
+ @options[:daemon] = which
179
+ end
180
+
181
+ # When shutting down, drain the accept socket of pending
182
+ # connections and process them. This loops over the accept
183
+ # socket until there are no more read events and then stops
184
+ # looking and waits for the requests to finish.
185
+ def drain_on_shutdown(which=true)
186
+ @options[:drain_on_shutdown] = which
187
+ end
188
+
189
+ # Set the environment in which the Rack's app will run.
190
+ def environment(environment)
191
+ @options[:environment] = environment
192
+ end
193
+
194
+ # How long to wait for threads to stop when shutting them
195
+ # down. Defaults to :forever. Specifying :immediately will cause
196
+ # Puma to kill the threads immediately. Otherwise the value
197
+ # is the number of seconds to wait.
198
+ #
199
+ # Puma always waits a few seconds after killing a thread for it to try
200
+ # to finish up it's work, even in :immediately mode.
201
+ def force_shutdown_after(val=:forever)
202
+ i = case val
203
+ when :forever
204
+ -1
205
+ when :immediately
206
+ 0
207
+ else
208
+ Integer(val)
209
+ end
210
+
211
+ @options[:force_shutdown_after] = i
212
+ end
213
+
214
+ # Code to run before doing a restart. This code should
215
+ # close logfiles, database connections, etc.
216
+ #
217
+ # This can be called multiple times to add code each time.
218
+ #
219
+ def on_restart(&block)
220
+ @options[:on_restart] ||= []
221
+ @options[:on_restart] << block
222
+ end
223
+
224
+ # Command to use to restart puma. This should be just how to
225
+ # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
226
+ # to puma, as those are the same as the original process.
227
+ #
228
+ def restart_command(cmd)
229
+ @options[:restart_cmd] = cmd.to_s
230
+ end
231
+
232
+ # Store the pid of the server in the file at +path+.
233
+ def pidfile(path)
234
+ @options[:pidfile] = path.to_s
235
+ end
236
+
237
+ # Disable request logging.
238
+ #
239
+ def quiet(which=true)
240
+ @options[:log_requests] = !which
241
+ end
242
+
243
+ # Enable request logging
244
+ #
245
+ def log_requests(which=true)
246
+ @options[:log_requests] = which
247
+ end
248
+
249
+ # Show debugging info
250
+ #
251
+ def debug
252
+ @options[:debug] = true
253
+ end
254
+
255
+ # Load +path+ as a rackup file.
256
+ #
257
+ def rackup(path)
258
+ @options[:rackup] = path.to_s
259
+ end
260
+
261
+ # Run Puma in TCP mode
262
+ #
263
+ def tcp_mode!
264
+ @options[:mode] = :tcp
265
+ end
266
+
267
+ def early_hints(answer=true)
268
+ @options[:early_hints] = answer
269
+ end
270
+
271
+ # Redirect STDOUT and STDERR to files specified.
272
+ def stdout_redirect(stdout=nil, stderr=nil, append=false)
273
+ @options[:redirect_stdout] = stdout
274
+ @options[:redirect_stderr] = stderr
275
+ @options[:redirect_append] = append
276
+ end
277
+
278
+ # Configure +min+ to be the minimum number of threads to use to answer
279
+ # requests and +max+ the maximum.
280
+ #
281
+ def threads(min, max)
282
+ min = Integer(min)
283
+ max = Integer(max)
284
+ if min > max
285
+ raise "The minimum (#{min}) number of threads must be less than or equal to the max (#{max})"
286
+ end
287
+
288
+ if max < 1
289
+ raise "The maximum number of threads (#{max}) must be greater than 0"
290
+ end
291
+
292
+ @options[:min_threads] = min
293
+ @options[:max_threads] = max
294
+ end
295
+
296
+ def ssl_bind(host, port, opts)
297
+ verify = opts.fetch(:verify_mode, 'none')
298
+ additions = +''
299
+
300
+ if defined?(JRUBY_VERSION)
301
+ additions << "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
302
+ else
303
+ Array(opts[:verification_flags]).each { |flag| additions << "&verification_flags=#{flag}" }
304
+ end
305
+
306
+ bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}#{additions}"
307
+ end
308
+
309
+ # Use +path+ as the file to store the server info state. This is
310
+ # used by pumactl to query and control the server.
311
+ #
312
+ def state_path(path)
313
+ @options[:state] = path.to_s
314
+ end
315
+
316
+ # *Cluster mode only* How many worker processes to run.
317
+ #
318
+ def workers(count)
319
+ @options[:workers] = count.to_i
320
+ end
321
+
322
+ # *Cluster mode only* Code to run immediately before master process
323
+ # forks workers (once on boot). These hooks can block if necessary
324
+ # to wait for background operations unknown to puma to finish before
325
+ # the process terminates.
326
+ # This can be used to close any connections to remote servers (database, redis, ...)
327
+ # that were opened when preloading the code
328
+ #
329
+ # This can be called multiple times to add hooks.
330
+ #
331
+ def before_fork(&block)
332
+ @options[:before_fork] ||= []
333
+ @options[:before_fork] << block
334
+ end
335
+
336
+ # *Cluster mode only* Code to run in a worker when it boots to setup
337
+ # the process before booting the app.
338
+ #
339
+ # This can be called multiple times to add hooks.
340
+ #
341
+ def on_worker_boot(&block)
342
+ @options[:before_worker_boot] ||= []
343
+ @options[:before_worker_boot] << block
344
+ end
345
+
346
+ # *Cluster mode only* Code to run immediately before a worker shuts
347
+ # down (after it has finished processing HTTP requests). These hooks
348
+ # can block if necessary to wait for background operations unknown
349
+ # to puma to finish before the process terminates.
350
+ #
351
+ # This can be called multiple times to add hooks.
352
+ #
353
+ def on_worker_shutdown(&block)
354
+ @options[:before_worker_shutdown] ||= []
355
+ @options[:before_worker_shutdown] << block
356
+ end
357
+
358
+ # *Cluster mode only* Code to run in the master when it is
359
+ # about to create the worker by forking itself.
360
+ #
361
+ # This can be called multiple times to add hooks.
362
+ #
363
+ def on_worker_fork(&block)
364
+ @options[:before_worker_fork] ||= []
365
+ @options[:before_worker_fork] << block
366
+ end
367
+
368
+ # *Cluster mode only* Code to run in the master after it starts
369
+ # a worker.
370
+ #
371
+ # This can be called multiple times to add hooks.
372
+ #
373
+ def after_worker_fork(&block)
374
+ @options[:after_worker_fork] ||= []
375
+ @options[:after_worker_fork] = block
376
+ end
377
+
378
+ alias_method :after_worker_boot, :after_worker_fork
379
+
380
+ # The directory to operate out of.
381
+ def directory(dir)
382
+ @options[:directory] = dir.to_s
383
+ end
384
+
385
+ # DEPRECATED: The directory to operate out of.
386
+ def worker_directory(dir)
387
+ $stderr.puts "worker_directory is deprecated. Please use `directory`"
388
+ directory dir
389
+ end
390
+
391
+ # Run the app as a raw TCP app instead of an HTTP rack app
392
+ def tcp_mode
393
+ @options[:mode] = :tcp
394
+ end
395
+
396
+ # *Cluster mode only* Preload the application before starting
397
+ # the workers and setting up the listen ports. This conflicts
398
+ # with using the phased restart feature, you can't use both.
399
+ #
400
+ def preload_app!(answer=true)
401
+ @options[:preload_app] = answer
402
+ end
403
+
404
+ # Use +obj+ or +block+ as the low level error handler. This allows a config file to
405
+ # change the default error on the server.
406
+ #
407
+ def lowlevel_error_handler(obj=nil, &block)
408
+ obj ||= block
409
+ raise "Provide either a #call'able or a block" unless obj
410
+ @options[:lowlevel_error_handler] = obj
411
+ end
412
+
413
+ # This option is used to allow your app and its gems to be
414
+ # properly reloaded when not using preload.
415
+ #
416
+ # When set, if puma detects that it's been invoked in the
417
+ # context of Bundler, it will cleanup the environment and
418
+ # re-run itself outside the Bundler environment, but directly
419
+ # using the files that Bundler has setup.
420
+ #
421
+ # This means that puma is now decoupled from your Bundler
422
+ # context and when each worker loads, it will be loading a
423
+ # new Bundler context and thus can float around as the release
424
+ # dictates.
425
+ def prune_bundler(answer=true)
426
+ @options[:prune_bundler] = answer
427
+ end
428
+
429
+ # Additional text to display in process listing
430
+ def tag(string)
431
+ @options[:tag] = string.to_s
432
+ end
433
+
434
+ # *Cluster mode only* Set the timeout for workers in seconds
435
+ # When set the master process will terminate any workers
436
+ # that have not checked in within the given +timeout+.
437
+ # This mitigates hung processes. Default value is 60 seconds.
438
+ def worker_timeout(timeout)
439
+ @options[:worker_timeout] = Integer(timeout)
440
+ end
441
+
442
+ # *Cluster mode only* Set the timeout for workers to boot
443
+ def worker_boot_timeout(timeout)
444
+ @options[:worker_boot_timeout] = Integer(timeout)
445
+ end
446
+
447
+ # *Cluster mode only* Set the timeout for worker shutdown
448
+ def worker_shutdown_timeout(timeout)
449
+ @options[:worker_shutdown_timeout] = Integer(timeout)
450
+ end
451
+
452
+ # When set to true (the default), workers accept all requests
453
+ # and queue them before passing them to the handlers.
454
+ # When set to false, each worker process accepts exactly as
455
+ # many requests as it is configured to simultaneously handle.
456
+ #
457
+ # Queueing requests generally improves performance. In some
458
+ # cases, such as a single threaded application, it may be
459
+ # better to ensure requests get balanced across workers.
460
+ #
461
+ # Note that setting this to false disables HTTP keepalive and
462
+ # slow clients will occupy a handler thread while the request
463
+ # is being sent. A reverse proxy, such as nginx, can handle
464
+ # slow clients and queue requests before they reach puma.
465
+ def queue_requests(answer=true)
466
+ @options[:queue_requests] = answer
467
+ end
468
+
469
+ # When a shutdown is requested, the backtraces of all the
470
+ # threads will be written to $stdout. This can help figure
471
+ # out why shutdown is hanging.
472
+ def shutdown_debug(val=true)
473
+ @options[:shutdown_debug] = val
474
+ end
475
+
476
+ # Control how the remote address of the connection is set. This
477
+ # is configurable because to calculate the true socket peer address
478
+ # a kernel syscall is required which for very fast rack handlers
479
+ # slows down the handling significantly.
480
+ #
481
+ # There are 4 possible values:
482
+ #
483
+ # * :socket (the default) - read the peername from the socket using the
484
+ # syscall. This is the normal behavior.
485
+ # * :localhost - set the remote address to "127.0.0.1"
486
+ # * header: http_header - set the remote address to the value of the
487
+ # provided http header. For instance:
488
+ # `set_remote_address header: "X-Real-IP"`.
489
+ # Only the first word (as separated by spaces or comma)
490
+ # is used, allowing headers such as X-Forwarded-For
491
+ # to be used as well.
492
+ # * Any string - this allows you to hardcode remote address to any value
493
+ # you wish. Because puma never uses this field anyway, it's
494
+ # format is entirely in your hands.
495
+ def set_remote_address(val=:socket)
496
+ case val
497
+ when :socket
498
+ @options[:remote_address] = val
499
+ when :localhost
500
+ @options[:remote_address] = :value
501
+ @options[:remote_address_value] = "127.0.0.1".freeze
502
+ when String
503
+ @options[:remote_address] = :value
504
+ @options[:remote_address_value] = val
505
+ when Hash
506
+ if hdr = val[:header]
507
+ @options[:remote_address] = :header
508
+ @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
509
+ else
510
+ raise "Invalid value for set_remote_address - #{val.inspect}"
511
+ end
512
+ else
513
+ raise "Invalid value for set_remote_address - #{val}"
514
+ end
515
+ end
516
+
517
+ end
518
+ end