From fa805939c647a189354335e293d3353daff388cd Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sat, 4 Oct 2025 21:41:25 +0300 Subject: [PATCH 1/6] rackup side allows Port but overwrites it into port, and webrick startup gets the value from :port --- lib/rackup/handler/webrick.rb | 2 +- lib/rackup/lobster.rb | 2 +- lib/rackup/server.rb | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/rackup/handler/webrick.rb b/lib/rackup/handler/webrick.rb index 7a7070f..280555f 100644 --- a/lib/rackup/handler/webrick.rb +++ b/lib/rackup/handler/webrick.rb @@ -23,7 +23,7 @@ def self.run(app, **options) if !options[:BindAddress] || options[:Host] options[:BindAddress] = options.delete(:Host) || default_host end - options[:Port] ||= 8080 + options[:Port] = options[:port] || 8080 if options[:SSLEnable] require 'webrick/https' end diff --git a/lib/rackup/lobster.rb b/lib/rackup/lobster.rb index 8502ba0..d136ba1 100644 --- a/lib/rackup/lobster.rb +++ b/lib/rackup/lobster.rb @@ -75,7 +75,7 @@ def call(env) require_relative 'show_exceptions' require_relative 'lint' Rackup::Server.start( - app: Rack::ShowExceptions.new(Rack::Lint.new(Rackup::Lobster.new)), Port: 9292 + app: Rack::ShowExceptions.new(Rack::Lint.new(Rackup::Lobster.new)), port: 9292 ) # :nocov: end diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index 3304b87..a23310a 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -70,7 +70,7 @@ def parse!(args) } opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port| - options[:Port] = port + options[:port] = port } 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| @@ -179,6 +179,7 @@ def handler_opts(options) # # Further options available here are documented on Rackup::Server#initialize def self.start(options = nil) + normalize_port_casing(options) new(options).start end @@ -252,7 +253,7 @@ def default_options { environment: environment, pid: nil, - Port: 9292, + port: 9292, Host: default_host, AccessLog: [], config: "config.ru" @@ -457,6 +458,10 @@ def exit_with_pid(pid) $stderr.puts "A server is already running (pid: #{pid}, file: #{options[:pid]})." exit(1) end + + def normalize_port_casing(options) + options[:port] = options[:port] || options[:Port].delete if options && options.is_a?(Hash) + end end end From 37283660c4078ffc2fc67700904b457c1e01e4d6 Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sat, 4 Oct 2025 23:19:26 +0300 Subject: [PATCH 2/6] proper has deletion --- lib/rackup/server.rb | 2 +- test/spec_server.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index a23310a..4536efb 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -460,7 +460,7 @@ def exit_with_pid(pid) end def normalize_port_casing(options) - options[:port] = options[:port] || options[:Port].delete if options && options.is_a?(Hash) + options[:port] = options[:port] || options.delete(:Port) if options && options.is_a?(Hash) end end diff --git a/test/spec_server.rb b/test/spec_server.rb index c5cebdb..ea1f618 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -52,9 +52,9 @@ def with_stderr server.app.must_equal "FOO" end - it "Options#parse parses -p and --port options into :Port" do - Rackup::Server::Options.new.parse!(%w[-p 1234]).must_equal :Port => '1234' - Rackup::Server::Options.new.parse!(%w[--port 1234]).must_equal :Port => '1234' + it "Options#parse parses -p and --port options into :port" do + Rackup::Server::Options.new.parse!(%w[-p 1234]).must_equal :port => '1234' + Rackup::Server::Options.new.parse!(%w[--port 1234]).must_equal :port => '1234' end it "Options#parse parses -D and --daemonize option into :daemonize" do From 852cc07478247a1928c47b465139ba6067c13483 Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sat, 4 Oct 2025 23:47:15 +0300 Subject: [PATCH 3/6] fix port tests --- lib/rackup/server.rb | 2 +- test/spec_server.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index 4536efb..7e30f2b 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -179,7 +179,6 @@ def handler_opts(options) # # Further options available here are documented on Rackup::Server#initialize def self.start(options = nil) - normalize_port_casing(options) new(options).start end @@ -232,6 +231,7 @@ def initialize(options = nil) @ignore_options = [] if options + normalize_port_casing(options) @use_default_options = false @options = options @app = options[:app] if options[:app] diff --git a/test/spec_server.rb b/test/spec_server.rb index ea1f618..659f966 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -52,7 +52,7 @@ def with_stderr server.app.must_equal "FOO" end - it "Options#parse parses -p and --port options into :port" do + it "Options#parse parses -p and --port options into :Port" do Rackup::Server::Options.new.parse!(%w[-p 1234]).must_equal :port => '1234' Rackup::Server::Options.new.parse!(%w[--port 1234]).must_equal :port => '1234' end @@ -482,9 +482,9 @@ def start(*) [self.class, :started] end t = Thread.new { server.start { |s| Thread.current[:server] = s } } t.join(0.01) until t[:server] && t[:server].status != :Stop body = if URI.respond_to?(:open) - URI.open("http://localhost:#{server.options[:Port]}/") { |f| f.read } + URI.open("http://localhost:#{server.options[:port]}/") { |f| f.read } else - open("http://localhost:#{server.options[:Port]}/") { |f| f.read } + open("http://localhost:#{server.options[:port]}/") { |f| f.read } end body.must_equal 'success' @@ -512,7 +512,7 @@ def start(*) [self.class, :started] end t = Thread.new { server.start { |s| Thread.current[:server] = s } } t.join(0.01) until t[:server] && t[:server].status != :Stop - uri = URI.parse("https://localhost:#{server.options[:Port]}/") + uri = URI.parse("https://localhost:#{server.options[:port]}/") Net::HTTP.start("localhost", uri.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| From 494059e29330c227918ab328feadd44f629448cd Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sat, 4 Oct 2025 23:56:37 +0300 Subject: [PATCH 4/6] delete Port anyway --- lib/rackup/server.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index 7e30f2b..28751c3 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -460,7 +460,10 @@ def exit_with_pid(pid) end def normalize_port_casing(options) - options[:port] = options[:port] || options.delete(:Port) if options && options.is_a?(Hash) + if options && options.is_a?(Hash) + capitalized_port_value = options.delete(:Port) + options[:port] = options[:port] || capitalized_port_value + end end end From eba717247c516e4f7a11c00ab17cde16d68784de Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sun, 5 Oct 2025 23:23:35 +0300 Subject: [PATCH 5/6] Added camelization + snakeifiation with priority between --- lib/rackup/server.rb | 48 +++++++++++++++++++++++++++++++++++--------- test/spec_server.rb | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index 28751c3..1f025ad 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -66,7 +66,7 @@ def parse!(args) } opts.on("-o", "--host HOST", "listen on HOST (default: localhost)") { |host| - options[:Host] = host + options[:host] = host } opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port| @@ -231,7 +231,6 @@ def initialize(options = nil) @ignore_options = [] if options - normalize_port_casing(options) @use_default_options = false @options = options @app = options[:app] if options[:app] @@ -239,6 +238,7 @@ def initialize(options = nil) @use_default_options = true @options = parse_options(ARGV) end + normalize_legacy_options end def options @@ -254,8 +254,8 @@ def default_options environment: environment, pid: nil, port: 9292, - Host: default_host, - AccessLog: [], + host: default_host, + access_log: [], config: "config.ru" } end @@ -459,12 +459,42 @@ def exit_with_pid(pid) exit(1) end - def normalize_port_casing(options) - if options && options.is_a?(Hash) - capitalized_port_value = options.delete(:Port) - options[:port] = options[:port] || capitalized_port_value + module LegacyOptionsNormalizer + def normalize_legacy_options + if @options && @options.is_a?(Hash) + @options.keys.each do |key| + snakeified_key = snakeify(key).to_sym + camelized_key = camelize(snakeified_key).to_sym + normalized_value = + if !@options[snakeified_key].nil? + @options[snakeified_key] + elsif !@options[camelized_key].nil? + @options[camelized_key] + else + @options[key] + end + @options[key] = @options[camelized_key] = @options[snakeified_key] = normalized_value + end + end + end + + def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) + if first_letter_in_uppercase + lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } + else + lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1] + end + end + + def snakeify(word) + word.to_s.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase end end - end + include LegacyOptionsNormalizer + end end diff --git a/test/spec_server.rb b/test/spec_server.rb index 659f966..c74c5e6 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -599,4 +599,41 @@ def start(*) [self.class, :started] end end end + it "normalize simple (non-camelized) words" do + options = {port: 8081} + server = Rackup::Server.new(options) + server.options[:port].must_equal 8081 + server.options[:Port].must_equal 8081 + end + + it "normalize simple (non-camelized) words with snake-case having priority" do + options = {port: 8081, Port: 8082} + server = Rackup::Server.new(options) + server.options[:port].must_equal 8081 + server.options[:Port].must_equal 8081 + end + + it "normalizes complex (camelized) words" do + options = {SSLEnable: true} + server = Rackup::Server.new(options) + server.options[:SSLEnable].must_equal true + server.options[:ssl_enable].must_equal true + server.options[:SslEnable].must_equal true + end + + it "normalizes complex (camelized) words with camel-case having priority over actual key" do + options = {SSLEnable: true, ssl_enable: false} + server = Rackup::Server.new(options) + server.options[:SSLEnable].must_equal false + server.options[:ssl_enable].must_equal false + server.options[:SslEnable].must_equal false + end + + it "normalizes complex (camelized) words with snake-case having priority over all" do + options = {SSLEnable: true, SslEnable: nil, ssl_enable: false} + server = Rackup::Server.new(options) + server.options[:SSLEnable].must_equal false + server.options[:ssl_enable].must_equal false + server.options[:SslEnable].must_equal false + end end From 6d6b3cc9f45a953fe407908dd8b15232cae23b62 Mon Sep 17 00:00:00 2001 From: sitalnora Date: Sun, 5 Oct 2025 23:29:21 +0300 Subject: [PATCH 6/6] ensure nil being settable --- lib/rackup/server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rackup/server.rb b/lib/rackup/server.rb index 1f025ad..5604e59 100644 --- a/lib/rackup/server.rb +++ b/lib/rackup/server.rb @@ -466,9 +466,9 @@ def normalize_legacy_options snakeified_key = snakeify(key).to_sym camelized_key = camelize(snakeified_key).to_sym normalized_value = - if !@options[snakeified_key].nil? + if @options.key?(snakeified_key) @options[snakeified_key] - elsif !@options[camelized_key].nil? + elsif @options.key?(camelized_key) @options[camelized_key] else @options[key]