Class: Airtable::ORM::Http::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/airtable/orm/http/client.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key) ⇒ Client

Returns a new instance of Client.



30
31
32
# File 'lib/airtable/orm/http/client.rb', line 30

def initialize(api_key)
  @api_key = api_key
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



10
11
12
# File 'lib/airtable/orm/http/client.rb', line 10

def api_key
  @api_key
end

Class Method Details

.defaultObject

Shared client instance with credential validation. Used by Persistence and Schema to avoid duplicating client/key setup.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/airtable/orm/http/client.rb', line 14

def self.default
  @default ||= begin
    key = ORM.config.api_key
    if key.blank?
      raise Airtable::ORM::Error,
            "Airtable API key is missing. Set api_key via Airtable::ORM.configure."
    end

    new(key)
  end
end

.raise_api_error(status, error) ⇒ Object

Parse an Airtable API error response and raise an ApiError.



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/airtable/orm/http/client.rb', line 70

def self.raise_api_error(status, error)
  type = (error.is_a?(Hash) && error.dig("error", "type")) || "Communication error"
  msg = case error
        when Hash then error.dig("error", "message")
        when String then error
        when NilClass then "invalid or empty response body (not valid JSON)"
        else error.inspect
        end

  raise Airtable::ORM::ApiError.new("HTTP #{status}: #{type}: #{msg.to_s.truncate(200, omission: "")}",
                                    status: status, response: error)
end

.reset!Object



26
27
28
# File 'lib/airtable/orm/http/client.rb', line 26

def self.reset!
  @default = nil
end

Instance Method Details

#api_uriObject



53
54
55
# File 'lib/airtable/orm/http/client.rb', line 53

def api_uri
  @api_uri ||= URI.parse(ORM.config.api_url)
end

#connectionObject



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

def connection
  @connection ||= Faraday.new(url: api_uri, headers: headers) do |builder|
    builder.options.open_timeout = ORM.config.open_timeout
    builder.options.timeout = ORM.config.read_timeout
    # Outermost middleware so its rescue wraps every inner handler and the adapter — maps raw
    # Faraday transport errors to Airtable::ORM::ConnectionError before they leave the client.
    builder.request :airtable_error_handler
    builder.request :json
    builder.request :airtable_rate_limiter, requests_per_second: ORM.config.rate_limit
    builder.response :json
    builder.adapter :net_http_persistent

    if (http_logger = ORM.config.http_logger)
      builder.response :logger, http_logger, bodies: { request: true, response: false }, headers: false,
                                             errors: true, log_level: :debug
    end
  end
end

#escape(string) ⇒ Object



65
66
67
# File 'lib/airtable/orm/http/client.rb', line 65

def escape(string)
  ERB::Util.url_encode(string)
end

#headersObject



57
58
59
60
61
62
63
# File 'lib/airtable/orm/http/client.rb', line 57

def headers
  {
    "Authorization" => "Bearer #{api_key}",
    "Content-Type" => "application/json",
    "User-Agent" => "airtable-orm/#{VERSION}"
  }
end