Class: Onetime::Transport
- Inherits:
-
Object
- Object
- Onetime::Transport
- Defined in:
- lib/onetime/transport.rb
Overview
Zero-dependency HTTP transport built on stdlib Net::HTTP.
Responsibilities:
- build the request URL, headers and body (form for v1, JSON for v2)
- apply HTTP Basic auth when credentials are configured
- retry idempotent requests with exponential backoff
- parse the JSON response and map error statuses to exceptions
It intentionally has no knowledge of API versions or resources; callers pass fully-qualified paths (e.g. "/api/v2/secret/conceal").
Constant Summary collapse
- IDEMPOTENT_METHODS =
%i[get head].freeze
- RETRYABLE_STATUSES =
[429, 500, 502, 503, 504].freeze
- RETRYABLE_ERRORS =
[ Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, EOFError, SocketError, IOError, Net::OpenTimeout, Net::ReadTimeout ].freeze
- METHOD_CLASSES =
{ get: Net::HTTP::Get, post: Net::HTTP::Post, patch: Net::HTTP::Patch, put: Net::HTTP::Put, delete: Net::HTTP::Delete, head: Net::HTTP::Head, }.freeze
Class Method Summary collapse
-
.encode_form(hash) ⇒ Object
Encodes a Hash as application/x-www-form-urlencoded, expanding Array values into repeated
key[]=pairs (Rack's array convention, which the v1 API relies on forrecipient).
Instance Method Summary collapse
-
#initialize(config) ⇒ Transport
constructor
A new instance of Transport.
-
#request(method, path, query: nil, body: nil, form: nil, headers: {}, raise_on_error: true) ⇒ Onetime::Response
Execute an HTTP request.
Constructor Details
#initialize(config) ⇒ Transport
Returns a new instance of Transport.
40 41 42 |
# File 'lib/onetime/transport.rb', line 40 def initialize(config) @config = config end |
Class Method Details
.encode_form(hash) ⇒ Object
Encodes a Hash as application/x-www-form-urlencoded, expanding Array
values into repeated key[]= pairs (Rack's array convention, which
the v1 API relies on for recipient).
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/onetime/transport.rb', line 86 def self.encode_form(hash) pairs = [] hash.each do |key, value| next if value.nil? if value.is_a?(Array) value.each { |v| pairs << ["#{key}[]", v.to_s] } else pairs << [key.to_s, value.to_s] end end URI.encode_www_form(pairs) end |
Instance Method Details
#request(method, path, query: nil, body: nil, form: nil, headers: {}, raise_on_error: true) ⇒ Onetime::Response
Execute an HTTP request.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/onetime/transport.rb', line 54 def request(method, path, query: nil, body: nil, form: nil, headers: {}, raise_on_error: true) uri = build_uri(path, query) attempt = 0 begin response = perform(method, uri, body: body, form: form, headers: headers) if response.http_status >= 400 if retryable_status?(response.http_status) && retry_allowed?(method, attempt) attempt += 1 backoff(attempt) raise Retry end raise Errors.from_response(response) if raise_on_error end response rescue Retry retry rescue *RETRYABLE_ERRORS => e if retry_allowed?(method, attempt) attempt += 1 backoff(attempt) retry end raise wrap_transport_error(e) end end |