Class: PoliPage::Client

Inherits:
Object
  • Object
show all
Includes:
Internal::PresignedFetch
Defined in:
lib/poli_page/client.rb,
lib/poli_page/render_to_file.rb

Overview

Main entry point — orchestrates retries, fires hooks, and delegates HTTP execution to ‘PoliPage::Internal::Transport`. The `render` and `documents` resource namespaces hold a reference to this client and delegate request execution back through it.

Thread-safety: configuration is immutable after ‘#initialize`; each request opens its own `Net::HTTP` connection. A single `Client` may be safely shared across threads — build one at boot and reuse it.

Examples:

Construct with defaults

client = PoliPage::Client.new(api_key: ENV.fetch("POLI_PAGE_API_KEY"))

Construct with full configuration

client = PoliPage::Client.new(
  api_key:     ENV.fetch("POLI_PAGE_API_KEY"),
  base_url:    "https://api.example.com",
  max_retries: 3,
  retry_delay: 0.5,                            # seconds
  timeout:     30,                             # seconds
  logger:      Logger.new($stdout),
  on_retry:    ->(e) { metrics.increment("polipage.retry") },
  on_error:    ->(err) { Sentry.capture_exception(err) },
  proxy:       "http://user:pass@proxy.example.com:8080",
  ca_file:     "/etc/ssl/corp-mitm-ca.pem"
)

Behind a corporate egress proxy (env-detected)

# `http_proxy` / `https_proxy` / `no_proxy` env vars are honoured
# automatically — no `proxy:` kwarg needed.
client = PoliPage::Client.new(api_key: ENV.fetch("POLI_PAGE_API_KEY"))

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Internal::PresignedFetch

#fetch_bytes, #stream_bytes

Constructor Details

#initialize(api_key:, base_url: Internal::Constants::DEFAULT_BASE_URL, max_retries: Internal::Constants::DEFAULT_MAX_RETRIES, retry_delay: Internal::Constants::DEFAULT_RETRY_DELAY, timeout: Internal::Constants::DEFAULT_TIMEOUT, logger: nil, on_request: nil, on_response: nil, on_retry: nil, on_error: nil, proxy: nil, ca_file: nil, ca_path: nil) ⇒ Client

Returns a new instance of Client.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/poli_page/client.rb', line 52

def initialize(api_key:, base_url: Internal::Constants::DEFAULT_BASE_URL,
               max_retries: Internal::Constants::DEFAULT_MAX_RETRIES,
               retry_delay: Internal::Constants::DEFAULT_RETRY_DELAY,
               timeout: Internal::Constants::DEFAULT_TIMEOUT,
               logger: nil, on_request: nil, on_response: nil,
               on_retry: nil, on_error: nil,
               proxy: nil, ca_file: nil, ca_path: nil)
  raise InvalidOptionsError, "api_key is required" if api_key.nil? || api_key.empty?

  @api_key     = api_key
  @base_url    = base_url
  @max_retries = max_retries
  @retry_delay = retry_delay
  @timeout     = timeout
  @logger      = logger
  @on_request  = on_request
  @on_response = on_response
  @on_retry    = on_retry
  @on_error    = on_error
  @proxy       = proxy
  @ca_file     = ca_file
  @ca_path     = ca_path
  init_collaborators
end

Instance Attribute Details

#base_urlObject (readonly)

Returns the value of attribute base_url.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def base_url
  @base_url
end

#documentsObject (readonly)

Returns the value of attribute documents.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def documents
  @documents
end

#max_retriesObject (readonly)

Returns the value of attribute max_retries.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def max_retries
  @max_retries
end

#renderObject (readonly)

Returns the value of attribute render.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def render
  @render
end

#retry_delayObject (readonly)

Returns the value of attribute retry_delay.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def retry_delay
  @retry_delay
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



50
51
52
# File 'lib/poli_page/client.rb', line 50

def timeout
  @timeout
end

Instance Method Details

#execute_delete(path) ⇒ 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.

Execute a DELETE request against ‘path`. Returns nil on 2xx; the response body is ignored. Raises `PoliPage::Error` on non-2xx.



110
111
112
113
# File 'lib/poli_page/client.rb', line 110

def execute_delete(path)
  run_with_retry(method: :delete, path: path, body: nil, idempotency_key: nil)
  nil
end

#execute_get(path) ⇒ 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.

Execute a GET request against ‘path`. Returns the parsed snake_case-symbol-keyed Hash on 2xx, or raises a `PoliPage::Error`.



101
102
103
104
# File 'lib/poli_page/client.rb', line 101

def execute_get(path)
  response = run_with_retry(method: :get, path: path, body: nil, idempotency_key: nil)
  parse_json_response(response)
end

#execute_get_raw(path) ⇒ 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.

Execute a GET request and return the raw ‘Internal::Transport::Response` (body + headers) without JSON parsing. Used by `documents.preview` which gets `text/html` directly plus the page count via the `X-Document-Page-Count` response header.



121
122
123
# File 'lib/poli_page/client.rb', line 121

def execute_get_raw(path)
  run_with_retry(method: :get, path: path, body: nil, idempotency_key: nil)
end

#execute_post(path, body:, idempotency_key: nil) ⇒ 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.

Execute a POST request against ‘path` with `body` (snake_case hash; caller’s responsibility to compact nils). Returns the parsed snake_case-symbol-keyed Hash on 2xx, or raises a ‘PoliPage::Error`.



90
91
92
93
94
95
# File 'lib/poli_page/client.rb', line 90

def execute_post(path, body:, idempotency_key: nil)
  wire_body = JSON.generate(Internal::Wire.to_wire(body))
  response = run_with_retry(method: :post, path: path, body: wire_body,
                            idempotency_key: idempotency_key || Internal::UUID.generate)
  parse_json_response(response)
end

#inspectObject Also known as: to_s

Redacted ‘#inspect`. Ruby’s default would dump ‘@api_key` into any `puts client` or exception backtrace — that’s how secrets end up in logs (sdk-ruby-plan.md §10.1 redaction rule).



80
81
82
# File 'lib/poli_page/client.rb', line 80

def inspect
  "#<PoliPage::Client base_url=#{@base_url.inspect} timeout=#{@timeout} max_retries=#{@max_retries}>"
end

#render_to_file(path, **kwargs) ⇒ nil

Render a PDF and stream the bytes straight to ‘path`. Built on `render.pdf_stream`, so memory usage stays bounded regardless of document size. Creates parent directories if missing. Overwrites existing files. On render error the partial file is removed before the error is re-raised.

Examples:

Write a PDF to disk

client.render_to_file(
  "out/welcome.pdf",
  project:  "getting-started",
  template: "welcome",
  version:  "1.0.0",
  data:     { name: "World" }
)

Parameters:

  • path (String, Pathname)
  • kwargs

    forwarded to ‘Resources::Render#pdf_stream`

Returns:

  • (nil)

Raises:



28
29
30
31
32
33
34
35
36
37
# File 'lib/poli_page/render_to_file.rb', line 28

def render_to_file(path, **kwargs)
  pathname = Pathname(path)
  FileUtils.mkdir_p(pathname.dirname) unless pathname.dirname.directory?

  stream_to_path(pathname, kwargs)
  nil
rescue Errno::EACCES, Errno::ENOSPC, Errno::EISDIR, Errno::ENOENT, Errno::EROFS => e
  raise PoliPage::InvalidOptionsError,
        "failed to write to #{pathname}: #{e.class}: #{e.message}"
end