Class: VoiceML::Transport Private
- Inherits:
-
Object
- Object
- VoiceML::Transport
- Defined in:
- lib/voiceml/transport.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
HTTP transport for the VoiceML REST API.
-
Auth: HTTP Basic with ‘account_sid` (Twilio-format `AC` + 32 hex) as the username and the per-tenant API key as the password. Drop-in compatible with the Twilio SDK constructor.
-
Wire format: requests are form-urlencoded by default (Twilio convention). The server also accepts JSON; pass ‘json: <hash>` to send JSON instead. Responses are always JSON.
-
Retries: 429 + 5xx are retried up to ‘max_retries` times with exponential backoff, honoring the `Retry-After` header when the server emits one.
-
Binary fetch: ‘fetch_bytes` follows the 302 -> S3 redirect that `GET /Recordings/sid.wav` issues when audio has been archived. Callers usually only care about the final bytes.
Constant Summary collapse
- DEFAULT_BASE_URL =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'https://voiceml.voicetel.com'- DEFAULT_TIMEOUT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
30- DEFAULT_MAX_RETRIES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
2- RETRYABLE_STATUSES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
[429, 500, 502, 503, 504].freeze
Instance Attribute Summary collapse
- #account_sid ⇒ Object readonly private
- #base_url ⇒ Object readonly private
- #max_retries ⇒ Object readonly private
- #timeout ⇒ Object readonly private
- #user_agent ⇒ Object readonly private
Class Method Summary collapse
-
.strip_trailing_slashes(s) ⇒ Object
private
Linear-time trailing-slash strip.
Instance Method Summary collapse
-
#close ⇒ Object
private
Close the persistent connection, releasing the underlying socket.
-
#fetch_bytes(path) ⇒ Array(Integer, String, Hash)
private
Fetch a binary payload (audio/wav recordings).
-
#initialize(account_sid:, api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, user_agent: nil, http_client: nil) ⇒ Transport
constructor
private
A new instance of Transport.
-
#request(method, path, params: nil, form: nil, json: nil) ⇒ Hash, ...
private
Perform a request.
Constructor Details
#initialize(account_sid:, api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, user_agent: nil, http_client: nil) ⇒ Transport
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Transport.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/voiceml/transport.rb', line 40 def initialize(account_sid:, api_key:, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, user_agent: nil, http_client: nil) raise ConfigurationError, 'account_sid is required' if account_sid.nil? || account_sid.empty? raise ConfigurationError, 'api_key is required' if api_key.nil? || api_key.empty? raise ConfigurationError, 'max_retries must be >= 0' if max_retries.negative? @account_sid = account_sid @api_key = api_key @base_url = self.class.strip_trailing_slashes(base_url) @timeout = timeout @max_retries = max_retries @user_agent = user_agent || "voiceml-ruby/#{VoiceML::VERSION}" @uri_base = URI.parse(@base_url) @conn_mutex = Mutex.new @owns_client = http_client.nil? @persistent = http_client end |
Instance Attribute Details
#account_sid ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/voiceml/transport.rb', line 38 def account_sid @account_sid end |
#base_url ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/voiceml/transport.rb', line 38 def base_url @base_url end |
#max_retries ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/voiceml/transport.rb', line 38 def max_retries @max_retries end |
#timeout ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/voiceml/transport.rb', line 38 def timeout @timeout end |
#user_agent ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/voiceml/transport.rb', line 38 def user_agent @user_agent end |
Class Method Details
.strip_trailing_slashes(s) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Linear-time trailing-slash strip. Equivalent to ‘base_url.sub(%r/+z, ”)` but without the polynomial-backtracking shape CodeQL flags (`rb/polynomial-redos`).
32 33 34 35 36 |
# File 'lib/voiceml/transport.rb', line 32 def self.strip_trailing_slashes(s) i = s.length i -= 1 while i.positive? && s.getbyte(i - 1) == 47 # '/' i == s.length ? s : s[0, i] end |
Instance Method Details
#close ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Close the persistent connection, releasing the underlying socket. Safe to call multiple times. The transport remains usable — the next request will transparently open a fresh connection.
62 63 64 |
# File 'lib/voiceml/transport.rb', line 62 def close @conn_mutex.synchronize { finish_connection } if @owns_client end |
#fetch_bytes(path) ⇒ Array(Integer, String, Hash)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Fetch a binary payload (audio/wav recordings). Follows the single 302 -> presigned S3 redirect that ‘GET /Recordings/sid.wav` issues when audio has been archived.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/voiceml/transport.rb', line 98 def fetch_bytes(path) uri = build_uri(path, nil) visited = [] loop do raise ApiError.new('too many redirects', status_code: 0) if visited.length > 5 req = Net::HTTP::Get.new(uri) apply_common_headers(req, auth: !visited.any? { |u| u.host != uri.host }) response = send_on_persistent(uri, req) case response when Net::HTTPRedirection visited << uri uri = URI.parse(response['location']) next when Net::HTTPSuccess headers = response.each_header.to_h return [response.code.to_i, response.body || '', headers] else raise_for_response(response) end end end |
#request(method, path, params: nil, form: nil, json: nil) ⇒ Hash, ...
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Perform a request. Pass ‘form:` for a form-urlencoded POST body, `json:` for a JSON body, or neither for a plain GET/DELETE. `params:` are query-string params.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/voiceml/transport.rb', line 71 def request(method, path, params: nil, form: nil, json: nil) uri = build_uri(path, params) attempt = 0 loop do response = perform_request(method, uri, form: form, json: json) if RETRYABLE_STATUSES.include?(response.code.to_i) && attempt < @max_retries sleep(backoff_delay(attempt, response)) attempt += 1 next end return parse_response(response) rescue *transport_errors => e raise ApiError.new("transport error after #{attempt + 1} attempts: #{e.}", status_code: 0) if attempt >= @max_retries sleep(backoff_delay(attempt)) attempt += 1 end end |