mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-10-16 00:01:48 -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
|
*.gem
|
||||||
.bundle
|
.bundle
|
||||||
.config
|
.config
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
module HTTPX::Channel
|
module HTTPX::Channel
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def by(uri)
|
def by(uri, *options)
|
||||||
case uri.scheme
|
case uri.scheme
|
||||||
when "http"
|
when "http"
|
||||||
TCP.new(uri)
|
TCP.new(uri, *options)
|
||||||
when "https"
|
when "https"
|
||||||
TLS.new(uri)
|
SSL.new(uri, *options)
|
||||||
else
|
else
|
||||||
raise "#{uri.scheme}: unrecognized channel"
|
raise "#{uri.scheme}: unrecognized channel"
|
||||||
end
|
end
|
||||||
@ -17,3 +17,4 @@ end
|
|||||||
|
|
||||||
require "httpx/channel/http2"
|
require "httpx/channel/http2"
|
||||||
require "httpx/channel/tcp"
|
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
|
BUFFER_SIZE = 1 << 16
|
||||||
|
|
||||||
attr_reader :remote_ip, :remote_port
|
attr_reader :remote_ip, :remote_port, :protocol
|
||||||
|
|
||||||
def_delegator :@io, :to_io
|
def_delegator :@io, :to_io
|
||||||
|
|
||||||
def initialize(uri)
|
def initialize(uri, *)
|
||||||
@io = TCPSocket.new(uri.host, uri.port)
|
@io = TCPSocket.new(uri.host, uri.port)
|
||||||
_, @remote_port, _,@remote_ip = @io.peeraddr
|
_, @remote_port, _,@remote_ip = @io.peeraddr
|
||||||
@read_buffer = +""
|
@read_buffer = +""
|
||||||
@write_buffer = +""
|
@write_buffer = +""
|
||||||
|
@protocol = "h2"
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
@io.close
|
@io.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def protocol
|
|
||||||
"h2"
|
|
||||||
end
|
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
@write_buffer.empty?
|
@write_buffer.empty?
|
||||||
end
|
end
|
||||||
|
@ -62,7 +62,7 @@ module HTTPX
|
|||||||
|
|
||||||
def close(channel)
|
def close(channel)
|
||||||
@channels.delete(channel)
|
@channels.delete(channel)
|
||||||
@channel.close
|
channel.close
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user