passed more of the channel discovery logic to the client; this allows for more more transparent IO plugins, and removes the last monkey-patch

This commit is contained in:
HoneyryderChuck 2018-01-03 09:51:25 +02:00
parent 2d79aa3673
commit c7cd490b73
3 changed files with 37 additions and 49 deletions

View File

@ -33,6 +33,12 @@ module HTTPX
private private
def find_channel(request)
uri = URI(request.uri)
@connection.find_channel(uri) ||
@connection.build_channel(uri)
end
def __build_reqs(*args, **options) def __build_reqs(*args, **options)
case args.size case args.size
when 1 when 1
@ -56,7 +62,10 @@ module HTTPX
end end
def __send_reqs(*requests) def __send_reqs(*requests)
requests.each { |request| @connection << request } requests.each do |request|
channel = find_channel(request)
channel.send(request)
end
responses = [] responses = []
# guarantee ordered responses # guarantee ordered responses

View File

@ -17,14 +17,6 @@ module HTTPX
!@channels.empty? !@channels.empty?
end end
def send(request, **args)
channel = bind(request.uri)
raise Error, "no channel available" unless channel
channel.send(request, **args)
end
alias :<< :send
def next_tick(timeout: @timeout.timeout) def next_tick(timeout: @timeout.timeout)
@selector.select(timeout) do |monitor| @selector.select(timeout) do |monitor|
if task = monitor.value if task = monitor.value
@ -56,29 +48,26 @@ module HTTPX
response response
end end
private def build_channel(uri)
channel = Channel.by(uri, @options, &method(:on_response))
def on_response(request, response) register_channel(channel)
@responses[request] = response channel
end end
# opens a channel to the IP reachable through +uri+. # opens a channel to the IP reachable through +uri+.
# Many hostnames are reachable through the same IP, so we try to # Many hostnames are reachable through the same IP, so we try to
# maximize pipelining by opening as few channels as possible. # maximize pipelining by opening as few channels as possible.
# #
def bind(uri) def find_channel(uri)
uri = URI(uri)
return @channels.find do |channel| return @channels.find do |channel|
channel.match?(uri) channel.match?(uri)
end || begin
channel = build_channel(uri)
register_channel(channel)
channel
end end
end end
def build_channel(uri) private
Channel.by(uri, @options, &method(:on_response))
def on_response(request, response)
@responses[request] = response
end end
def register_channel(channel) def register_channel(channel)

View File

@ -5,7 +5,7 @@ require "forwardable"
module HTTPX module HTTPX
module Plugins module Plugins
module Proxy module Proxy
def self.load_dependencies(*) def self.configure(*)
require "httpx/plugins/proxy/http" require "httpx/plugins/proxy/http"
require "httpx/plugins/proxy/socks" require "httpx/plugins/proxy/socks"
end end
@ -31,49 +31,39 @@ module HTTPX
end end
end end
module ConnectionMethods module InstanceMethods
def bind(uri) def with_proxy(*args)
proxy = proxy_params(uri) branch(default_options.with_proxy(*args))
return super unless proxy
return @channels.find do |channel|
channel.match?(uri)
end || begin
channel = build_proxy_channel(proxy)
register_channel(channel)
channel
end
end end
private private
def proxy_params(uri) def proxy_params(uri)
return @options.proxy if @options.proxy return @default_options.proxy if @default_options.proxy
uri = URI(uri).find_proxy uri = URI(uri).find_proxy
return unless uri return unless uri
{ uri: uri } { uri: uri }
end end
def find_channel(request)
uri = URI(request.uri)
proxy = proxy_params(uri)
return super unless proxy
@connection.find_channel(proxy) ||
build_proxy_channel(proxy)
end
def build_proxy_channel(proxy) def build_proxy_channel(proxy)
parameters = Parameters.new(**proxy) parameters = Parameters.new(**proxy)
uri = parameters.uri uri = parameters.uri
io = TCP.new(uri.host, uri.port, @options) io = TCP.new(uri.host, uri.port, @default_options)
proxy_type = Parameters.registry(parameters.type) proxy_type = Parameters.registry(parameters.type)
proxy_type.new(io, parameters, @options, &method(:on_response)) channel = proxy_type.new(io, parameters, @default_options, &@connection.method(:on_response))
@connection.__send__(:register_channel, channel)
channel
end end
end end
module InstanceMethods
def initialize(*)
super
@connection.extend(ConnectionMethods)
end
def with_proxy(*args)
branch(default_options.with_proxy(*args))
end
end
module OptionsMethods module OptionsMethods
def self.included(klass) def self.included(klass)
super super