Class: ApolloDeploySignalSdkRails::Transport

Inherits:
Object
  • Object
show all
Defined in:
lib/apollo_deploy_signal_sdk_rails/transport.rb

Overview

HTTP transport layer built on Faraday.

Defined Under Namespace

Classes: SSEParser

Constant Summary collapse

RETRYABLE_METHODS =
%i[get head options put delete].freeze
RETRYABLE_STATUSES =
[408, 425, 429, 500, 502, 503, 504].freeze
MAX_RETRIES =
8
MAX_RETRY_DELAY =
30.0
MAX_RESPONSE_BODY_BYTES =
5 * 1024 * 1024
MAX_SSE_LINE_BYTES =
1024 * 1024
"!#$%&'()*+-./:<=>?@[]^_`{|}~".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Transport

Returns a new instance of Transport.



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

def initialize(config)
  @config = config
  base_uri = URI.parse(config.base_url)
  unless base_uri.is_a?(URI::HTTP) && base_uri.host
    raise ArgumentError, "base_url must be an absolute HTTP(S) URL"
  end
  @base_query_pairs = URI.decode_www_form(base_uri.query.to_s)
  base_uri.query = nil
  base_uri.fragment = nil
  base_path = base_uri.path.to_s.sub(%r{/+\z}, "")
  base_uri.path = base_path.empty? ? "/" : "#{base_path}/"
  @connection = Faraday.new(url: base_uri.to_s) do |faraday|
    faraday.request :json
    faraday.response :raise_error
    faraday.options.timeout = config.timeout
    faraday.options.open_timeout = [config.timeout / 3.0, 2.0].max
    faraday.headers["Accept"] = "application/json"
    faraday.headers["User-Agent"] = "apollo-deploy-signal-sdk-rails-ruby-sdk/4.0.1"
    config.default_headers.each { |key, value| faraday.headers[key] = value }
    faraday.adapter Faraday.default_adapter
  end
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



153
154
155
# File 'lib/apollo_deploy_signal_sdk_rails/transport.rb', line 153

def config
  @config
end

#connectionObject (readonly)

Returns the value of attribute connection.



154
155
156
# File 'lib/apollo_deploy_signal_sdk_rails/transport.rb', line 154

def connection
  @connection
end

Class Method Details



485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/apollo_deploy_signal_sdk_rails/transport.rb', line 485

def self.encode_cookie_component(value)
  value.to_s.bytes.map do |byte|
    character = byte.chr
    if (byte >= 0x30 && byte <= 0x39) ||
        (byte >= 0x41 && byte <= 0x5A) ||
        (byte >= 0x61 && byte <= 0x7A) ||
        COOKIE_SAFE_CHARACTERS.include?(character)
      character
    else
      format("%%%02X", byte)
    end
  end.join
end

Instance Method Details

#request(method:, path:, path_params: {}, query: nil, body: nil, headers: {}, content_type: nil, timeout_ms: nil) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/apollo_deploy_signal_sdk_rails/transport.rb', line 179

def request(method:, path:, path_params: {}, query: nil, body: nil, headers: {}, content_type: nil, timeout_ms: nil)
  url = append_query(build_url(path, path_params), build_query(query))
  method = method.to_sym
  max_retries = [[(@config.retries[:attempts] || 3).to_i, 0].max, MAX_RETRIES].min
  attempt = 0

  begin
    request_headers = build_headers(headers, content_type)
    prepared_body, request_headers = prepare_request_body(
      body,
      content_type,
      request_headers,
    )
    response = @connection.run_request(
      method,
      url,
      prepared_body,
      request_headers,
    ) do |request|
      apply_timeout(request, timeout_ms)
    end
    parse_response(response)
  rescue Faraday::Error => error
    mapped = map_error(error, method: method, path: path)
    unless retryable_request?(method, headers) && mapped.retryable? && attempt < max_retries
      raise mapped
    end

    sleep(retry_delay(error, attempt))
    attempt += 1
    retry
  end
end

#stream(method:, path:, path_params: {}, query: nil, body: nil, headers: {}, content_type: nil, timeout_ms: nil) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/apollo_deploy_signal_sdk_rails/transport.rb', line 213

def stream(method:, path:, path_params: {}, query: nil, body: nil, headers: {}, content_type: nil, timeout_ms: nil)
  Enumerator.new do |output|
    url = append_query(build_url(path, path_params), build_query(query))
    parser = SSEParser.new(output)
    stream_headers = build_headers(headers, content_type)
    set_header(stream_headers, "Accept", "text/event-stream")
    prepared_body, stream_headers = prepare_request_body(
      body,
      content_type,
      stream_headers,
    )
    @connection.run_request(
      method.to_sym,
      url,
      prepared_body,
      stream_headers
    ) do |request|
      apply_timeout(request, timeout_ms)
      request.options.on_data = proc { |chunk, _bytes| parser.write(chunk) }
    end
    parser.finish
  rescue Faraday::Error => error
    raise map_error(error, method: method, path: path)
  end
end