piesync-puma 3.12.6

Sign up to get free protection for your applications and to get access to all the features.
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