Loading lib/httpx/io/ssl.rb +20 −8 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ module HTTPX end def protocol # @type ivar @io: OpenSSL::SSL::SSLSocket @io.alpn_protocol || super rescue StandardError super Loading @@ -60,6 +61,7 @@ module HTTPX # in jruby, alpn_protocol may return "" # https://github.com/jruby/jruby-openssl/issues/287 def protocol # @type ivar @io: OpenSSL::SSL::SSLSocket proto = @io.alpn_protocol return super if proto.nil? || proto.empty? Loading @@ -76,9 +78,10 @@ module HTTPX def verify_hostname(host) return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE return false if !@io.respond_to?(:peer_cert) || @io.peer_cert.nil? # @type ivar @io: OpenSSL::SSL::SSLSocket return false if !@io.respond_to?(:peer_cert) || (peer_cert = @io.peer_cert).nil? OpenSSL::SSL.verify_certificate_identity(@io.peer_cert, host) OpenSSL::SSL.verify_certificate_identity(peer_cert, host) end def connected? Loading @@ -86,7 +89,9 @@ module HTTPX end def ssl_session_expired? @ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (@ssl_session.time.to_f + @ssl_session.timeout) ssl_session = @ssl_session ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (ssl_session.time.to_f + ssl_session.timeout) end def connect Loading @@ -97,6 +102,8 @@ module HTTPX return unless @state == :connected end # @type ivar @io: OpenSSL::SSL::SSLSocket unless @io.is_a?(OpenSSL::SSL::SSLSocket) if (hostname_is_ip = (@ip == @sni_hostname)) && @ctx.verify_hostname # IPv6 address would be "[::1]", must turn to "0000:0000:0000:0000:0000:0000:0000:0001" for cert SAN check Loading @@ -105,16 +112,19 @@ module HTTPX @ctx.verify_hostname = false end @io = OpenSSL::SSL::SSLSocket.new(@io, @ctx) ssl = OpenSSL::SSL::SSLSocket.new(@io, @ctx) @io.hostname = @sni_hostname unless hostname_is_ip @io.session = @ssl_session unless ssl_session_expired? @io.sync_close = true ssl.hostname = @sni_hostname unless hostname_is_ip ssl.session = @ssl_session unless ssl_session_expired? ssl.sync_close = true @io = ssl end try_ssl_connect end def try_ssl_connect # @type ivar @io: OpenSSL::SSL::SSLSocket ret = @io.connect_nonblock(exception: false) log(level: 3, color: :cyan) { "TLS CONNECT: #{ret}..." } case ret Loading Loading @@ -147,7 +157,9 @@ module HTTPX def log_transition_state(nextstate) return super unless nextstate == :negotiated server_cert = @io.peer_cert # @type ivar @io: OpenSSL::SSL::SSLSocket server_cert = @io.peer_cert #: OpenSSL::X509::Certificate "#{super}\n\n" \ "SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \ Loading lib/httpx/io/tcp.rb +15 −12 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ module HTTPX @fallback_protocol = @options.fallback_protocol @port = origin.port @interests = :w if @options.io @io = case @options.io if (io = @options.io) io = case io when Hash @options.io[origin.authority] io[origin.authority] else @options.io io end raise Error, "Given IO objects do not match the request authority" unless @io raise Error, "Given IO objects do not match the request authority" unless io _, _, _, ip = @io.addr @ip = Resolver::Entry.new(ip) @addresses << @ip # @type var io: TCPSocket | OpenSSL::SSL::SSLSocket _, _, _, ip = io.addr @io = io @addresses << (@ip = Resolver::Entry.new(ip)) @keep_open = true @state = :connected else Loading lib/httpx/io/unix.rb +13 −9 Original line number Diff line number Diff line Loading @@ -14,16 +14,20 @@ module HTTPX @state = :idle @options = options @fallback_protocol = @options.fallback_protocol if @options.io @io = case @options.io if (io = @options.io) io = case io when Hash @options.io[origin.authority] io[origin.authority] else @options.io io end raise Error, "Given IO objects do not match the request authority" unless @io raise Error, "Given IO objects do not match the request authority" unless io @path = @io.path # @type var io: UNIXSocket _, @path = io.addr @io = io @keep_open = true @state = :connected elsif path Loading sig/io/tcp.rbs +2 −2 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ module HTTPX public def read: (Integer size, ?(Buffer | String) buffer) -> (0 | nil | untyped) def read: (Integer size, Buffer | String buffer) -> (0 | nil | untyped) def write: (Buffer buffer) -> Integer? Loading @@ -67,6 +67,6 @@ module HTTPX def do_transition: (Symbol nextstate) -> void def log_transition_state: (Symbol nextstate) -> void def log_transition_state: (Symbol nextstate) -> String end end sig/options.rbs +4 −2 Original line number Diff line number Diff line Loading @@ -107,8 +107,10 @@ module HTTPX attr_reader ssl: Hash[Symbol, untyped] # io type io_option = _ToIO | Hash[String, _ToIO] type external_io = TCPSocket | OpenSSL::SSL::SSLSocket | UNIXSocket type io_option = external_io | Hash[String, external_io] attr_reader io: io_option? # fallback_protocol Loading Loading
lib/httpx/io/ssl.rb +20 −8 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ module HTTPX end def protocol # @type ivar @io: OpenSSL::SSL::SSLSocket @io.alpn_protocol || super rescue StandardError super Loading @@ -60,6 +61,7 @@ module HTTPX # in jruby, alpn_protocol may return "" # https://github.com/jruby/jruby-openssl/issues/287 def protocol # @type ivar @io: OpenSSL::SSL::SSLSocket proto = @io.alpn_protocol return super if proto.nil? || proto.empty? Loading @@ -76,9 +78,10 @@ module HTTPX def verify_hostname(host) return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE return false if !@io.respond_to?(:peer_cert) || @io.peer_cert.nil? # @type ivar @io: OpenSSL::SSL::SSLSocket return false if !@io.respond_to?(:peer_cert) || (peer_cert = @io.peer_cert).nil? OpenSSL::SSL.verify_certificate_identity(@io.peer_cert, host) OpenSSL::SSL.verify_certificate_identity(peer_cert, host) end def connected? Loading @@ -86,7 +89,9 @@ module HTTPX end def ssl_session_expired? @ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (@ssl_session.time.to_f + @ssl_session.timeout) ssl_session = @ssl_session ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (ssl_session.time.to_f + ssl_session.timeout) end def connect Loading @@ -97,6 +102,8 @@ module HTTPX return unless @state == :connected end # @type ivar @io: OpenSSL::SSL::SSLSocket unless @io.is_a?(OpenSSL::SSL::SSLSocket) if (hostname_is_ip = (@ip == @sni_hostname)) && @ctx.verify_hostname # IPv6 address would be "[::1]", must turn to "0000:0000:0000:0000:0000:0000:0000:0001" for cert SAN check Loading @@ -105,16 +112,19 @@ module HTTPX @ctx.verify_hostname = false end @io = OpenSSL::SSL::SSLSocket.new(@io, @ctx) ssl = OpenSSL::SSL::SSLSocket.new(@io, @ctx) @io.hostname = @sni_hostname unless hostname_is_ip @io.session = @ssl_session unless ssl_session_expired? @io.sync_close = true ssl.hostname = @sni_hostname unless hostname_is_ip ssl.session = @ssl_session unless ssl_session_expired? ssl.sync_close = true @io = ssl end try_ssl_connect end def try_ssl_connect # @type ivar @io: OpenSSL::SSL::SSLSocket ret = @io.connect_nonblock(exception: false) log(level: 3, color: :cyan) { "TLS CONNECT: #{ret}..." } case ret Loading Loading @@ -147,7 +157,9 @@ module HTTPX def log_transition_state(nextstate) return super unless nextstate == :negotiated server_cert = @io.peer_cert # @type ivar @io: OpenSSL::SSL::SSLSocket server_cert = @io.peer_cert #: OpenSSL::X509::Certificate "#{super}\n\n" \ "SSL connection using #{@io.ssl_version} / #{Array(@io.cipher).first}\n" \ Loading
lib/httpx/io/tcp.rb +15 −12 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ module HTTPX @fallback_protocol = @options.fallback_protocol @port = origin.port @interests = :w if @options.io @io = case @options.io if (io = @options.io) io = case io when Hash @options.io[origin.authority] io[origin.authority] else @options.io io end raise Error, "Given IO objects do not match the request authority" unless @io raise Error, "Given IO objects do not match the request authority" unless io _, _, _, ip = @io.addr @ip = Resolver::Entry.new(ip) @addresses << @ip # @type var io: TCPSocket | OpenSSL::SSL::SSLSocket _, _, _, ip = io.addr @io = io @addresses << (@ip = Resolver::Entry.new(ip)) @keep_open = true @state = :connected else Loading
lib/httpx/io/unix.rb +13 −9 Original line number Diff line number Diff line Loading @@ -14,16 +14,20 @@ module HTTPX @state = :idle @options = options @fallback_protocol = @options.fallback_protocol if @options.io @io = case @options.io if (io = @options.io) io = case io when Hash @options.io[origin.authority] io[origin.authority] else @options.io io end raise Error, "Given IO objects do not match the request authority" unless @io raise Error, "Given IO objects do not match the request authority" unless io @path = @io.path # @type var io: UNIXSocket _, @path = io.addr @io = io @keep_open = true @state = :connected elsif path Loading
sig/io/tcp.rbs +2 −2 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ module HTTPX public def read: (Integer size, ?(Buffer | String) buffer) -> (0 | nil | untyped) def read: (Integer size, Buffer | String buffer) -> (0 | nil | untyped) def write: (Buffer buffer) -> Integer? Loading @@ -67,6 +67,6 @@ module HTTPX def do_transition: (Symbol nextstate) -> void def log_transition_state: (Symbol nextstate) -> void def log_transition_state: (Symbol nextstate) -> String end end
sig/options.rbs +4 −2 Original line number Diff line number Diff line Loading @@ -107,8 +107,10 @@ module HTTPX attr_reader ssl: Hash[Symbol, untyped] # io type io_option = _ToIO | Hash[String, _ToIO] type external_io = TCPSocket | OpenSSL::SSL::SSLSocket | UNIXSocket type io_option = external_io | Hash[String, external_io] attr_reader io: io_option? # fallback_protocol Loading