Parent

Included Modules

Stella::Client

Constants

SSL_CERT_PATH

Attributes

base_uri[RW]
clientid[R]
created[RW]
index[R]
proxy[RW]

Public Class Methods

new(opts={}) click to toggle source

Options:

  • :timeout (Integer) => 30

  • :ssl_verify_mode (Class) => nil (possible values: OpenSSL::SSL::VERIFY_NONE)

# File lib/stella/client.rb, line 34
def initialize(opts={})
  @index = @@client_index += 1
  @created = Stella.now
  @opts = opts
  @opts[:timeout] ||= 30
  @base_uri, @index = opts[:base_uri] || opts['base_uri'], index
  @proxy = OpenStruct.new
  @done = false
  @session = Session.new @base_uri
  @redirect_count = 0
  @clientid = [@session.object_id, created, index, opts].digest
end

Public Instance Methods

create_http_client() click to toggle source
# File lib/stella/client.rb, line 195
def create_http_client
  http_client = HTTPClient.new(
    :agent_name  => @opts[:agent] || @opts['agent'] || Stella.agent,
    :from        => nil
  )
  #http_client.set_proxy_auth(@proxy.user, @proxy.pass) if @proxy.user
  #http_client.debug_dev = STDOUT if Stella.debug?
  http_client.protocol_version = "HTTP/1.1"
  if @opts[:ssl_verify_mode]
    http_client.ssl_config.verify_mode = @opts[:ssl_verify_mode]
  end
  
  # See: http://ghouston.blogspot.com/2006/03/using-ssl-with-ruby-http-access2.html
  begin 
    http_client.ssl_config.clear_cert_store
    http_client.ssl_config.set_trust_ca SSL_CERT_PATH
  rescue => ex
    Stella.li ex.class, ex.message
    Stella.ld ex.backtrace
  end
  
  http_client.connect_timeout = @opts[:timeout]
  http_client.send_timeout = @opts[:timeout]
  http_client.receive_timeout = @opts[:timeout]
  http_client
end
debug(msg) click to toggle source
# File lib/stella/client.rb, line 191
def debug(msg)
  Stella.ld " #{clientid.short} #{msg}"
end
done!() click to toggle source
# File lib/stella/client.rb, line 222
def done!
  @done = true
end
done?() click to toggle source
# File lib/stella/client.rb, line 226
def done?
  @done == true
end
exception() click to toggle source
# File lib/stella/client.rb, line 47
def exception 
  @session.exception
end
execute(usecase, &each_request) click to toggle source
# File lib/stella/client.rb, line 51
def execute usecase, &each_request
  @session.http_client = create_http_client
  tt = Benelux.current_track.timeline
  usecase.requests.each_with_index do |rt,idx|
    begin 
      debug "request start (session: #{@session.object_id})"
      @session.prepare_request usecase, rt 
      
      debug "#{@session.http_method} #{@session.uri} (#{rt.id.short})"
      debug " #{@session.params.inspect}" unless @session.params.empty?
      debug " #{@session.headers.inspect}" unless @session.headers.empty?
      
      stella_id = [clientid, rt.id, @session.uri.to_s, @session.params, @session.headers, idx].digest
      
      Benelux.current_track.add_tags :request   => rt.id
      Benelux.current_track.add_tags :stella_id => stella_id
      
      ## Useful for testing larger large request header
      ## 50.times do |idx|
      ##   headers["X-header-#{idx}"] = (1000 << 1000).to_s
      ## end
      
      # Mis-behaving HTTP servers will fail w/o an Accept header
      @session.headers["Accept"] ||= '*/*'
      
      # if hard_timeout is nil this will do nothing
      timeout(@opts[:hard_timeout], TimeoutError) do
        @session.generate_request stella_id
      end
      res = @session.res
      
      each_request.call(@session) unless each_request.nil?
      
      # Needs to happen before handle response incase it raises an exception
      log = Stella::Log::HTTP.new Stella.now,  
               @session.http_method, @session.uri, @session.params, res.request.header.dump, 
               res.request.body.content, res.status, res.header.dump, res.body.content
      
      tt.add_count :requests, 1, :kind => :http
      
      run_sleeper @opts[:wait] unless usecase.requests.size == idx+1
      
      if @session.response_handler?
        @session.handle_response
      elsif res.status >= 400
        raise Stella::HTTPError.new(res.status)
      elsif rt.follow && @session.redirect?
        raise ForcedRedirect, @session.location
      end

      tt.add_message log, :status => res.status, :kind => :http_log, :state => :nominal
      
      @redirect_count = 0
      
    rescue RepeatRequest => ex
      debug " REPEAT REQUEST: #{@session.location}"
      retry
      
    rescue ForcedRedirect => ex  
      # TODO: warn when redirecting from https to http
      debug " FOUND REDIRECT: #{@session.location}"
      if @redirect_count < 10
        @redirect_count += 1
        @session.clear_previous_request
        @session.redirect_uri = ex.location
        retry
      end
    
    rescue Errno::ETIMEDOUT, SocketError, 
           HTTPClient::ConnectTimeoutError, 
           HTTPClient::SendTimeoutError,
           HTTPClient::ReceiveTimeoutError,
           TimeoutError,
           Errno::ECONNRESET => ex
      debug "[#{ex.class}] #{ex.message}"
      log = Stella::Log::HTTP.new Stella.now, @session.http_method, @session.uri, @session.params
      if @session.res 
        log.request_headers = @session.res.request.header.dump if @session.res.request 
        log.request_body = @session.res.request.body.content if @session.res.request 
        log.response_status = @session.res.status
        log.response_headers = @session.res.header.dump if @session.res.content
        log.response_body = @session.res.body.content if @session.res.body
      end
      log.msg = "#{ex.class} (#{@session.http_client.receive_timeout})"
      tt.add_message log, :kind => :http_log, :state => :timeout
      Benelux.current_track.remove_tags :status, :request, :stella_id
      next
      
    rescue StellaError, StellaBehavior => ex
      debug "[#{ex.class}] #{ex.message}"
      log = Stella::Log::HTTP.new Stella.now, @session.http_method, @session.uri, @session.params
      if @session.res 
        log.request_headers = @session.res.request.header.dump if @session.res.request 
        log.request_body = @session.res.request.body.content if @session.res.request 
        log.response_status = @session.res.status
        log.response_headers = @session.res.header.dump if @session.res.content
        log.response_body = @session.res.body.content if @session.res.body
      end
      log.msg = ex.message
      tt.add_message log, :status => log.response_status, :kind => :http_log, :state => :exception
      Benelux.current_track.remove_tags :status, :request, :stella_id
      @session.exception = ex
      break
    
    rescue Errno::ECONNREFUSED => ex
      debug "[#{ex.class}] #{ex.message}"
      log = Stella::Log::HTTP.new Stella.now, @session.http_method, @session.uri, @session.params
      log.msg = "Connection refused"
      tt.add_message log, :status => log.response_status, :kind => :http_log, :state => :exception
      Benelux.current_track.remove_tags :status, :request, :stella_id
      break
    
    rescue OpenSSL::SSL::SSLError => ex
      debug "[#{ex.class}] #{ex.message}"
      log = Stella::Log::HTTP.new Stella.now, @session.http_method, @session.uri, @session.params
      log.msg = ex.message
      tt.add_message log, :status => log.response_status, :kind => :http_log, :state => :exception
      Benelux.current_track.remove_tags :status, :request, :stella_id
      break
      
    rescue => ex
      Stella.le "[#{ex.class}] #{ex.message}", ex.backtrace
      log = Stella::Log::HTTP.new Stella.now, @session.http_method, @session.uri, @session.params
      log.msg = ex.message
      tt.add_message log, :status => log.response_status, :kind => :http_log, :state => :fubar
      Benelux.current_track.remove_tags :status, :request, :stella_id
      break
      
    end
  end
  
end
run_sleeper(dur) click to toggle source
# File lib/stella/client.rb, line 184
def run_sleeper dur
  return unless dur && dur > 0
  dur = (rand * (dur.last-dur.first) + dur.first) if Range === dur
  debug "sleep: #{dur}"
  sleep dur
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.