Class: Mirakl::MiraklClient

Inherits:
Object
  • Object
show all
Defined in:
lib/mirakl/mirakl_client.rb

Defined Under Namespace

Classes: FaradayMiraklEncoder, RequestLogContext

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conn = nil) ⇒ MiraklClient

Returns a new instance of MiraklClient.



35
36
37
# File 'lib/mirakl/mirakl_client.rb', line 35

def initialize(conn = nil)
  self.conn = conn || self.class.default_conn
end

Instance Attribute Details

#connObject

Returns the value of attribute conn.



33
34
35
# File 'lib/mirakl/mirakl_client.rb', line 33

def conn
  @conn
end

Class Method Details

.active_clientObject



40
41
42
# File 'lib/mirakl/mirakl_client.rb', line 40

def self.active_client
  Thread.current[:mirakl_client] || default_client
end

.default_clientObject



44
45
46
47
# File 'lib/mirakl/mirakl_client.rb', line 44

def self.default_client
  Thread.current[:mirakl_default_client] ||=
    Mirakl::MiraklClient.new(default_conn)
end

.default_connObject

A default Faraday connection to be used when one isn’t configured. This object should never be mutated, and instead instantiating your own connection and wrapping it in a Mirakl::MiraklClient object should be preferred.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/mirakl/mirakl_client.rb', line 52

def self.default_conn
  # We're going to keep connections around so that we can take advantage
  # of connection re-use, so make sure that we have a separate connection
  # object per thread.
  Thread.current[:mirakl_client_default_conn] ||= begin
    conn = Faraday.new do |builder|
      builder.request :multipart, flat_encode: true
      # builder.use Faraday::Request::Multipart,
      builder.use Faraday::Request::UrlEncoded
      builder.use Faraday::Response::RaiseError

      # Net::HTTP::Persistent doesn't seem to do well on Windows or JRuby,
      # so fall back to default there.
      if Gem.win_platform? || RUBY_PLATFORM == "java"
        builder.adapter :net_http
      else
        builder.adapter :net_http_persistent
      end
    end


    # if Mirakl.verify_ssl_certs
    #   conn.ssl.verify = true
    #   conn.ssl.cert_store = Mirakl.ca_store
    # else
    #   conn.ssl.verify = false
    #
    #   unless @verify_ssl_warned
    #     @verify_ssl_warned = true
    #     warn("WARNING: Running without SSL cert verification. " \
    #       "You should never do this in production. " \
    #       "Execute `Mirakl.verify_ssl_certs = true` to enable " \
    #       "verification.")
    #   end
    # end

    conn
  end
end

Instance Method Details

#execute_request(method, path, api_base: nil, api_key: nil, headers: {}, params: {}) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/mirakl/mirakl_client.rb', line 111

def execute_request(method, path,
                    api_base: nil, api_key: nil, headers: {}, params: {})

  api_base ||= Mirakl.api_base
  api_key ||= Mirakl.api_key
  # params = Util.objects_to_ids(params)

  check_api_key!(api_key)

  body = nil
  query_params = nil
  case method.to_s.downcase.to_sym
  when :get, :head, :delete
    query_params = params
  else
    body = params
  end

  # This works around an edge case where we end up with both query
  # parameters in `query_params` and query parameters that are appended
  # onto the end of the given path. In this case, Faraday will silently
  # discard the URL's parameters which may break a request.
  #
  # Here we decode any parameters that were added onto the end of a path
  # and add them to `query_params` so that all parameters end up in one
  # place and all of them are correctly included in the final request.
  u = URI.parse(path)
  unless u.query.nil?
    query_params ||= {}
    query_params = Hash[URI.decode_www_form(u.query)].merge(query_params)

    # Reset the path minus any query parameters that were specified.
    path = u.path
  end

  headers = request_headers(api_key)
            .update(Util.normalize_headers(headers))

  Util.log_debug("HEADERS:",
                 headers: headers)


  params_encoder = FaradayMiraklEncoder.new
  url = api_url(path, api_base)

  if !body.nil?
    Util.log_debug("BODY:",
                 body: body,
                  bodyencoded: body.to_json)


    body = body.to_json if headers['Content-Type'] == 'application/json'
  end

  # stores information on the request we're about to make so that we don't
  # have to pass as many parameters around for logging.
  context = RequestLogContext.new
  context.api_key         = api_key
  context.body            = body ? body : nil # TODO : Refactor this.
  # context.body            = body ? body : nil
  context.method          = method
  context.path            = path
  context.query_params    = if query_params
                              params_encoder.encode(query_params)
                            end

  # note that both request body and query params will be passed through
  # `FaradayMiraklEncoder`
  http_resp = execute_request_with_rescues(api_base, context) do
    conn.run_request(method, url, body, headers) do |req|

      Util.log_debug("BODYSOUP:",
                     body: body)

      req.options.open_timeout = Mirakl.open_timeout
      req.options.params_encoder = params_encoder
      req.options.timeout = Mirakl.read_timeout
      req.params = query_params unless query_params.nil?
    end
  end

  begin
    resp = MiraklResponse.from_faraday_response(http_resp)
  rescue JSON::ParserError
    raise general_api_error(http_resp.status, http_resp.body)
  end

  # Allows MiraklClient#request to return a response object to a caller.
  @last_response = resp
  [resp, api_key]
end

#requestObject

Executes the API call within the given block. Usage looks like:

client = MiraklClient.new
obj, resp = client.request { ... }


97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/mirakl/mirakl_client.rb', line 97

def request
  @last_response = nil
  old_mirakl_client = Thread.current[:mirakl_client]
  Thread.current[:mirakl_client] = self

  begin
    res = yield
    [res, @last_response]
  ensure
    Thread.current[:mirakl_client] = old_mirakl_client
  end
end