Class: Mailkube::Config
- Inherits:
-
Object
- Object
- Mailkube::Config
- Defined in:
- lib/mailkube/config.rb,
sig/mailkube/config.rbs
Overview
Resolved client configuration: the key, the origin, the timeout and the default headers.
This is the only place configuration is read, and the only place a URL is built. Keeping the origin guard here rather than in a resource protects every future link-following feature for free. Instances are frozen: a client that cannot be reconfigured after construction is a client that cannot develop a concurrency bug.
Constant Summary collapse
- ENV_API_KEY =
Environment variable holding the API key.
"MAILKUBE_API_KEY"- ENV_BASE_URL =
Environment variable overriding the API base URL.
"MAILKUBE_BASE_URL"- DEFAULT_TIMEOUT =
Per-request timeout in seconds when the caller does not set one.
30
Instance Attribute Summary collapse
-
#base_url ⇒ String
readonly
The resolved API base URL, always ending in a slash.
-
#timeout ⇒ Integer, Float
readonly
The per-request timeout in seconds.
Instance Method Summary collapse
-
#build_url(path, params = {}) ⇒ String
Join a relative path onto the base URL, attach the query, and refuse any absolute URL off the base URL's origin.
-
#default_headers ⇒ Hash{String => String}
The auth and non-browser identification headers sent on every request.
-
#initialize(api_key: nil, base_url: nil, timeout: DEFAULT_TIMEOUT, user_agent_suffix: nil) ⇒ Config
constructor
Resolve configuration from the arguments, then the environment, then the defaults.
-
#user_agent ⇒ String
This gem's token, plus any suffix a wrapping tool supplied.
Constructor Details
#initialize(api_key: nil, base_url: nil, timeout: DEFAULT_TIMEOUT, user_agent_suffix: nil) ⇒ Config
Resolve configuration from the arguments, then the environment, then the defaults.
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/mailkube/config.rb', line 36 def initialize(api_key: nil, base_url: nil, timeout: DEFAULT_TIMEOUT, user_agent_suffix: nil) key = api_key || ENV.fetch(ENV_API_KEY, nil) raise ConfigurationError, "no API key provided: pass api_key: or set #{ENV_API_KEY}" if key.nil? || key.empty? @api_key = key @base_url = base_url || ENV.fetch(ENV_BASE_URL, nil) || Mailkube::DEFAULT_BASE_URL @timeout = timeout suffix = user_agent_suffix.to_s.strip # Dropped rather than sanitized: a header value that could split the request is not one this # gem will send, and silently repairing it hides the caller's bug. @user_agent_suffix = suffix.match?(/[\r\n]/) ? "" : suffix freeze end |
Instance Attribute Details
#base_url ⇒ String (readonly)
Returns the resolved API base URL, always ending in a slash.
24 25 26 |
# File 'lib/mailkube/config.rb', line 24 def base_url @base_url end |
#timeout ⇒ Integer, Float (readonly)
Returns the per-request timeout in seconds.
26 27 28 |
# File 'lib/mailkube/config.rb', line 26 def timeout @timeout end |
Instance Method Details
#build_url(path, params = {}) ⇒ String
Join a relative path onto the base URL, attach the query, and refuse any absolute URL off the base URL's origin.
Every request carries the Authorization header, so following a link that names a foreign host would hand that host the API key.
The query is attached after the origin check and only when there is one, so an absolute
page link the API issued keeps its own query untouched and an unfiltered listing produces no
? at all. URI.encode_www_form — not Serialization.escape_segment — is correct here: a
space in a query value is +, and a space in a path segment is %20.
93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/mailkube/config.rb', line 93 def build_url(path, params = {}) base = URI.parse(@base_url) resolved = base.merge(path) unless resolved.scheme == base.scheme && resolved.host == base.host && resolved.port == base.port raise ConfigurationError, "refusing to follow #{resolved}: it is not on the configured API origin" end resolved.query = URI.encode_www_form(params) unless params.empty? resolved.to_s rescue URI::InvalidURIError, URI::InvalidComponentError => e raise ConfigurationError, "invalid URL #{path.inspect}: #{e.}" end |
#default_headers ⇒ Hash{String => String}
The auth and non-browser identification headers sent on every request.
The User-Agent is required: the API rejects a request without one. It reports Mailkube::VERSION, which the gemspec also reads, so it cannot drift from the released version.
57 58 59 60 61 62 63 64 |
# File 'lib/mailkube/config.rb', line 57 def default_headers { "Authorization" => "Bearer #{@api_key}", "User-Agent" => user_agent, "Content-Type" => "application/json", "Accept" => "application/json" } end |
#user_agent ⇒ String
This gem's token, plus any suffix a wrapping tool supplied.
The SDK token always leads, so attribution of the SDK itself never depends on what the wrapper chose to call itself.
72 73 74 75 |
# File 'lib/mailkube/config.rb', line 72 def user_agent agent = "mailkube-ruby/#{VERSION}" @user_agent_suffix.empty? ? agent : "#{agent} #{@user_agent_suffix}" end |