diff --git a/lib/puma/binder.rb b/lib/puma/binder.rb index 1c498dbf..68802420 100644 --- a/lib/puma/binder.rb +++ b/lib/puma/binder.rb @@ -111,7 +111,16 @@ module Puma bak = params.fetch('backlog', 1024).to_i io = add_tcp_listener uri.host, uri.port, opt, bak - logger.log "* Listening on #{str}" + + @ios.each do |i| + addr = if i.local_address.ipv6? + "[#{i.local_address.ip_unpack[0]}]:#{i.local_address.ip_unpack[1]}" + else + i.local_address.ip_unpack.join(':') + end + + logger.log "* Listening on tcp://#{addr}" + end end @listeners << [str, io] if io diff --git a/test/test_binder.rb b/test/test_binder.rb index 89a7e584..b5ab9aa5 100644 --- a/test/test_binder.rb +++ b/test/test_binder.rb @@ -7,14 +7,20 @@ require "puma/puma_http11" class TestBinderBase < Minitest::Test def setup - @events = Puma::Events.null + @events = Puma::Events.strings @binder = Puma::Binder.new(@events) - @key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__ - @cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__ end private + def key + @key ||= File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__ + end + + def cert + @cert ||= File.expand_path "../../examples/puma/cert_puma.pem", __FILE__ + end + def ssl_context_for_binder(binder) binder.instance_variable_get(:@ios)[0].instance_variable_get(:@ctx) end @@ -26,6 +32,24 @@ class TestBinder < TestBinderBase assert_equal [], @binder.instance_variable_get(:@listeners) end + + def test_correct_zero_port + @binder.parse(["tcp://localhost:0"], @events) + + m = %r!tcp://127.0.0.1:(\d+)!.match(@events.stdout.string) + port = m[1].to_i + + refute_equal 0, port + end + + def test_logs_all_localhost_bindings + @binder.parse(["tcp://localhost:0"], @events) + + assert_match %r!tcp://127.0.0.1:(\d+)!, @events.stdout.string + if @binder.loopback_addresses.include?("::1") + assert_match %r!tcp://\[::1\]:(\d+)!, @events.stdout.string + end + end end class TestBinderJRuby < TestBinderBase @@ -52,7 +76,7 @@ class TestBinderMRI < TestBinderBase end def test_localhost_addresses_dont_alter_listeners_for_ssl_addresses - @binder.parse(["ssl://localhost:10002?key=#{@key}&cert=#{@cert}"], @events) + @binder.parse(["ssl://localhost:10002?key=#{key}&cert=#{cert}"], @events) assert_equal [], @binder.instance_variable_get(:@listeners) end @@ -60,38 +84,38 @@ class TestBinderMRI < TestBinderBase def test_binder_parses_ssl_cipher_filter ssl_cipher_filter = "AES@STRENGTH" - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&ssl_cipher_filter=#{ssl_cipher_filter}"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}&ssl_cipher_filter=#{ssl_cipher_filter}"], @events) assert_equal ssl_cipher_filter, ssl_context_for_binder(@binder).ssl_cipher_filter end def test_binder_parses_tlsv1_disabled - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1=true"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}&no_tlsv1=true"], @events) assert ssl_context_for_binder(@binder).no_tlsv1 end def test_binder_parses_tlsv1_enabled - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1=false"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}&no_tlsv1=false"], @events) refute ssl_context_for_binder(@binder).no_tlsv1 end def test_binder_parses_tlsv1_tlsv1_1_unspecified_defaults_to_enabled - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}"], @events) refute ssl_context_for_binder(@binder).no_tlsv1 refute ssl_context_for_binder(@binder).no_tlsv1_1 end def test_binder_parses_tlsv1_1_disabled - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1_1=true"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}&no_tlsv1_1=true"], @events) assert ssl_context_for_binder(@binder).no_tlsv1_1 end def test_binder_parses_tlsv1_1_enabled - @binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1_1=false"], @events) + @binder.parse(["ssl://0.0.0.0?key=#{key}&cert=#{cert}&no_tlsv1_1=false"], @events) refute ssl_context_for_binder(@binder).no_tlsv1_1 end