Class: Angarium::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/angarium/client.rb

Overview

Thin wrapper over HTTPX. Returns a plain result struct so callers/tests never touch HTTPX response objects directly. Note: HTTPX does NOT follow redirects unless the :follow_redirects plugin is enabled, so we intentionally leave it disabled so a 3xx to an internal URL can't bypass SSRF checks.

Defined Under Namespace

Classes: Result

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.connectionObject



43
44
45
46
47
48
49
50
51
# File 'lib/angarium/client.rb', line 43

def self.connection
  HTTPX.with(
    headers: {"user-agent" => Angarium.config.user_agent, "content-type" => "application/json"},
    timeout: {
      connect_timeout: Angarium.config.open_timeout,
      read_timeout: Angarium.config.http_timeout
    }
  )
end

Instance Method Details

#monotonicObject



41
# File 'lib/angarium/client.rb', line 41

def monotonic = Process.clock_gettime(Process::CLOCK_MONOTONIC)

#post(url, body:, headers:, addresses: nil) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/angarium/client.rb', line 13

def post(url, body:, headers:, addresses: nil)
  conn = self.class.connection
  conn = conn.with(addresses: addresses) if addresses && !addresses.empty?

  started = monotonic
  response = conn.post(url, body: body, headers: headers)
  duration = monotonic - started

  if response.is_a?(HTTPX::ErrorResponse)
    return Result.new(success: false,
      error: "#{response.error.class}: #{response.error.message}",
      duration: duration,
      headers: {})
  end

  max = Angarium.config.max_response_body_bytes
  body = response.body.to_s
  body = body.byteslice(0, max) if max

  Result.new(
    success: (200..299).cover?(response.status),
    code: response.status,
    body: body,
    duration: duration,
    headers: response.headers.to_h.transform_keys(&:downcase)
  )
end