Class: Philiprehberger::HttpClient::Client

Inherits:
Object
  • Object
show all
Includes:
Connection
Defined in:
lib/philiprehberger/http_client/client.rb

Constant Summary

Constants included from Connection

Philiprehberger::HttpClient::Connection::NETWORK_ERRORS, Philiprehberger::HttpClient::Connection::REDIRECT_CODES, Philiprehberger::HttpClient::Connection::RETRYABLE_ERRORS, Philiprehberger::HttpClient::Connection::TIMEOUT_ERRORS

Constants included from Retries

Retries::RETRY_AFTER_CEILING

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_url:, headers: {}, timeout: 30, **opts) ⇒ Client

Returns a new instance of Client.

Parameters:

  • base_url (String)

    Base URL for all requests

  • headers (Hash) (defaults to: {})

    Default headers applied to every request

  • timeout (Integer) (defaults to: 30)

    General read/open timeout in seconds

  • open_timeout (Integer, nil)

    TCP connection timeout (overrides timeout)

  • read_timeout (Integer, nil)

    Response read timeout (overrides timeout)

  • write_timeout (Integer, nil)

    Request write timeout (overrides timeout)

  • retries (Integer)

    Number of retry attempts on network errors

  • retry_delay (Numeric)

    Seconds to wait between retries

  • retry_backoff (Symbol)

    Backoff strategy (:fixed or :exponential)

  • retry_jitter (Boolean)

    Randomize backoff delay with full jitter (default: false)

  • retry_max_delay (Numeric)

    Upper bound (seconds) on any computed backoff delay (default: 30.0)

  • cookies (Boolean)

    Enable cookie jar for automatic cookie handling

  • proxy (String, nil)

    Proxy URL (e.g., "http://proxy:8080"), also reads HTTP_PROXY/HTTPS_PROXY

  • follow_redirects (Boolean)

    Follow 3xx redirects (default: true)

  • max_redirects (Integer)

    Maximum number of redirects to follow (default: 5)

  • pool (Boolean, nil)

    Enable connection pooling (default: false)

  • pool_size (Integer, nil)

    Maximum connections per host:port (default: 5)

  • cache (Boolean, nil)

    Enable response caching for GET requests (default: false)

  • cache_max_entries (Integer, nil)

    Maximum cached entries before LRU eviction (default: 1000)

  • on_request (Proc, nil)

    Callback invoked after each request with (method, uri, status, duration)



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/philiprehberger/http_client/client.rb', line 34

def initialize(base_url:, headers: {}, timeout: 30, **opts)
  @base_url = base_url.chomp('/')
  @default_headers = headers
  @timeout = timeout
  validate_timeout!(:timeout, timeout)
  assign_timeout_opts(opts)
  assign_retry_opts(opts)
  validate_config!
  assign_cookie_opts(opts)
  assign_proxy_opts(opts)
  assign_redirect_opts(opts)
  assign_pool_opts(opts)
  assign_cache_opts(opts)
  @on_request = opts[:on_request]
  @interceptors = []
  @request_count = 0
end

Instance Attribute Details

#cacheCache? (readonly)

Returns the response cache (nil if caching is disabled).

Returns:



70
71
72
# File 'lib/philiprehberger/http_client/client.rb', line 70

def cache
  @cache
end

Returns the cookie jar (nil if cookies are disabled).

Returns:



60
61
62
# File 'lib/philiprehberger/http_client/client.rb', line 60

def cookie_jar
  @cookie_jar
end

#poolPool? (readonly)

Returns the connection pool (nil if pooling is disabled).

Returns:



65
66
67
# File 'lib/philiprehberger/http_client/client.rb', line 65

def pool
  @pool
end

#request_countInteger (readonly)

Returns the total number of requests executed.

Returns:

  • (Integer)


55
56
57
# File 'lib/philiprehberger/http_client/client.rb', line 55

def request_count
  @request_count
end

Class Method Details

.open(**opts) {|Client| ... } ⇒ Object

Create a client, yield it to the block, and ensure it is closed afterward.

Parameters:

Yields:

  • (Client)

    the client instance

Returns:

  • (Object)

    the return value of the block



224
225
226
227
228
229
# File 'lib/philiprehberger/http_client/client.rb', line 224

def self.open(**opts)
  client = new(**opts)
  yield client
ensure
  client&.close
end

Instance Method Details

#basic_auth(username, password) ⇒ self

Set Basic auth credentials for all subsequent requests.

Parameters:

  • username (String)
  • password (String)

Returns:

  • (self)


199
200
201
202
203
# File 'lib/philiprehberger/http_client/client.rb', line 199

def basic_auth(username, password)
  encoded = Base64.strict_encode64("#{username}:#{password}")
  @default_headers['authorization'] = "Basic #{encoded}"
  self
end

#bearer_token(token) ⇒ self

Set a Bearer token for all subsequent requests.

Parameters:

  • token (String)

    the bearer token

Returns:

  • (self)


189
190
191
192
# File 'lib/philiprehberger/http_client/client.rb', line 189

def bearer_token(token)
  @default_headers['authorization'] = "Bearer #{token}"
  self
end

#clear_cache!void

This method returns an undefined value.

Flush the response cache. No-op if caching is disabled.



208
209
210
# File 'lib/philiprehberger/http_client/client.rb', line 208

def clear_cache!
  @cache&.clear!
end

#closevoid

This method returns an undefined value.

Drain the connection pool. No-op if pooling is disabled.



215
216
217
# File 'lib/philiprehberger/http_client/client.rb', line 215

def close
  @pool&.drain
end

#delete(path, headers: {}, expect: nil, request_id: nil, **timeout_opts) ⇒ Response

