Class: HTTPX::SSL
Direct Known Subclasses
Constant Summary collapse
- TLS_OPTIONS =
rubocop:disable Style/MutableConstant
{ alpn_protocols: %w[h2 http/1.1].freeze }
Constants included from Loggable
Loggable::COLORS, Loggable::USE_DEBUG_LOG
Instance Attribute Summary collapse
-
#ssl_session ⇒ Object
writeonly
Sets the attribute ssl_session.
Attributes inherited from TCP
#addresses, #interests, #ip, #port, #state
Instance Method Summary collapse
- #can_verify_peer? ⇒ Boolean
- #connect ⇒ Object
- #connected? ⇒ Boolean
-
#initialize(_, _, options) ⇒ SSL
constructor
A new instance of SSL.
-
#protocol ⇒ Object
in jruby, alpn_protocol may return "" https://github.com/jruby/jruby-openssl/issues/287.
-
#session_new_cb {|sess| ... } ⇒ void
session_new_cb not implemented under JRuby.
- #ssl_session_expired? ⇒ Boolean
-
#try_ssl_connect ⇒ void
:nocov:.
- #verify_hostname(host) ⇒ Boolean
Methods inherited from TCP
#add_addresses, #addresses?, #build_socket, #can_disconnect?, #close, #closed?, #do_transition, #inspect, #read, #socket, #to_io, #try_connect, #write
Methods included from Loggable
#log, #log_exception, log_identifiers, #log_redact, #log_redact_body, #log_redact_headers
Constructor Details
#initialize(_, _, options) ⇒ SSL
Returns a new instance of SSL.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/httpx/io/ssl.rb', line 19 def initialize(_, _, ) super @ssl_session = nil = TLS_OPTIONS = .merge(.ssl) if .ssl && !.ssl.empty? @sni_hostname = (.delete(:hostname) if .key?(:hostname)) || @hostname if @keep_open && @io.is_a?(OpenSSL::SSL::SSLSocket) # externally initiated ssl socket @ctx = @io.context @state = :negotiated else @ctx = OpenSSL::SSL::SSLContext.new @ctx.set_params() unless @ctx.session_cache_mode.nil? # a dummy method on JRuby @ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE end yield(self) if block_given? end @verify_hostname = @ctx.verify_hostname end |
Instance Attribute Details
#ssl_session=(value) ⇒ Object (writeonly)
Sets the attribute ssl_session
17 18 19 |
# File 'lib/httpx/io/ssl.rb', line 17 def ssl_session=(value) @ssl_session = value end |
Instance Method Details
#can_verify_peer? ⇒ Boolean
74 75 76 |
# File 'lib/httpx/io/ssl.rb', line 74 def can_verify_peer? @ctx.verify_mode == OpenSSL::SSL::VERIFY_PEER end |
#connect ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/httpx/io/ssl.rb', line 96 def connect return if @state == :negotiated unless @state == :connected super 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 @sni_hostname = @ip.to_string # IP addresses in SNI is not valid per RFC 6066, section 3. @ctx.verify_hostname = false end ssl = OpenSSL::SSL::SSLSocket.new(@io, @ctx) 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 |
#connected? ⇒ Boolean
86 87 88 |
# File 'lib/httpx/io/ssl.rb', line 86 def connected? @state == :negotiated end |
#protocol ⇒ Object
in jruby, alpn_protocol may return "" https://github.com/jruby/jruby-openssl/issues/287
63 64 65 66 67 |
# File 'lib/httpx/io/ssl.rb', line 63 def protocol return super unless @io.is_a?(OpenSSL::SSL::SSLSocket) @io.alpn_protocol || super end |
#session_new_cb {|sess| ... } ⇒ void
This method returns an undefined value.
session_new_cb not implemented under JRuby
51 52 53 |
# File 'lib/httpx/io/ssl.rb', line 51 def session_new_cb(&pr) @ctx.session_new_cb = proc { |_, sess| pr.call(sess) } end |
#ssl_session_expired? ⇒ Boolean
90 91 92 93 94 |
# File 'lib/httpx/io/ssl.rb', line 90 def ssl_session_expired? ssl_session = @ssl_session ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (ssl_session.time.to_f + ssl_session.timeout) end |
#try_ssl_connect ⇒ void
This method returns an undefined value.
:nocov:
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'sig/io/ssl.rbs', line 26 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 when :wait_readable @interests = :r return when :wait_writable @interests = :w return end @io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname transition(:negotiated) @interests = :w end |
#verify_hostname(host) ⇒ Boolean
78 79 80 81 82 83 84 |
# File 'lib/httpx/io/ssl.rb', line 78 def verify_hostname(host) return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE # @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(peer_cert, host) end |