Class: Infrawrench::Transport

Inherits:
Object
  • Object
show all
Defined in:
lib/infrawrench/transport.rb,
sig/infrawrench/sdk.rbs

Overview

Request plumbing shared by every namespace.

The generated namespace classes each hold one of these; reach for APIV1Client instead unless you need the resolved #base_url.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_url: nil, api_key: nil, org_id: nil, headers: {}, timeout: nil, open_timeout: nil, http_handler: nil) ⇒ Transport

Returns a new instance of Transport.

Parameters:

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

    Base URL of the deployment. Defaults to the production API.

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

    API key or WorkOS access token, sent as Authorization: Bearer <key>.

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

    Default organization id, filled in for every org-scoped call.

  • headers (Hash{String => String}) (defaults to: {})

    Headers merged into every request. Per-call headers win.

  • timeout (Numeric, nil) (defaults to: nil)

    Read timeout in seconds. Net::HTTP's default when nil.

  • open_timeout (Numeric, nil) (defaults to: nil)

    Connect timeout in seconds.

  • http_handler (#call, nil) (defaults to: nil)

    Replaces the network call entirely. Receives (URI, Net::HTTPRequest) and must return something that answers code, body and []. This is the seam for tests and for routing through a pre-configured connection pool.



130
131
132
133
134
135
136
137
138
139
# File 'lib/infrawrench/transport.rb', line 130

def initialize(base_url: nil, api_key: nil, org_id: nil, headers: {}, timeout: nil,
               open_timeout: nil, http_handler: nil)
  @base_url = (base_url || DEFAULT_BASE_URL).sub(%r{/+\z}, "")
  @api_key = api_key
  @defaults = SCOPE_PARAM.nil? ? {} : { SCOPE_PARAM => org_id }
  @headers = headers.transform_keys(&:to_s)
  @timeout = timeout
  @open_timeout = open_timeout
  @http_handler = http_handler
end

Instance Attribute Details

#base_urlString (readonly)

Returns Normalized base URL, without a trailing slash.

Returns:

  • (String)

    Normalized base URL, without a trailing slash.



118
119
120
# File 'lib/infrawrench/transport.rb', line 118

def base_url
  @base_url
end

Instance Method Details

#request(http_method:, path:, path_params: nil, query: nil, body: nil, form: nil, form_files: [], accept: :json, request_options: nil) ⇒ Object?

Perform one call. The generated methods are thin wrappers around this.

Parameters:

  • http_method (String)

    Uppercase verb.

  • path (String)

    URL template with {param} placeholders.

  • path_params (Hash{String => Object}, nil) (defaults to: nil)

    Values for those placeholders, by wire name.

  • query (Hash{String => Object}, nil) (defaults to: nil)

    Query parameters; nil values are dropped, Arrays repeat.

  • body (Object, nil) (defaults to: nil)

    JSON request body. Omitted when nil.

  • form (Hash{String => Object}, nil) (defaults to: nil)

    multipart/form-data fields. Mutually exclusive with body.

  • form_files (Array<String>) (defaults to: [])

    Which form fields are file parts rather than scalars.

  • accept (Symbol) (defaults to: :json)

    :json, :binary or :empty — what the endpoint returns.

  • request_options (Hash, nil) (defaults to: nil)

    Per-call :headers, :timeout, :open_timeout.

Returns:

  • (Object, nil)

    Parsed JSON, raw bytes, or nil.

Raises:



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/infrawrench/transport.rb', line 155

def request(http_method:, path:, path_params: nil, query: nil, body: nil, form: nil,
            form_files: [], accept: :json, request_options: nil)
  options = request_options || {}
  url = "#{@base_url}#{resolve_path(http_method, path, path_params)}#{serialize_query(query)}"
  uri = URI.parse(url)

  request_class = METHOD_CLASSES.fetch(http_method)
  req = request_class.new(uri)
  req["accept"] = accept == :binary ? "application/octet-stream" : "application/json"
  @headers.each { |name, value| req[name] = value }
  (options[:headers] || {}).each { |name, value| req[name.to_s] = value }
  req["authorization"] = "Bearer #{@api_key}" unless @api_key.nil? || @api_key.empty?

  if form
    boundary = SecureRandom.hex(16)
    req["content-type"] = "multipart/form-data; boundary=#{boundary}"
    req.body = encode_multipart(form, form_files, boundary)
  elsif !body.nil?
    req["content-type"] = "application/json"
    req.body = JSON.generate(body)
  end

  response = perform(uri, req, options)
  status = response.code.to_i
  raise build_error(response, status, http_method, url) unless (200..299).cover?(status)

  decode(response, status, accept)
end