class HTTPClient::SessionManager
Manages sessions for a HTTPClient
instance.
Attributes
Name of this client. Used for ‘User-Agent’ header in HTTP
request.
Chunk size for chunked request
Maximum retry count. 0 for infinite.
Device for dumping log for debugging
Owner of this client. Used for ‘From’ header in HTTP
request.
Requested protocol version
Local address to bind local side of the socket to
Boolean value for Socket#sync
Raise BadResponseError
if response size does not match with Content-Length header in response.
Boolean value to send TCP keepalive packets; no timing settings exist at present
Public Class Methods
# File lib/httpclient/session.rb, line 132 def initialize(client) @client = client @proxy = client.proxy @agent_name = nil @from = nil @protocol_version = nil @debug_dev = client.debug_dev @socket_sync = true @tcp_keepalive = false @chunk_size = ::HTTP::Message::Body::DEFAULT_CHUNK_SIZE @connect_timeout = 60 @connect_retry = 1 @send_timeout = 120 @receive_timeout = 60 # For each read_block_size bytes @keep_alive_timeout = 15 # '15' is from Apache 2 default @read_block_size = 1024 * 16 # follows net/http change in 1.8.7 @protocol_retry_count = 5 @ssl_config = nil @test_loopback_http_response = [] @transparent_gzip_decompression = false @strict_response_size_check = false @socket_local = Site.new @sess_pool = {} @sess_pool_mutex = Mutex.new @sess_pool_last_checked = Time.now end
Public Instance Methods
assert: sess.last_used must not be nil
# File lib/httpclient/session.rb, line 195 def keep(sess) add_cached_session(sess) end
# File lib/httpclient/session.rb, line 165 def proxy=(proxy) if proxy.nil? @proxy = nil else @proxy = Site.new(proxy) end end
# File lib/httpclient/session.rb, line 173 def query(req, via_proxy) req.http_body.chunk_size = @chunk_size if req.http_body sess = get_session(req, via_proxy) begin sess.query(req) rescue sess.close raise end sess end
# File lib/httpclient/session.rb, line 185 def reset(uri) site = Site.new(uri) close(site) end
# File lib/httpclient/session.rb, line 190 def reset_all close_all end
Private Instance Methods
# File lib/httpclient/session.rb, line 298 def add_cached_session(sess) @sess_pool_mutex.synchronize do (@sess_pool[sess.dest] ||= []).unshift(sess) end end
This method might not work as you expected…
# File lib/httpclient/session.rb, line 251 def close(dest) if cached = get_cached_session(Site.new(dest)) cached.close true else false end end
# File lib/httpclient/session.rb, line 239 def close_all @sess_pool_mutex.synchronize do @sess_pool.each do |site, pool| pool.each do |sess| sess.close end end end @sess_pool.clear end
# File lib/httpclient/session.rb, line 260 def get_cached_session(site) if Thread.current[:HTTPClient_AcquireNewConnection] return nil end @sess_pool_mutex.synchronize do now = Time.now if now > @sess_pool_last_checked + @keep_alive_timeout scrub_cached_session(now) @sess_pool_last_checked = now end if pool = @sess_pool[site] pool.each_with_index do |sess, idx| if valid_session?(sess, now) return pool.slice!(idx) end end end end nil end
TODO: create PR for webmock’s httpclient adapter to use get_session
instead of open so that we can remove duplicated Site
creation for each session.
# File lib/httpclient/session.rb, line 204 def get_session(req, via_proxy = false) uri = req.header.request_uri if uri.scheme.nil? raise ArgumentError.new("Request URI must have schema. Possibly add 'http://' to the request URI?") end site = Site.new(uri) if cached = get_cached_session(site) cached else open(uri, via_proxy) end end
# File lib/httpclient/session.rb, line 217 def open(uri, via_proxy = false) site = Site.new(uri) sess = Session.new(@client, site, @agent_name, @from) sess.proxy = via_proxy ? @proxy : nil sess.socket_sync = @socket_sync sess.tcp_keepalive = @tcp_keepalive sess.requested_version = @protocol_version if @protocol_version sess.connect_timeout = @connect_timeout sess.connect_retry = @connect_retry sess.send_timeout = @send_timeout sess.receive_timeout = @receive_timeout sess.read_block_size = @read_block_size sess.protocol_retry_count = @protocol_retry_count sess.ssl_config = @ssl_config sess.debug_dev = @debug_dev sess.strict_response_size_check = @strict_response_size_check sess.socket_local = @socket_local sess.test_loopback_http_response = @test_loopback_http_response sess.transparent_gzip_decompression = @transparent_gzip_decompression sess end
# File lib/httpclient/session.rb, line 281 def scrub_cached_session(now) @sess_pool.each do |site, pool| pool.replace(pool.select { |sess| if valid_session?(sess, now) true else sess.close # close & remove from the pool false end }) end end
# File lib/httpclient/session.rb, line 294 def valid_session?(sess, now) (now <= sess.last_used + @keep_alive_timeout) end