Class: Attio::HttpClient Private
- Inherits:
-
Object
- Object
- Attio::HttpClient
- Defined in:
- lib/attio/http_client.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
HTTP client for making API requests to Attio
This class handles the low-level HTTP communication with the Attio API, including request execution, response parsing, and error handling.
Defined Under Namespace
Classes: ConnectionError, TimeoutError
Constant Summary collapse
- DEFAULT_TIMEOUT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
30
Instance Attribute Summary collapse
- #base_url ⇒ Object readonly private
- #headers ⇒ Object readonly private
- #rate_limiter ⇒ Object readonly private
- #timeout ⇒ Object readonly private
Instance Method Summary collapse
- #delete(path, params = nil) ⇒ Object private
- #error_class_for_status(status) ⇒ Object private private
- #execute_request(method, path, options = {}) ⇒ Object private private
- #extract_rate_limit_headers(response) ⇒ Object private private
- #extract_retry_after(response) ⇒ Object private private
- #get(path, params = nil) ⇒ Object private
- #handle_connection_error(response) ⇒ Object private private
- #handle_error_response(response) ⇒ Object private private
- #handle_response(response) ⇒ Object private private
-
#initialize(base_url:, headers: {}, timeout: DEFAULT_TIMEOUT, rate_limiter: nil) ⇒ HttpClient
constructor
private
A new instance of HttpClient.
- #parse_error_message(response) ⇒ Object private private
- #parse_json(body) ⇒ Object private private
- #patch(path, body = {}) ⇒ Object private
- #perform_request(method, path, options = {}) ⇒ Object private private
- #post(path, body = {}) ⇒ Object private
- #put(path, body = {}) ⇒ Object private
Constructor Details
#initialize(base_url:, headers: {}, timeout: DEFAULT_TIMEOUT, rate_limiter: nil) ⇒ HttpClient
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of HttpClient.
18 19 20 21 22 23 |
# File 'lib/attio/http_client.rb', line 18 def initialize(base_url:, headers: {}, timeout: DEFAULT_TIMEOUT, rate_limiter: nil) @base_url = base_url @headers = headers @timeout = timeout @rate_limiter = rate_limiter end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
16 17 18 |
# File 'lib/attio/http_client.rb', line 16 def base_url @base_url end |
#headers ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
16 17 18 |
# File 'lib/attio/http_client.rb', line 16 def headers @headers end |
#rate_limiter ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
16 17 18 |
# File 'lib/attio/http_client.rb', line 16 def rate_limiter @rate_limiter end |
#timeout ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
16 17 18 |
# File 'lib/attio/http_client.rb', line 16 def timeout @timeout end |
Instance Method Details
#delete(path, params = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
45 46 47 48 49 50 51 |
# File 'lib/attio/http_client.rb', line 45 def delete(path, params = nil) if params execute_request(:delete, path, body: params.to_json) else execute_request(:delete, path) end end |
#error_class_for_status(status) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/attio/http_client.rb', line 115 private def error_class_for_status(status) error_map = { 401 => AuthenticationError, 404 => NotFoundError, 422 => ValidationError, 429 => RateLimitError, } return error_map[status] if error_map.key?(status) return ServerError if (500..599).cover?(status) Error end |
#execute_request(method, path, options = {}) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
53 54 55 56 57 58 |
# File 'lib/attio/http_client.rb', line 53 private def execute_request(method, path, = {}) # Use rate limiter if available return @rate_limiter.execute { perform_request(method, path, ) } if @rate_limiter perform_request(method, path, ) end |
#extract_rate_limit_headers(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/attio/http_client.rb', line 150 private def extract_rate_limit_headers(response) headers = {} response.headers.each do |key, value| case key.downcase when "x-ratelimit-limit" headers["x-ratelimit-limit"] = value when "x-ratelimit-remaining" headers["x-ratelimit-remaining"] = value when "x-ratelimit-reset" headers["x-ratelimit-reset"] = value end end headers end |
#extract_retry_after(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/attio/http_client.rb', line 165 private def extract_retry_after(response) retry_after = response.headers["retry-after"] || response.headers["Retry-After"] return nil unless retry_after # Try parsing as integer (seconds) first parsed = retry_after.to_i # If to_i returns 0 but the string isn't "0", it means parsing failed return parsed if parsed > 0 || retry_after == "0" # If not a valid integer, could be HTTP date, default to 60 seconds 60 rescue StandardError # If not an integer, could be HTTP date, default to 60 seconds 60 end |
#get(path, params = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
25 26 27 28 29 30 31 |
# File 'lib/attio/http_client.rb', line 25 def get(path, params = nil) if params && !params.empty? execute_request(:get, path, params: params) else execute_request(:get, path) end end |
#handle_connection_error(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
93 94 95 96 97 |
# File 'lib/attio/http_client.rb', line 93 private def handle_connection_error(response) raise TimeoutError, "Request timed out" if response.timed_out? raise ConnectionError, "Connection failed: #{response.}" end |
#handle_error_response(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/attio/http_client.rb', line 99 private def handle_error_response(response) error_class = error_class_for_status(response.code) = (response) # Handle rate limit errors specially if response.code == 429 retry_after = extract_retry_after(response) raise RateLimitError.new(, retry_after: retry_after, response: response, code: response.code) end # Add status code to message for generic errors = "Request failed with status #{response.code}: #{}" if error_class == Error raise error_class, end |
#handle_response(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/attio/http_client.rb', line 80 private def handle_response(response) return handle_connection_error(response) if response.code == 0 if (200..299).cover?(response.code) result = parse_json(response.body) # Add headers to result for rate limiter to process result["_headers"] = extract_rate_limit_headers(response) if @rate_limiter return result end handle_error_response(response) end |
#parse_error_message(response) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/attio/http_client.rb', line 136 private def (response) body = begin parse_json(response.body) rescue StandardError response.body end if body.is_a?(Hash) body["error"] || body["message"] || body.to_s else body.to_s end end |
#parse_json(body) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
128 129 130 131 132 133 134 |
# File 'lib/attio/http_client.rb', line 128 private def parse_json(body) return {} if body.nil? || body.empty? JSON.parse(body) rescue JSON::ParserError => e raise Error, "Invalid JSON response: #{e.}" end |
#patch(path, body = {}) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
37 38 39 |
# File 'lib/attio/http_client.rb', line 37 def patch(path, body = {}) execute_request(:patch, path, body: body.to_json) end |
#perform_request(method, path, options = {}) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/attio/http_client.rb', line 60 private def perform_request(method, path, = {}) url = "#{base_url}/#{path}" = { method: method, headers: headers.merge("Content-Type" => "application/json"), timeout: timeout, connecttimeout: timeout, # SSL/TLS security settings ssl_verifypeer: true, ssl_verifyhost: 2, followlocation: false, # Prevent following redirects for security }.merge() request = Typhoeus::Request.new(url, ) response = request.run handle_response(response) end |
#post(path, body = {}) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/attio/http_client.rb', line 33 def post(path, body = {}) execute_request(:post, path, body: body.to_json) end |
#put(path, body = {}) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
41 42 43 |
# File 'lib/attio/http_client.rb', line 41 def put(path, body = {}) execute_request(:put, path, body: body.to_json) end |