Class: ApiAdaptor::JsonClient

Inherits:
Object
  • Object
show all
Includes:
ExceptionHandling
Defined in:
lib/api_adaptor/json_client.rb

Overview

HTTP client for JSON APIs with comprehensive redirect handling and authentication support.

JSONClient provides a low-level interface for making HTTP requests to JSON APIs. It handles automatic JSON parsing, configurable redirect following, authentication (bearer token and basic auth), timeout management, and comprehensive error handling.

Examples:

Basic usage with bearer token

client = JSONClient.new(bearer_token: "abc123")
response = client.get_json("https://api.example.com/users")
users = response["data"]

Custom timeout and redirect configuration

client = JSONClient.new(
  timeout: 10,
  max_redirects: 5,
  follow_non_get_redirects: true
)

With basic authentication

client = JSONClient.new(
  basic_auth: { user: "username", password: "password" }
)

Disable cross-origin redirects for security

client = JSONClient.new(
  allow_cross_origin_redirects: false
)

See Also:

Constant Summary collapse

DEFAULT_TIMEOUT_IN_SECONDS =

Default request timeout in seconds

4
DEFAULT_MAX_REDIRECTS =

Default maximum number of redirects to follow

3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ExceptionHandling

#build_specific_http_error, #error_class_for_code

Constructor Details

#initialize(options = {}) ⇒ JsonClient

Initializes a new JSON HTTP client

Examples:

Default configuration

client = JSONClient.new
# timeout: 4s, max_redirects: 3, only GET/HEAD follow redirects

Full configuration

client = JSONClient.new(
  bearer_token: "secret",
  timeout: 10,
  max_redirects: 5,
  allow_cross_origin_redirects: false,
  logger: Logger.new($stdout)
)

Parameters:

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

    Configuration options

Options Hash (options):

  • :bearer_token (String)

    Bearer token for Authorization header

  • :basic_auth (Hash)

    Basic authentication credentials with :user and :password keys

  • :timeout (Integer)

    Request timeout in seconds (default: 4)

  • :max_redirects (Integer)

    Maximum number of redirects to follow (default: 3)

  • :allow_cross_origin_redirects (Boolean)

    Allow redirects to different origins (default: true)

  • :forward_auth_on_cross_origin_redirects (Boolean)

    Forward auth headers on cross-origin redirects (default: false, security risk if enabled)

  • :follow_non_get_redirects (Boolean)

    Follow redirects for POST/PUT/PATCH/DELETE (default: false, only 307/308 supported)

  • :logger (Logger)

    Custom logger instance (default: NullLogger)

Raises:

  • (RuntimeError)

    If disable_timeout or negative timeout is provided



74
75
76
77
78
79
# File 'lib/api_adaptor/json_client.rb', line 74

def initialize(options = {})
  raise "It is no longer possible to disable the timeout." if options[:disable_timeout] || options[:timeout].to_i.negative?

  @logger = options[:logger] || NullLogger.new
  @options = options
end

Instance Attribute Details

#loggerLogger, Hash

Returns:

  • (Logger)

    Logger instance for request/response logging

  • (Hash)

    Client configuration options



46
47
48
# File 'lib/api_adaptor/json_client.rb', line 46

def logger
  @logger
end

#optionsLogger, Hash

Returns:

  • (Logger)

    Logger instance for request/response logging

  • (Hash)

    Client configuration options



46
47
48
# File 'lib/api_adaptor/json_client.rb', line 46

def options
  @options
end

Class Method Details

.default_request_headersHash

Returns default HTTP headers for all requests

Returns:

  • (Hash)

    Default headers including Accept and User-Agent



84
85
86
87
88
89
# File 'lib/api_adaptor/json_client.rb', line 84

def self.default_request_headers
  {
    "Accept" => "application/json",
    "User-Agent" => "#{Variables.app_name}/#{Variables.app_version} (#{Variables.app_contact})"
  }
end

.default_request_with_json_body_headersHash

Returns default headers for requests with JSON body

Returns:

  • (Hash)

    Default headers plus Content-Type: application/json



94
95
96
# File 'lib/api_adaptor/json_client.rb', line 94

def self.default_request_with_json_body_headers
  default_request_headers.merge(json_body_headers)
end

.json_body_headersHash

Returns Content-Type header for JSON requests

Returns:

  • (Hash)

    Content-Type header



101
102
103
104
105
# File 'lib/api_adaptor/json_client.rb', line 101

def self.json_body_headers
  {
    "Content-Type" => "application/json"
  }
end

Instance Method Details

#delete_json(url, params = {}, additional_headers = {}) ⇒ Response

Performs a DELETE request with optional JSON body

