Class: PactBroker::Client::Hal::HttpClient

Inherits:
Object
  • Object
show all
Defined in:
lib/pact_broker/client/hal/http_client.rb

Defined Under Namespace

Classes: Response

Constant Summary collapse

RETRYABLE_ERRORS =
[Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Net::ReadTimeout]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ HttpClient

Returns a new instance of HttpClient.



13
14
15
16
17
18
# File 'lib/pact_broker/client/hal/http_client.rb', line 13

def initialize options
  @username = options[:username]
  @password = options[:password]
  @verbose = options[:verbose]
  @token = options[:token]
end

Instance Attribute Details

#passwordObject

Returns the value of attribute password.



11
12
13
# File 'lib/pact_broker/client/hal/http_client.rb', line 11

def password
  @password
end

#tokenObject

Returns the value of attribute token.



11
12
13
# File 'lib/pact_broker/client/hal/http_client.rb', line 11

def token
  @token
end

#usernameObject

Returns the value of attribute username.



11
12
13
# File 'lib/pact_broker/client/hal/http_client.rb', line 11

def username
  @username
end

#verboseObject

Returns the value of attribute verbose.



11
12
13
# File 'lib/pact_broker/client/hal/http_client.rb', line 11

def verbose
  @verbose
end

Instance Method Details

#create_request(uri, http_method, body = nil, headers = {}) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/pact_broker/client/hal/http_client.rb', line 47

def create_request uri, http_method, body = nil, headers = {}
  request = Net::HTTP.const_get(http_method).new(uri.request_uri)
  request['Content-Type'] ||= "application/json" if ['Post', 'Put'].include?(http_method)
  request['Content-Type'] ||= "application/merge-patch+json" if ['Patch'].include?(http_method)
  request['Accept'] = "application/hal+json"
  headers.each do | key, value |
    request[key] = value
  end

  request.body = body if body
  request.basic_auth username, password if username
  request['Authorization'] = "Bearer #{token}" if token
  request
end

#default_max_triesObject



106
107
108
# File 'lib/pact_broker/client/hal/http_client.rb', line 106

def default_max_tries
  5
end

#delete(href, body = nil, headers = {}) ⇒ Object



42
43
44
45
# File 'lib/pact_broker/client/hal/http_client.rb', line 42

def delete href, body = nil, headers = {}
  uri = URI(href)
  perform_request(create_request(uri, 'Delete', body, headers), uri)
end

#get(href, params = {}, headers = {}) ⇒ Object



20
21
22
23
24
25
# File 'lib/pact_broker/client/hal/http_client.rb', line 20

def get href, params = {}, headers = {}
  query = params.collect{ |(key, value)| "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}" }.join("&")
  uri = URI(href)
  uri.query = query
  perform_request(create_request(uri, 'Get', nil, headers), uri)
end

#output_streamObject



114
115
116
# File 'lib/pact_broker/client/hal/http_client.rb', line 114

def output_stream
  AuthorizationHeaderRedactor.new($stdout)
end

#patch(href, body = nil, headers = {}) ⇒ Object



37
38
39
40
# File 'lib/pact_broker/client/hal/http_client.rb', line 37

def patch href, body = nil, headers = {}
  uri = URI(href)
  perform_request(create_request(uri, 'Patch', body, headers), uri)
end

#perform_request(request, uri) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/pact_broker/client/hal/http_client.rb', line 62

def perform_request request, uri
  response = until_truthy_or_max_times(condition: ->(resp) { resp.code.to_i < 500 }) do
    http = Net::HTTP.new(uri.host, uri.port, :ENV)
    http.set_debug_output(output_stream) if verbose
    http.use_ssl = (uri.scheme == 'https')
    # Need to manually set the ca_file and ca_path for the pact-ruby-standalone.
    # The env vars seem to be picked up automatically in later Ruby versions.
    # See https://github.com/pact-foundation/pact-ruby-standalone/issues/57
    http.ca_file = ENV['SSL_CERT_FILE'] if ENV['SSL_CERT_FILE'] && ENV['SSL_CERT_FILE'] != ''
    http.ca_path = ENV['SSL_CERT_DIR'] if ENV['SSL_CERT_DIR'] && ENV['SSL_CERT_DIR'] != ''
    http.start do |http|
      http.request request
    end
  end
  Response.new(response)
end

#post(href, body = nil, headers = {}) ⇒ Object



32
33
34
35
# File 'lib/pact_broker/client/hal/http_client.rb', line 32

def post href, body = nil, headers = {}
  uri = URI(href)
  perform_request(create_request(uri, 'Post', body, headers), uri)
end

#put(href, body = nil, headers = {}) ⇒ Object



27
28
29
30
# File 'lib/pact_broker/client/hal/http_client.rb', line 27

def put href, body = nil, headers = {}
  uri = URI(href)
  perform_request(create_request(uri, 'Put', body, headers), uri)
end

#sleep(seconds) ⇒ Object



110
111
112
# File 'lib/pact_broker/client/hal/http_client.rb', line 110

def sleep seconds
  Kernel.sleep seconds
end

#until_truthy_or_max_times(options = {}) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/pact_broker/client/hal/http_client.rb', line 79

def until_truthy_or_max_times options = {}
  max_tries = options.fetch(:times, default_max_tries)
  tries = 0
  sleep_interval = options.fetch(:sleep, 5)
  sleep(sleep_interval) if options[:sleep_first]
  while true
    begin
      result = yield
      return result if max_tries < 2
      if options[:condition]
        condition_result = options[:condition].call(result)
        return result if condition_result
      else
        return result if result
      end
      tries += 1
      return result if max_tries == tries
      sleep sleep_interval
    rescue *RETRYABLE_ERRORS => e
      tries += 1
      $stderr.puts "ERROR: Error making request - #{e.class} #{e.message} #{e.backtrace.find{|l| l.include?('pact_broker-client')}}, attempt #{tries} of #{max_tries}"
      raise e if max_tries == tries
      sleep sleep_interval
    end
  end
end