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.
-
#process_from_url(location, callback: nil, metadata: nil) ⇒ Scanii::ProcessingResult
Submit a remote URL 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.
-
#retrieve_trace(id) ⇒ Scanii::TraceResult?
Retrieve the processing event trace for a previously submitted scan.
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.
266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/scanii/client.rb', line 266 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.
295 296 297 298 299 300 301 |
# File 'lib/scanii/client.rb', line 295 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.
255 256 257 258 259 260 |
# File 'lib/scanii/client.rb', line 255 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 |
#process_from_url(location, callback: nil, metadata: nil) ⇒ Scanii::ProcessingResult
Submit a remote URL for synchronous scanning.
Sends the URL as a location field in a multipart/form-data POST to /files. The Scanii server fetches and scans the URL synchronously and returns a ProcessingResult. This is distinct from #fetch, which submits to /files/fetch for asynchronous server-side fetching.
location must be a String URL. This matches the existing #fetch String-URL convention and the Java reference (processFromUrl(String)).
This is a v2.2 preview surface; the API shape may shift before it is marked stable.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/scanii/client.rb', line 225 def process_from_url(location, callback: nil, metadata: nil) raise ArgumentError, "location must not be empty" if location.nil? || location.to_s.empty? fields = build_text_fields(, callback) fields["location"] = location.to_s boundary = Multipart.make_boundary body = String.new(encoding: Encoding::BINARY) fields.each do |name, value| body << "--#{boundary}\r\n".b body << "Content-Disposition: form-data; name=\"#{name}\"\r\n".b body << "Content-Type: text/plain; charset=UTF-8\r\n\r\n".b body << value.to_s.b body << "\r\n".b end body << "--#{boundary}--\r\n".b status, resp_body, headers = post( "/files", body: body, content_type: Multipart.make_content_type(boundary) ) raise_for_status(status, resp_body, headers) unless status == 201 ProcessingResult.from_response(resp_body, headers) 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.
283 284 285 286 287 288 289 |
# File 'lib/scanii/client.rb', line 283 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 |
#retrieve_trace(id) ⇒ Scanii::TraceResult?
Retrieve the processing event trace for a previously submitted scan.
Returns nil when no trace exists for the given id (HTTP 404).
This is a v2.2 preview surface; the API shape may shift before it is marked stable.
197 198 199 200 201 202 203 204 205 |
# File 'lib/scanii/client.rb', line 197 def retrieve_trace(id) raise ArgumentError, "id must not be empty" if id.nil? || id.empty? status, resp_body, headers = request("GET", "/files/#{url_encode(id)}/trace") return nil if status == 404 raise_for_status(status, resp_body, headers) unless status == 200 TraceResult.from_response(resp_body, headers) end |