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

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)

  • cookies (Boolean)

    Enable cookie jar for automatic cookie handling

  • proxy (String, nil)

    Proxy URL (e.g., “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)

  • on_request (Proc, nil)

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



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

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:



67
68
69
# File 'lib/philiprehberger/http_client/client.rb', line 67

def cache
  @cache
end

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

Returns:



57
58
59
# File 'lib/philiprehberger/http_client/client.rb', line 57

def cookie_jar
  @cookie_jar
end

#poolPool? (readonly)

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

Returns:



62
63
64
# File 'lib/philiprehberger/http_client/client.rb', line 62

def pool
  @pool
end

#request_countInteger (readonly)

Returns the total number of requests executed.

Returns:

  • (Integer)


52
53
54
# File 'lib/philiprehberger/http_client/client.rb', line 52

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



221
222
223
224
225
226
# File 'lib/philiprehberger/http_client/client.rb', line 221

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)


196
197
198
199
200
# File 'lib/philiprehberger/http_client/client.rb', line 196

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)


186
187
188
189
# File 'lib/philiprehberger/http_client/client.rb', line 186

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.



205
206
207
# File 'lib/philiprehberger/http_client/client.rb', line 205

def clear_cache!
  @cache&.clear!
end

#closevoid

This method returns an undefined value.

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



212
213
214
# File 'lib/philiprehberger/http_client/client.rb', line 212

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:



176
177
178
179
180
# File 'lib/philiprehberger/http_client/client.rb', line 176

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:



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/philiprehberger/http_client/client.rb', line 95

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:



118
119
120
121
122
# File 'lib/philiprehberger/http_client/client.rb', line 118

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:



162
163
164
# File 'lib/philiprehberger/http_client/client.rb', line 162

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:



134
135
136
# File 'lib/philiprehberger/http_client/client.rb', line 134

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:



148
149
150
# File 'lib/philiprehberger/http_client/client.rb', line 148

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)


77
78
79
80
# File 'lib/philiprehberger/http_client/client.rb', line 77

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