Class: Fopost::HTTP::Client
- Inherits:
-
Object
- Object
- Fopost::HTTP::Client
- Defined in:
- lib/fopost/http/client.rb
Overview
Internal transport wrapper: auth headers, JSON coding, envelope unwrap, and the 429 retry. One per Client.
Constant Summary collapse
- DEFAULT_BASE_URL =
'https://api.fopost.com/v1'- DEFAULT_TIMEOUT =
30.0- DEFAULT_MAX_RETRIES =
3- MAX_RETRY_WAIT =
60.0- USER_AGENT =
"fopost-ruby/#{Fopost::VERSION}".freeze
Instance Attribute Summary collapse
-
#base_url ⇒ Object
readonly
Returns the value of attribute base_url.
-
#max_retries ⇒ Object
readonly
Returns the value of attribute max_retries.
Class Method Summary collapse
-
.unwrap(body) ⇒ Object
Peel the
{"data": ...}envelope the API wraps most responses in.
Instance Method Summary collapse
- #delete(path, json = nil) ⇒ Object
- #get(path, params = nil) ⇒ Object
- #headers ⇒ Object
-
#initialize(api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, transport: nil, sleeper: nil) ⇒ Client
constructor
A new instance of Client.
- #post(path, json = nil) ⇒ Object
- #put(path, json = nil) ⇒ Object
-
#request(method, path, json: nil, params: nil) ⇒ Object
Send a request, retrying on 429, and return the decoded body.
Constructor Details
#initialize(api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, transport: nil, sleeper: nil) ⇒ Client
Returns a new instance of Client.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/fopost/http/client.rb', line 25 def initialize(api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, transport: nil, sleeper: nil) raise ConfigurationError, 'fopost: api_key is required' if api_key.nil? || api_key.to_s.empty? raise ConfigurationError, 'fopost: max_retries must be at least 1' if max_retries < 1 @api_key = api_key @base_url = base_url.to_s.sub(%r{/+\z}, '') @max_retries = max_retries @transport = transport || NetHTTPTransport.new(timeout: timeout) # Indirected so tests can replace the wait without touching the real clock. @sleeper = sleeper || ->(seconds) { sleep(seconds) } end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
Returns the value of attribute base_url.
23 24 25 |
# File 'lib/fopost/http/client.rb', line 23 def base_url @base_url end |
#max_retries ⇒ Object (readonly)
Returns the value of attribute max_retries.
23 24 25 |
# File 'lib/fopost/http/client.rb', line 23 def max_retries @max_retries end |
Class Method Details
.unwrap(body) ⇒ Object
Peel the {"data": ...} envelope the API wraps most responses in. Some
endpoints (POST /posts, GET /posts/:id) return the resource bare, so the
envelope comes off only when it is actually there.
86 87 88 |
# File 'lib/fopost/http/client.rb', line 86 def self.unwrap(body) body.is_a?(Hash) && body.key?('data') ? body['data'] : body end |
Instance Method Details
#delete(path, json = nil) ⇒ Object
79 80 81 |
# File 'lib/fopost/http/client.rb', line 79 def delete(path, json = nil) request(:delete, path, json: json) end |
#get(path, params = nil) ⇒ Object
67 68 69 |
# File 'lib/fopost/http/client.rb', line 67 def get(path, params = nil) request(:get, path, params: params) end |
#headers ⇒ Object
38 39 40 41 42 43 44 45 |
# File 'lib/fopost/http/client.rb', line 38 def headers { 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'X-API-Key' => @api_key, 'User-Agent' => USER_AGENT } end |
#post(path, json = nil) ⇒ Object
71 72 73 |
# File 'lib/fopost/http/client.rb', line 71 def post(path, json = nil) request(:post, path, json: json) end |
#put(path, json = nil) ⇒ Object
75 76 77 |
# File 'lib/fopost/http/client.rb', line 75 def put(path, json = nil) request(:put, path, json: json) end |
#request(method, path, json: nil, params: nil) ⇒ Object
Send a request, retrying on 429, and return the decoded body.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/fopost/http/client.rb', line 48 def request(method, path, json: nil, params: nil) url = build_url(path, params) body = json.nil? ? nil : JSON.generate(json) attempt = 0 loop do attempt += 1 response = @transport.call(method: method.to_s.upcase, url: url, headers: headers, body: body) if response.status == 429 && attempt < @max_retries wait = retry_after_seconds(response) @sleeper.call([wait || 1.0, MAX_RETRY_WAIT].min) next end return decode(response) end end |