added the options module, similar to http

This commit is contained in:
HoneyryderChuck 2017-11-28 18:12:02 +00:00
parent 70a2d7ad82
commit c7319964c0
5 changed files with 137 additions and 13 deletions

View File

@ -3,6 +3,7 @@
require "httpx/version"
require "httpx/callbacks"
require "httpx/options"
require "httpx/connection"
require "httpx/headers"
require "httpx/request"

View File

@ -3,8 +3,12 @@
module HTTPX
class Client
def initialize(**options)
@connection = Connection.new(**options)
@default_options = options
@default_options = Options.new(options)
@connection = Connection.new(@default_options)
end
def close
@connection.close
end
def request(verb, uri, **options)

View File

@ -7,11 +7,9 @@ require "httpx/channel"
module HTTPX
class Connection
CONNECTION_TIMEOUT = 2
def initialize(**options)
@options = options
@connection_timeout = options.fetch(:connection_timeout, CONNECTION_TIMEOUT)
def initialize(options)
@options = Options.new(options)
@operation_timeout = options.operation_timeout
@channels = []
@responses = {}
end
@ -42,10 +40,10 @@ module HTTPX
end
def response(request)
@responses[request]
@responses.delete(request)
end
def process_events(timeout: @connection_timeout)
def process_events(timeout: @operation_timeout)
rmonitors = @channels
wmonitors = rmonitors.reject(&:empty?)
readers, writers = IO.select(rmonitors, wmonitors, nil, timeout)
@ -60,9 +58,15 @@ module HTTPX
end if writers
end
def close(channel)
@channels.delete(channel)
channel.close
def close(channel = nil)
if channel
@channels.delete(channel)
channel.close
else
while ch = @channels.shift
ch.close
end
end
end
end
end

View File

@ -4,6 +4,13 @@ module HTTPX
class Headers
EMPTY = [].freeze # :nodoc:
class << self
def new(h = nil)
return h if h.is_a?(self)
super
end
end
def initialize(h = nil)
@headers = {}
return unless h
@ -90,6 +97,10 @@ module HTTPX
end
end
def ==(other)
to_hash == Headers.new(other).to_hash
end
# the headers store in Hash format
def to_hash
Hash[to_a]
@ -133,7 +144,7 @@ module HTTPX
end
def downcased(field)
field.downcase
String(field).downcase
end
end
end

104
lib/httpx/options.rb Normal file
View File

@ -0,0 +1,104 @@
# frozen_string_literal: true
module HTTPX
class Options
KEEP_ALIVE_TIMEOUT = 5
OPERATION_TIMEOUT = 5
CONNECT_TIMEOUT = 5
class << self
def new(options = {})
return options if options.is_a?(self)
super
end
def defined_options
@defined_options ||= []
end
protected
def def_option(name, &interpreter)
defined_options << name.to_sym
interpreter ||= lambda { |v| v }
attr_accessor name
protected :"#{name}="
define_method(:"with_#{name}") do |value|
dup { |opts| opts.send(:"#{name}=", instance_exec(value, &interpreter)) }
end
end
end
def initialize(options = {})
defaults = {
:proxy => {},
:ssl => {},
:keep_alive_timeout => KEEP_ALIVE_TIMEOUT,
:operation_timeout => OPERATION_TIMEOUT,
:connect_timeout => CONNECT_TIMEOUT,
:headers => {},
:cookies => {},
}
defaults.merge!(options)
defaults[:headers] = Headers.new(defaults[:headers])
defaults.each { |(k, v)| self[k] = v }
end
def_option(:headers) do |headers|
self.headers.merge(headers)
end
def_option(:cookies) do |cookies|
cookies.each_with_object self.cookies.dup do |(k, v), jar|
cookie = k.is_a?(Cookie) ? k : Cookie.new(k.to_s, v.to_s)
jar[cookie.name] = cookie.cookie_value
end
end
%w[
proxy params form json body follow
ssl_context ssl
keep_alive_timeout connect_timeout operation_timeout
].each do |method_name|
def_option(method_name)
end
def merge(other)
h1 = to_hash
h2 = other.to_hash
merged = h1.merge(h2) do |k, v1, v2|
case k
when :headers
v1.merge(v2)
else
v2
end
end
self.class.new(merged)
end
def to_hash
hash_pairs = self.class.
defined_options.
flat_map { |opt_name| [opt_name, send(opt_name)] }
Hash[*hash_pairs]
end
def dup
dupped = super
yield(dupped) if block_given?
dupped
end
protected
def []=(option, val)
send(:"#{option}=", val)
end
end
end