class Ecoportal::API::Common::Client
@note
- You can see the documentation of the `HTTP` module in [the repository](https://github.com/httprb/http) - it does `extend` the module `Chainable` ([chainable.rb](https://github.com/httprb/http/blob/master/lib/http/chainable.rb)), - where all the http requests are dev by using `HTTP::Client#request` ([client.rb](https://github.com/httprb/http/blob/master/lib/http/client.rb)) - which calls `build_request` (new `HTTP::Request`) and `perform` (new `HTTP::Connection`) - to return `HTTP::Response` ([response.rb](https://github.com/httprb/http/blob/master/lib/http/response.rb))
@attr_reader logger [Logger] the logger.
Constants
- DELAY_REQUEST_RETRY
Attributes
Public Class Methods
@note the `api_key` will be automatically added as parameter `X-ApiKey` in the header of the http requests. @param api_key [String] the key version to stablish the api connection. @param version [String] it is part of the base url and will determine the api version we query against. @param host [String] api server domain. @param logger [Logger] an object with `Logger` interface to generate logs. @return [Client] an object that holds the configuration of the api connection.
# File lib/ecoportal/api/common/client.rb, line 24 def initialize(api_key:, version: "v1", host: "live.ecoportal.com", logger: nil) @version = version @api_key = api_key @logger = logger @host = host if host.match(/^localhost|^127\.0\.0\.1/) @base_uri = "http://#{host}/api/" else @base_uri = "https://#{host}/api/" end log(:info) { "#{version} client initialized pointing at #{host}" } if @api_key.nil? || @api_key.match(/\A\W*\z/) log(:error) { "Api-key missing!" } end @response_logging_enabled = true end
Public Instance Methods
Creates a HTTP object adding the `X-ApiKey` or `X-ECOPORTAL-API-KEY` param to the header, depending on the API
version. @note It configures HTTP so it only allows body data in json format. @return [HTTP] HTTP object.
# File lib/ecoportal/api/common/client.rb, line 129 def base_request @base_request ||= begin case @version when "v2" HTTP.headers("X-ECOPORTAL-API-KEY" => @api_key).accept(:json) else HTTP.headers("X-ApiKey" => @api_key).accept(:json) end end end
Sends an http `DELETE` request against the api version using `path` to complete the base url. @param path [String] the tail that completes the url of the request. @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 101 def delete(path) instrument("DELETE", path) do request do |http| http.delete(url_for(path)) end end end
Sends an http `GET` request against the api version using `path` to complete the base url, and adding the key_value pairs of `params` in the http header. @param path [String] the tail that completes the url of the request. @param params [Hash] the header paramters of the http request (not including the api key). @option params [String] :page the current page we are requesting with given the `:per_page` offset. @option params [String] :per_page the offset or the number of entries you get per request. @option params [String] :q some text to search. Omit this parameter to target all the entries. @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 62 def get(path, params: {}) instrument("GET", path, params) do request do |http| http.get(url_for(path), params: params) end end end
Logger
interface. @example:
log(:info) {"General information on what's going on"} log(:warn) {"This is a warning that something is likely to have gone amiss"} log(:error) {"Something went wrong"} log(:fatal) {"An unrecoverable error has happend"}
@param level [Symbol] the level that the message should be logged. @yield [] generates the message. @yieldreturn [String] the generated message.
# File lib/ecoportal/api/common/client.rb, line 50 def log(level, &block) logger.send(level, &block) if logger end
Sends an http `PATCH` request against the api version using `path` to complete the base url, and the `data` as a body of the http request. @note it automatically adds the http header param `Content-Type` as `application/json` @param path [String] the tail that completes the url of the request. @param data [String] the body of the query in json format. @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 90 def patch(path, data:) instrument("PATCH", path, data) do request do |http| http.patch(url_for(path), json: data) end end end
Sends an http `POST` request against the api version using `path` to complete the base url, and the `data` as a body of the http request. @note it automatically adds the http header param `Content-Type` as `application/json` @param path [String] the tail that completes the url of the request. @param data [String] the body of the query in json format. @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 76 def post(path, data:) instrument("POST", path, data) do request do |http| http.post(url_for(path), json: data) end end end
Allows to launch a different operation via `block`, providing the basic HTTP connection to the block. @yield [http] launch specific http request. @yieldparam http [HTTP] the http connection. @yieldreturn [Common::Response] the basic custom response object. @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 115 def request wrap_response yield(base_request) end
Full URl builder of the request @param path [String] the tail that completes the url of the request. @return [String] the final url.
# File lib/ecoportal/api/common/client.rb, line 143 def url_for(path) @base_uri+@version+path end
# File lib/ecoportal/api/common/client.rb, line 147 def without_response_logging(&block) begin @response_logging_enabled = false yield self ensure @response_logging_enabled = true end end
Wrap with basic custom object of the gem for responses. @param response [HTTP::Response] @return [Common::Reponse] the basic custom response object.
# File lib/ecoportal/api/common/client.rb, line 122 def wrap_response(response) Ecoportal::API::Common::Response.new(response) end
Private Instance Methods
# File lib/ecoportal/api/common/client.rb, line 158 def instrument(method, path, data = nil, &block) raise "Expected block" unless block start_time = Time.now.to_f log(:info) { "#{method} #{url_for(path)}" } log(:debug) { "Data: #{JSON.pretty_generate(data)}" } with_retry(&block).tap do |result| end_time = Time.now.to_f log(result.success?? :info : :warn) do "Took %.2fs, Status #{result.status}" % (end_time - start_time) end log(result.success?? :debug : :warn) do "Response: #{JSON.pretty_generate(result.body)}" end if @response_logging_enabled end end
Helper to ensure unexpected server errors do not bring client scripts immediately down
# File lib/ecoportal/api/common/client.rb, line 176 def with_retry(attempts = 3, delay = DELAY_REQUEST_RETRY) response = nil attempts.times do |i| response = yield return response unless unexpected_server_error?(response.status) log_unexpected_server_error(response) sleep(delay) if i < attempts end response end