Class: Postscale::HttpClient

Inherits:
Object
  • Object
show all
Defined in:
lib/postscale/http_client.rb

Constant Summary collapse

IDEMPOTENT_METHODS =
%w[GET HEAD OPTIONS].freeze
RETRYABLE_ERRORS =
[
  Net::OpenTimeout,
  Net::ReadTimeout,
  Errno::ECONNREFUSED,
  Errno::ECONNRESET,
  Errno::EHOSTUNREACH,
  Errno::ETIMEDOUT,
  SocketError,
  EOFError
].freeze
USER_AGENT =
"postscale-ruby/#{Postscale::VERSION}"

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ HttpClient

Returns a new instance of HttpClient.



19
20
21
22
# File 'lib/postscale/http_client.rb', line 19

def initialize(config)
  @config = config
  @base_uri = URI.parse(config.base_url)
end

Instance Method Details

#delete(path, params: nil, headers: nil, parse_as: :json) ⇒ Object

Perform a DELETE request.



45
46
47
# File 'lib/postscale/http_client.rb', line 45

def delete(path, params: nil, headers: nil, parse_as: :json)
  request("DELETE", path, params: params, headers: headers, parse_as: parse_as)
end

#get(path, params: nil, headers: nil, parse_as: :json) ⇒ Object

Perform a GET request.



25
26
27
# File 'lib/postscale/http_client.rb', line 25

def get(path, params: nil, headers: nil, parse_as: :json)
  request("GET", path, params: params, headers: headers, parse_as: parse_as)
end

#patch(path, json: nil, headers: nil, parse_as: :json) ⇒ Object

Perform a PATCH request with a JSON body.



40
41
42
# File 'lib/postscale/http_client.rb', line 40

def patch(path, json: nil, headers: nil, parse_as: :json)
  request("PATCH", path, json: json, headers: headers, parse_as: parse_as)
end

#post(path, json: nil, headers: nil, parse_as: :json) ⇒ Object

Perform a POST request with a JSON body.



30
31
32
# File 'lib/postscale/http_client.rb', line 30

def post(path, json: nil, headers: nil, parse_as: :json)
  request("POST", path, json: json, headers: headers, parse_as: parse_as)
end

#put(path, json: nil, headers: nil, parse_as: :json) ⇒ Object

Perform a PUT request with a JSON body.



35
36
37
# File 'lib/postscale/http_client.rb', line 35

def put(path, json: nil, headers: nil, parse_as: :json)
  request("PUT", path, json: json, headers: headers, parse_as: parse_as)
end

#request(method, path, json: nil, params: nil, headers: nil, parse_as: :json) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/postscale/http_client.rb', line 49

def request(method, path, json: nil, params: nil, headers: nil, parse_as: :json)
  method = method.to_s.upcase
  attempts = max_attempts(method)
  last_error = nil

  attempts.times do |attempt|
    uri = build_uri(path, params)
    request = build_request(method, uri, json, headers)

    begin
      response = perform_request(uri, request)
    rescue *RETRYABLE_ERRORS => e
      last_error = network_error(e)
      if retry_network_error?(method, attempt, attempts)
        sleep_for(backoff(attempt))
        next
      end
      return failure(last_error)
    end

    response_headers = headers_from(response)
    status = response.code.to_i

    if status >= 200 && status < 300
      return Result.new(data: parse_success(response, parse_as), error: nil, headers: response_headers)
    end

    body = parse_error_body(response)
    error = api_error(status, body, response_headers.request_id)
    last_error = error

    if retry_response?(method, status, attempt, attempts)
      sleep_for(retry_delay(response, body, attempt))
      next
    end

    return Result.new(data: nil, error: error, headers: response_headers)
  end

  failure(last_error || APIError.new(message: "Postscale API request failed after all retry attempts.", code: "application_error"))
end