When the SSLSocket client sets the alpn protocol parameters, but the server does not negotiate it, returned alpn_protocol is an empty string (instead of nil). This script reproduces it:
require "uri"
require "openssl"
require "logger"
require "webrick/ssl"
class TestServer < WEBrick::HTTPServer
def initialize
super(
:BindAddress => "127.0.0.1",
:Port => 0,
:SSLEnable => true,
:SSLStartImmediately => true,
:SSLCertName => "/C=JP/O=www.ruby-lang.org/CN=Ruby",
:SSLCertComment => "bang",
:AccessLog => $stderr,
:Logger => Logger.new($stderr)
)
mount_proc("/") do |_req, res|
res.status = 200
res.body = "hello"
end
end
def origin
sock = listeners.first
_, port, ip, _ = sock.addr
scheme = @config[:SSLEnable] ? URI::HTTPS : URI::HTTP
scheme.build(host: ip, port: port)
end
end
def start_test_servlet(servlet_class, *args)
server = servlet_class.new(*args)
th = Thread.new { server.start }
begin
yield server
ensure
if server.respond_to?(:shutdown)
server.shutdown
begin
Timeout.timeout(3) { th.join }
rescue Timeout::Error
th.kill
end
else
th.kill
end
end
end
start_test_servlet(TestServer) do |server|
uri = URI(server.origin)
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE, alpn_protocols: %w[h2 http/1.1])
ssl = OpenSSL::SSL::SSLSocket.open(uri.host, uri.port, context: ctx)
ssl.connect
puts "alpn: #{ssl.alpn_protocol.inspect}"
ssl.close
end
# nil in ruby 3.2. "" in jruby 9.4, jruby-openssl 0.14.1, BC 1.71
When the SSLSocket client sets the alpn protocol parameters, but the server does not negotiate it, returned alpn_protocol is an empty string (instead of
nil
). This script reproduces it: