mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-08-28 00:01:04 -04:00
added ssl channel, with alpn negotiation support
This commit is contained in:
parent
85f08f0c7a
commit
f3255ff182
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/**/*.swp
|
||||
*.gem
|
||||
.bundle
|
||||
.config
|
||||
|
@ -3,12 +3,12 @@
|
||||
module HTTPX::Channel
|
||||
module_function
|
||||
|
||||
def by(uri)
|
||||
def by(uri, *options)
|
||||
case uri.scheme
|
||||
when "http"
|
||||
TCP.new(uri)
|
||||
TCP.new(uri, *options)
|
||||
when "https"
|
||||
TLS.new(uri)
|
||||
SSL.new(uri, *options)
|
||||
else
|
||||
raise "#{uri.scheme}: unrecognized channel"
|
||||
end
|
||||
@ -17,3 +17,4 @@ end
|
||||
|
||||
require "httpx/channel/http2"
|
||||
require "httpx/channel/tcp"
|
||||
require "httpx/channel/ssl"
|
||||
|
64
lib/httpx/channel/ssl.rb
Normal file
64
lib/httpx/channel/ssl.rb
Normal file
@ -0,0 +1,64 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "forwardable"
|
||||
require "openssl"
|
||||
|
||||
module HTTPX::Channel
|
||||
class SSL < TCP
|
||||
def initialize(uri, ssl = {}, **)
|
||||
ctx = OpenSSL::SSL::SSLContext.new
|
||||
ctx.set_params(ssl)
|
||||
ctx.alpn_protocols = %w[h2 http/1.1] if ctx.respond_to?(:alpn_protocols=)
|
||||
ctx.alpn_select_cb = lambda do |pr|
|
||||
pr.first unless pr.nil? || pr.empty?
|
||||
end if ctx.respond_to?(:alpn_select_cb=)
|
||||
super
|
||||
@io = OpenSSL::SSL::SSLSocket.new(@io, ctx)
|
||||
@io.hostname = uri.host
|
||||
@io.sync_close = true
|
||||
@io.connect # TODO: non-block variant missing
|
||||
end
|
||||
|
||||
def protocol
|
||||
@io.alpn_protocol
|
||||
end
|
||||
|
||||
def send(request, &block)
|
||||
if @processor.nil?
|
||||
@processor = PROTOCOLS[protocol].new(@write_buffer)
|
||||
@processor.on(:response, &block)
|
||||
end
|
||||
@processor.send(request)
|
||||
end
|
||||
|
||||
if OpenSSL::VERSION < "2.0.6"
|
||||
# OpenSSL < 2.0.6 has a leak in the buffer destination data.
|
||||
# It has been fixed as of 2.0.6: https://github.com/ruby/openssl/pull/153
|
||||
def dread(size = BUFFER_SIZE)
|
||||
begin
|
||||
loop do
|
||||
@io.read_nonblock(size, @read_buffer)
|
||||
@processor << @read_buffer
|
||||
end
|
||||
rescue IO::WaitReadable
|
||||
# wait read/write
|
||||
rescue EOFError
|
||||
# EOF
|
||||
throw(:close, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def perform_io
|
||||
yield
|
||||
rescue IO::WaitReadable, IO::WaitWritable
|
||||
# wait read/write
|
||||
rescue EOFError
|
||||
# EOF
|
||||
@io.close
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -13,25 +13,22 @@ module HTTPX::Channel
|
||||
|
||||
BUFFER_SIZE = 1 << 16
|
||||
|
||||
attr_reader :remote_ip, :remote_port
|
||||
attr_reader :remote_ip, :remote_port, :protocol
|
||||
|
||||
def_delegator :@io, :to_io
|
||||
|
||||
def initialize(uri)
|
||||
def initialize(uri, *)
|
||||
@io = TCPSocket.new(uri.host, uri.port)
|
||||
_, @remote_port, _,@remote_ip = @io.peeraddr
|
||||
@read_buffer = +""
|
||||
@write_buffer = +""
|
||||
@protocol = "h2"
|
||||
end
|
||||
|
||||
def close
|
||||
@io.close
|
||||
end
|
||||
|
||||
def protocol
|
||||
"h2"
|
||||
end
|
||||
|
||||
def empty?
|
||||
@write_buffer.empty?
|
||||
end
|
||||
|
@ -62,7 +62,7 @@ module HTTPX
|
||||
|
||||
def close(channel)
|
||||
@channels.delete(channel)
|
||||
@channel.close
|
||||
channel.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user