Perform a DELETE request.

Parameters:

  • path (String)

    Request path

  • headers (Hash) (defaults to: {})

    Additional headers

  • timeout (Integer, nil)

    Optional per-request timeout override

  • open_timeout (Integer, nil)

    Optional per-request open timeout

  • read_timeout (Integer, nil)

    Optional per-request read timeout

  • write_timeout (Integer, nil)

    Optional per-request write timeout

  • expect (Array<Integer>, nil) (defaults to: nil)

    Expected status codes

Returns:



179
180
181
182
183
# File 'lib/philiprehberger/http_client/client.rb', line 179

def delete(path, headers: {}, expect: nil, request_id: nil, **timeout_opts)
  uri = build_uri(path)
  request = Net::HTTP::Delete.new(uri)
  execute(uri, request, headers, expect: expect, request_id: request_id, **timeout_opts)
end

#get(path, params: {}, headers: {}, expect: nil, request_id: nil, **timeout_opts) {|String| ... } ⇒ Response

Perform a GET request.

Parameters:

  • path (String)

    Request path appended to the base URL

  • params (Hash) (defaults to: {})

    Query parameters

  • headers (Hash) (defaults to: {})

    Additional headers for this request

  • timeout (Integer, nil)

    Optional per-request timeout override

  • open_timeout (Integer, nil)

    Optional per-request open timeout

  • read_timeout (Integer, nil)

    Optional per-request read timeout

  • write_timeout (Integer, nil)

    Optional per-request write timeout

  • expect (Array<Integer>, nil) (defaults to: nil)

    Expected status codes (raises HttpError otherwise)

  • request_id (String, nil) (defaults to: nil)

    Custom request ID (auto-generated if nil)

Yields:

  • (String)

    response body chunks when streaming

Returns:



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/philiprehberger/http_client/client.rb', line 98

def get(path, params: {}, headers: {}, expect: nil, request_id: nil, **timeout_opts, &block)
  uri = build_uri(path, params)
  request = Net::HTTP::Get.new(uri)

  if @cache && !block
    cached = lookup_cache(uri, headers)
    return cached if cached
  end

  execute(uri, request, headers, expect: expect, request_id: request_id, **timeout_opts, &block)
end

#head(path, params: {}, headers: {}, expect: nil, request_id: nil, **timeout_opts) ⇒ Response

Perform a HEAD request.

Parameters:

  • path (String)

    Request path appended to the base URL

  • params (Hash) (defaults to: {})

    Query parameters

  • headers (Hash) (defaults to: {})

    Additional headers for this request

  • timeout (Integer, nil)

    Optional per-request timeout override

  • open_timeout (Integer, nil)

    Optional per-request open timeout

  • read_timeout (Integer, nil)

    Optional per-request read timeout

  • write_timeout (Integer, nil)

    Optional per-request write timeout

  • expect (Array<Integer>, nil) (defaults to: nil)

    Expected status codes

Returns:



121
122
123
124
125
# File 'lib/philiprehberger/http_client/client.rb', line 121

def head(path, params: {}, headers: {}, expect: nil, request_id: nil, **timeout_opts)
  uri = build_uri(path, params)
  request = Net::HTTP::Head.new(uri)
  execute(uri, request, headers, expect: expect, request_id: request_id, **timeout_opts)
end

#patch(path) ⇒ Response

Perform a PATCH request.

Parameters:

  • path (String)

    Request path

  • body (String, nil)

    Raw body string

  • json (Hash, Array, nil)

    JSON-serializable body

  • form (Hash, nil)

    Form-urlencoded body

  • multipart (Hash, nil)

    Multipart form data

  • headers (Hash)

    Additional headers

  • expect (Array<Integer>, nil)

    Expected status codes

Returns:



165
166
167
# File 'lib/philiprehberger/http_client/client.rb', line 165

def patch(path, ...)
  request_with_body(Net::HTTP::Patch, path, ...)
end

#post(path) ⇒ Response

Perform a POST request.

Parameters:

  • path (String)

    Request path

  • body (String, nil)

    Raw body string

  • json (Hash, Array, nil)

    JSON-serializable body (sets Content-Type automatically)

  • form (Hash, nil)

    Form-urlencoded body (sets Content-Type automatically)

  • multipart (Hash, nil)

    Multipart form data (sets Content-Type automatically)

  • headers (Hash)

    Additional headers

  • expect (Array<Integer>, nil)

    Expected status codes

Returns:



137
138
139
# File 'lib/philiprehberger/http_client/client.rb', line 137

def post(path, ...)
  request_with_body(Net::HTTP::Post, path, ...)
end

#put(path) ⇒ Response

Perform a PUT request.

Parameters:

  • path (String)

    Request path

  • body (String, nil)

    Raw body string

  • json (Hash, Array, nil)

    JSON-serializable body

  • form (Hash, nil)

    Form-urlencoded body

  • multipart (Hash, nil)

    Multipart form data

  • headers (Hash)

    Additional headers

  • expect (Array<Integer>, nil)

    Expected status codes

Returns:



151
152
153
# File 'lib/philiprehberger/http_client/client.rb', line 151

def put(path, ...)
  request_with_body(Net::HTTP::Put, path, ...)
end

#use {|Hash| ... } ⇒ self

Register a request/response interceptor.

The block receives a Hash with :request and, after the request completes, :response. It is called twice: once before the request (with :request only) and once after (with both :request and :response).

Yields:

  • (Hash)

    context hash with :request and optionally :response

Returns:

  • (self)


80
81
82
83
# File 'lib/philiprehberger/http_client/client.rb', line 80

def use(&block)
  @interceptors << block
  self
end