Class: Scanii::Client
- Inherits:
-
Object
- Object
- Scanii::Client
- Defined in:
- lib/scanii/client.rb
Overview
Synchronous client for the Scanii REST API v2.2.
Construct with either key: + secret: (HTTP Basic Auth) or token: (auth-token authentication). Mixing the two raises ArgumentError.
Per SDK Principle 3 the client is integration-only: it does not retry, batch, or paginate. Each public method maps to exactly one HTTP request.
Constant Summary collapse
- DEFAULT_ENDPOINT =
"https://api.scanii.com".freeze
- DEFAULT_TIMEOUT =
60- API_VERSION_PATH =
"/v2.2".freeze
- USER_AGENT =
"scanii-ruby/#{Scanii::VERSION}".freeze
Instance Attribute Summary collapse
-
#endpoint ⇒ Object
readonly
Returns the value of attribute endpoint.
-
#timeout ⇒ Object
readonly
Returns the value of attribute timeout.
-
#user_agent ⇒ Object
readonly
Returns the value of attribute user_agent.
Instance Method Summary collapse
-
#create_auth_token(timeout_seconds) ⇒ Scanii::AuthToken
Mint a short-lived auth token.
-
#delete_auth_token(id) ⇒ Boolean
Revoke an auth token.
-
#fetch(url, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Ask Scanii to download a remote URL and scan it asynchronously.
-
#initialize(key: nil, secret: nil, token: nil, endpoint: DEFAULT_ENDPOINT, timeout: DEFAULT_TIMEOUT, user_agent: nil) ⇒ Client
constructor
A new instance of Client.
-
#ping ⇒ Boolean
Verify that the configured credentials reach the API.
-
#process(io, filename:, content_type: nil, metadata: nil, callback: nil) ⇒ Scanii::ProcessingResult
Submit an IO-like object for synchronous scanning.
-
#process_async(io, filename:, content_type: nil, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Submit an IO-like object for server-side asynchronous scanning.
-
#process_async_file(file_path, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Submit a file path for server-side asynchronous scanning.
-
#process_file(file_path, metadata: nil, callback: nil) ⇒ Scanii::ProcessingResult
Submit a file path for synchronous scanning.
-
#retrieve(id) ⇒ Scanii::ProcessingResult
Retrieve a previously submitted scan result by id.
-
#retrieve_auth_token(id) ⇒ Scanii::AuthToken
Inspect a previously created auth token.
Constructor Details
#initialize(key: nil, secret: nil, token: nil, endpoint: DEFAULT_ENDPOINT, timeout: DEFAULT_TIMEOUT, user_agent: nil) ⇒ Client
Returns a new instance of Client.
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/scanii/client.rb', line 37 def initialize(key: nil, secret: nil, token: nil, endpoint: DEFAULT_ENDPOINT, timeout: DEFAULT_TIMEOUT, user_agent: nil) @auth_header = build_auth_header(key, secret, token) @endpoint = endpoint.to_s.sub(%r{/+\z}, "") raise ArgumentError, "endpoint must not be empty" if @endpoint.empty? @base_uri = URI.parse("#{@endpoint}#{API_VERSION_PATH}") raise ArgumentError, "endpoint must be http(s)" unless %w[http https].include?(@base_uri.scheme) @timeout = Integer(timeout) @user_agent = user_agent && !user_agent.empty? ? "#{user_agent} #{USER_AGENT}" : USER_AGENT end |
Instance Attribute Details
#endpoint ⇒ Object (readonly)
Returns the value of attribute endpoint.
29 30 31 |
# File 'lib/scanii/client.rb', line 29 def endpoint @endpoint end |
#timeout ⇒ Object (readonly)
Returns the value of attribute timeout.
29 30 31 |
# File 'lib/scanii/client.rb', line 29 def timeout @timeout end |
#user_agent ⇒ Object (readonly)
Returns the value of attribute user_agent.
29 30 31 |
# File 'lib/scanii/client.rb', line 29 def user_agent @user_agent end |
Instance Method Details
#create_auth_token(timeout_seconds) ⇒ Scanii::AuthToken
Mint a short-lived auth token. timeout_seconds must be positive.
202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/scanii/client.rb', line 202 def create_auth_token(timeout_seconds) ts = Integer(timeout_seconds) raise ArgumentError, "timeout_seconds must be positive" if ts <= 0 status, resp_body, headers = post( "/auth/tokens", body: URI.encode_www_form("timeout" => ts), content_type: "application/x-www-form-urlencoded" ) raise_for_status(status, resp_body, headers) unless [200, 201].include?(status) AuthToken.from_response(resp_body, headers) end |
#delete_auth_token(id) ⇒ Boolean
Revoke an auth token.
231 232 233 234 235 236 237 |
# File 'lib/scanii/client.rb', line 231 def delete_auth_token(id) raise ArgumentError, "id must not be empty" if id.nil? || id.empty? status, resp_body, headers = request("DELETE", "/auth/tokens/#{url_encode(id)}") raise_for_status(status, resp_body, headers) unless status == 204 true end |
#fetch(url, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Ask Scanii to download a remote URL and scan it asynchronously.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/scanii/client.rb', line 159 def fetch(url, metadata: nil, callback: nil) raise ArgumentError, "url must not be empty" if url.nil? || url.empty? form = { "location" => url } form["callback"] = callback if callback && !callback.empty? ( || {}).each { |k, v| form["metadata[#{k}]"] = v.to_s } status, resp_body, headers = post( "/files/fetch", body: URI.encode_www_form(form), content_type: "application/x-www-form-urlencoded" ) raise_for_status(status, resp_body, headers) unless status == 202 PendingResult.from_response(resp_body, headers) end |
#ping ⇒ Boolean
Verify that the configured credentials reach the API.
191 192 193 194 195 196 |
# File 'lib/scanii/client.rb', line 191 def ping status, resp_body, headers = request("GET", "/ping") return true if status == 200 raise_for_status(status, resp_body, headers) end |
#process(io, filename:, content_type: nil, metadata: nil, callback: nil) ⇒ Scanii::ProcessingResult
Submit an IO-like object for synchronous scanning.
io is duck-typed: anything responding to read(n) returning a String. Both File (opened with File.open(path, “rb”)) and StringIO work. The body is streamed to the socket; file content is never fully buffered.
Passing a String path is deprecated — use #process_file instead.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/scanii/client.rb', line 67 def process(first_arg, filename: nil, content_type: nil, metadata: nil, callback: nil) if first_arg.is_a?(String) # @deprecated Use {#process_file} instead. Will be removed in a future major version. warn "[DEPRECATION] `Scanii::Client#process(path)` is deprecated; " \ "use `process_file(path)` instead. Will be removed in a future major version." return process_file(first_arg, metadata: , callback: callback) end raise ArgumentError, "io must respond to read" unless first_arg.respond_to?(:read) raise ArgumentError, "filename: is required" if filename.nil? || filename.to_s.empty? fields = build_text_fields(, callback) stream, ct, length = Multipart.stream_encode(fields, first_arg, filename.to_s, content_type) status, resp_body, headers = post("/files", body_stream: stream, content_type: ct, content_length: length) raise_for_status(status, resp_body, headers) unless status == 201 ProcessingResult.from_response(resp_body, headers) end |
#process_async(io, filename:, content_type: nil, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Submit an IO-like object for server-side asynchronous scanning.
Returns a pending id; the final result is delivered to callback (when supplied) or fetched via #retrieve.
Passing a String path is deprecated — use #process_async_file instead.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/scanii/client.rb', line 119 def process_async(first_arg, filename: nil, content_type: nil, metadata: nil, callback: nil) if first_arg.is_a?(String) # @deprecated Use {#process_async_file} instead. Will be removed in a future major version. warn "[DEPRECATION] `Scanii::Client#process_async(path)` is deprecated; " \ "use `process_async_file(path)` instead. Will be removed in a future major version." return process_async_file(first_arg, metadata: , callback: callback) end raise ArgumentError, "io must respond to read" unless first_arg.respond_to?(:read) raise ArgumentError, "filename: is required" if filename.nil? || filename.to_s.empty? fields = build_text_fields(, callback) stream, ct, length = Multipart.stream_encode(fields, first_arg, filename.to_s, content_type) status, resp_body, headers = post("/files/async", body_stream: stream, content_type: ct, content_length: length) raise_for_status(status, resp_body, headers) unless status == 202 PendingResult.from_response(resp_body, headers) end |
#process_async_file(file_path, metadata: nil, callback: nil) ⇒ Scanii::PendingResult
Submit a file path for server-side asynchronous scanning.
Opens the file in binary mode and delegates to #process_async.
147 148 149 150 151 152 153 |
# File 'lib/scanii/client.rb', line 147 def process_async_file(file_path, metadata: nil, callback: nil) assert_readable(file_path) File.open(file_path.to_s, "rb") do |f| process_async(f, filename: File.basename(file_path.to_s), metadata: , callback: callback) end end |
#process_file(file_path, metadata: nil, callback: nil) ⇒ Scanii::ProcessingResult
Submit a file path for synchronous scanning.
Opens the file in binary mode, streams it to Scanii, and closes it. Delegates to #process with filename set to the basename.
96 97 98 99 100 101 |
# File 'lib/scanii/client.rb', line 96 def process_file(file_path, metadata: nil, callback: nil) assert_readable(file_path) File.open(file_path.to_s, "rb") do |f| process(f, filename: File.basename(file_path.to_s), metadata: , callback: callback) end end |
#retrieve(id) ⇒ Scanii::ProcessingResult
Retrieve a previously submitted scan result by id.
179 180 181 182 183 184 185 |
# File 'lib/scanii/client.rb', line 179 def retrieve(id) raise ArgumentError, "id must not be empty" if id.nil? || id.empty? status, resp_body, headers = request("GET", "/files/#{url_encode(id)}") raise_for_status(status, resp_body, headers) unless status == 200 ProcessingResult.from_response(resp_body, headers) end |
#retrieve_auth_token(id) ⇒ Scanii::AuthToken
Inspect a previously created auth token.
219 220 221 222 223 224 225 |
# File 'lib/scanii/client.rb', line 219 def retrieve_auth_token(id) raise ArgumentError, "id must not be empty" if id.nil? || id.empty? status, resp_body, headers = request("GET", "/auth/tokens/#{url_encode(id)}") raise_for_status(status, resp_body, headers) unless status == 200 AuthToken.from_response(resp_body, headers) end |