Parameters:

  • url (String)

    The URL to request

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

    Optional data to send as JSON in request body (default: {})

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

    Additional HTTP headers to include

Returns:

  • (Response)

    Response object with parsed JSON

Raises:



219
220
221
# File 'lib/api_adaptor/json_client.rb', line 219

def delete_json(url, params = {}, additional_headers = {})
  do_json_request(:delete, url, params, additional_headers)
end

#get_json(url, additional_headers = {}) {|response| ... } ⇒ Response, Object

Performs a GET request and parses the JSON response

Examples:

Basic usage

response = client.get_json("https://api.example.com/users")
users = response["data"]

With custom response class

users = client.get_json("https://api.example.com/users") do |r|
  UserListResponse.new(r)
end

Parameters:

  • url (String)

    The URL to request

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

    Additional HTTP headers to include

Yields:

  • (response)

    Optional block to create custom response object

Yield Parameters:

  • response (RestClient::Response)

    The raw HTTP response

Yield Returns:

  • (Object)

    Custom response object

Returns:

  • (Response, Object)

    Response object or custom object from block

Raises:



161
162
163
# File 'lib/api_adaptor/json_client.rb', line 161

def get_json(url, additional_headers = {}, &create_response)
  do_json_request(:get, url, nil, additional_headers, &create_response)
end

#get_raw(url) ⇒ RestClient::Response

Performs a GET request and returns the raw response (alias for get_raw!)

Parameters:

  • url (String)

    The URL to request

Returns:

  • (RestClient::Response)

    Raw HTTP response

See Also:



136
137
138
# File 'lib/api_adaptor/json_client.rb', line 136

def get_raw(url)
  get_raw!(url)
end

#get_raw!(url) ⇒ RestClient::Response

Performs a GET request and returns the raw response

Parameters:

  • url (String)

    The URL to request

Returns:

  • (RestClient::Response)

    Raw HTTP response

Raises:



125
126
127
# File 'lib/api_adaptor/json_client.rb', line 125

def get_raw!(url)
  do_raw_request(:get, url)
end

#patch_json(url, params, additional_headers = {}) ⇒ Response

Performs a PATCH request with JSON body

Parameters:

  • url (String)

    The URL to request

  • params (Hash)

    Data to send as JSON in request body

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

    Additional HTTP headers to include

Returns:

  • (Response)

    Response object with parsed JSON

Raises:



206
207
208
# File 'lib/api_adaptor/json_client.rb', line 206

def patch_json(url, params, additional_headers = {})
  do_json_request(:patch, url, params, additional_headers)
end

#post_json(url, params = {}, additional_headers = {}) ⇒ Response

Performs a POST request with JSON body

Examples:

response = client.post_json("https://api.example.com/users", {
  name: "Alice",
  email: "[email protected]"
})

Parameters:

  • url (String)

    The URL to request

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

    Data to send as JSON in request body (default: {})

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

    Additional HTTP headers to include

Returns:

  • (Response)

    Response object with parsed JSON

Raises:



180
181
182
# File 'lib/api_adaptor/json_client.rb', line 180

def post_json(url, params = {}, additional_headers = {})
  do_json_request(:post, url, params, additional_headers)
end

#post_multipart(url, params) ⇒ Response

Performs a POST request with multipart/form-data

Examples:

Uploading a file

client.post_multipart("https://api.example.com/upload", {
  file: File.open("image.jpg", "rb"),
  description: "Profile photo"
})

Parameters:

  • url (String)

    The URL to request

  • params (Hash)

    Multipart form data (may include file uploads)

Returns:



235
236
237
238
# File 'lib/api_adaptor/json_client.rb', line 235

def post_multipart(url, params)
  r = do_raw_request(:post, url, params.merge(multipart: true))
  Response.new(r)
end

#put_json(url, params, additional_headers = {}) ⇒ Response

Performs a PUT request with JSON body

Parameters:

  • url (String)

    The URL to request

  • params (Hash)

    Data to send as JSON in request body

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

    Additional HTTP headers to include

Returns:

  • (Response)

    Response object with parsed JSON

Raises:



193
194
195
# File 'lib/api_adaptor/json_client.rb', line 193

def put_json(url, params, additional_headers = {})
  do_json_request(:put, url, params, additional_headers)
end

#put_multipart(url, params) ⇒ Response

Performs a PUT request with multipart/form-data

Parameters:

  • url (String)

    The URL to request

  • params (Hash)

    Multipart form data (may include file uploads)

Returns:



246
247
248
249
# File 'lib/api_adaptor/json_client.rb', line 246

def put_multipart(url, params)
  r = do_raw_request(:put, url, params.merge(multipart: true))
  Response.new(r)
end