chimera_http_client 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f53a50a92fd82daebeae2cad2156dd5a0eef366d4aec27d2ecb13fffe8f771f3
4
- data.tar.gz: ef515b583ba8cbbd76286e626dfbe34cf06662710c04e441f9d4e926577962cb
3
+ metadata.gz: 5e2fa666cf4ec3fe21e1f4a8ecfb3932c5dac1cb6d0c7d16762eea73bf76fb44
4
+ data.tar.gz: df72864e42844dd77dcc9f64bfc23f69d73a66ee66f7589c8ef1e460524b831c
5
5
  SHA512:
6
- metadata.gz: fa715d6646f2f924a67bd0049598156eaacee8b60a81d28858cddf86f8a7e42c2ae50097fd7be824d8d7ff91fd0bc1569713cb014b7e3a1859a634bf9c3d4568
7
- data.tar.gz: '069987a5e71950ba299b313a93f9cb6533adfe275bbda057a076614aeb8d053fc1e574a7db588d75dfc36a7611d10260c6b0ebde9fac274474e5ef85603fe356'
6
+ metadata.gz: 52cd8916ab3bd1956753eac56a54a0c9b6130fdfbb38e9d7f2083b137097e1a585a8d205ad75f6e3b6713ee55cf66c1443b8136c22f7d48c8e0045da397612c5
7
+ data.tar.gz: 70f7a691115d59909ec1831d48ed1fc02f4aa7ce8057bc35cf015a4254ee1f09318b45a20cf30686548d2b0bd686644ac0df6f5f6e9e9c2303b09b5cedfbb611
data/.rubocop.yml CHANGED
@@ -76,6 +76,9 @@ Style/NumericLiterals:
76
76
  Style/Semicolon:
77
77
  AllowAsExpressionSeparator: true
78
78
 
79
+ Style/SymbolProc:
80
+ Enabled: false
81
+
79
82
  # Cop supports --auto-correct.
80
83
  # Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
81
84
  # SupportedStyles: comma, consistent_comma, no_comma
data/README.markdown CHANGED
@@ -1,6 +1,10 @@
1
1
  # ChimeraHttpClient
2
2
 
3
- When starting to split monolithic apps into smaller services, you need an easy way to access the remote data from the other apps. This chimera_http_client gem should serve as a unified way to access endpoints from other apps. And what works for the internal communication between your own apps, will also work for external APIs that do not offer a client for simplified access.
3
+ When starting to split monolithic apps into smaller services, you need an easy way to access the remote data from the other apps. This **chimera_http_client gem** should serve as **a comfortable and unifying way** to access endpoints from other apps.
4
+
5
+ And what works for the internal communication between your own apps, will also work for external APIs that do not offer a client for simplified access.
6
+
7
+ It offers an **easy to learn interface** and **nice error handling**. And it enables you to **queue HTTP requests to run them in parallel** for better performance.
4
8
 
5
9
  ## Dependencies
6
10
 
@@ -8,10 +12,43 @@ The `chimera_http_client` gem is using the _libcurl_ wrapper [**Typhoeus**](http
8
12
 
9
13
  It does not have any other runtime dependencies.
10
14
 
11
- ### optional
15
+ ### ENV variables
12
16
 
13
17
  Setting the environment variable `ENV['CHIMERA_HTTP_CLIENT_LOG_REQUESTS']` to `true` (or `'true'`) will provide more detailed error messages for logging and also add additional information to the Error JSON. It is recommended to use this only in development environments.
14
18
 
19
+ ## Table of Contents
20
+
21
+ <!-- TOC depthFrom:1 depthTo:4 withLinks:1 updateOnSave:0 orderedList:0 -->
22
+
23
+ - [ChimeraHttpClient](#chimerahttpclient)
24
+ - [Table of Contents](#table-of-contents)
25
+ - [Dependencies](#dependencies)
26
+ - [ENV variables](#env-variables)
27
+ - [The Connection class](#the-connection-class)
28
+ - [Initialization](#initialization)
29
+ - [Mandatory initialization parameter `base_url`](#mandatory-initialization-parameter-baseurl)
30
+ - [Optional initialization parameters](#optional-initialization-parameters)
31
+ - [Request methods](#request-methods)
32
+ - [Mandatory request parameter `endpoint`](#mandatory-request-parameter-endpoint)
33
+ - [Optional request parameters](#optional-request-parameters)
34
+ - [Basic auth](#basic-auth)
35
+ - [Timeout duration](#timeout-duration)
36
+ - [Custom logger](#custom-logger)
37
+ - [Caching responses](#caching-responses)
38
+ - [Example usage](#example-usage)
39
+ - [The Request class](#the-request-class)
40
+ - [The Response class](#the-response-class)
41
+ - [Error classes](#error-classes)
42
+ - [The Queue class](#the-queue-class)
43
+ - [Queueing requests](#queueing-requests)
44
+ - [Executing requests in parallel](#executing-requests-in-parallel)
45
+ - [Installation](#installation)
46
+ - [Maintainers and Contributors](#maintainers-and-contributors)
47
+ - [Roadmap](#roadmap)
48
+ - [Chimera](#chimera)
49
+
50
+ <!-- /TOC -->
51
+
15
52
  ## The Connection class
16
53
 
17
54
  The basic usage looks like this:
@@ -21,38 +58,119 @@ connection = ChimeraHttpClient::Connection.new(base_url: 'http://localhost/names
21
58
  response = connection.get!(endpoint, params: params)
22
59
  ```
23
60
 
24
- `ChimeraHttpClient::Connection.new` expects an options hash as parameter. The only required option is **base_url** which should include the host, port and base path to the API endpoints you want to call, e.g.
25
- `base_url: 'http://localhost:3000/v1'`.
61
+ ### Initialization
62
+
63
+ `connection = ChimeraHttpClient::Connection.new(base_url: 'http://localhost:3000/v1', logger: logger, cache: cache)`
64
+
65
+ #### Mandatory initialization parameter `base_url`
66
+
67
+ The mandatory parameter is **base_url** which should include the host, port and base path to the API endpoints you want to call, e.g. `'http://localhost:3000/v1'`.
68
+
69
+ Setting the `base_url` is meant to be a comfort feature, as you can then pass short endpoints to each request like `/users`. You could set an empty string `''` as `base_url` and then pass full qualified URLs as endpoint of the requests.
70
+
71
+ #### Optional initialization parameters
26
72
 
27
- On this connection object, you can call methods like `#get!` or `#post!` with an endpoint and an options hash as parameters, e.g.
28
- `connection.get!("users/#{id}")`
29
- or
30
- `connection.get(['users', id], options: { headers: { ' Accept-Charset' => 'utf-8' })`
73
+ The optional parameters are:
31
74
 
32
- Please take note that _the endpoint can be given as a String, a Symbol, or as an Array._
33
- While they do no harm, there is _no need to pass leading or trailing `/` in endpoints._
34
- When passing the endpoint as an Array, _it's elements are converted to Strings and concatenated with `/`._
35
- On each request _the http-headers can be amended or overwritten_ completely or partially.
75
+ * `logger` - an instance of a logger class that implements `#info` and `#warn` methods
76
+ * `timeout` - the timeout for all requests, can be overwritten in any request, the default are 3 seconds
77
+ * `user_agent` - if you would like your calls to identify with a specific user agent
78
+ * `verbose` - the default is `false`, set it to true while debugging issues
79
+ * `cache` - an instance of your cache solution, can be overwritten in any request
36
80
 
37
- ### Basic auth
81
+ ### Request methods
82
+
83
+ The available methods are:
84
+
85
+ * `get` / `get!`
86
+ * `post` / `post!`
87
+ * `put` / `put`
88
+ * `patch` / `patch!`
89
+ * `delete` / `delete!`
90
+
91
+ where the methods ending on a _bang!_ will raise an error (which you should handle in your application) while the others will return an error object.
92
+
93
+ #### Mandatory request parameter `endpoint`
94
+
95
+ The `base_url` set in the connection will together with the `endpoint` determine the URL to make a request to.
96
+
97
+ ```ruby
98
+ connection.get([:users, id])
99
+ connection.get(["users", id])
100
+ connection.get("users/#{id}")
101
+ connection.get("/users/#{id}")
102
+ ```
38
103
 
39
- In case you need to use an API that is protected by **basic_auth** just pass the credentials in the options hash:
40
- `options: { username: 'admin', password: 'secret' }`
104
+ All forms above ave valid and will make a request to the same URL.
41
105
 
42
- ### Timeout duration
106
+ * Please take note that _the endpoint can be given as a String, a Symbol, or an Array._
107
+ * While they do no harm, there is _no need to pass leading or trailing `/` in endpoints._
108
+ * When passing the endpoint as an Array, _it's elements are converted to Strings and concatenated with `/`._
109
+
110
+ #### Optional request parameters
111
+
112
+ All request methods expect a mandatory `endpoint` and an optional hash as parameters. In the latter the following keywords are treated specially:
113
+
114
+ * `body` - the mandatory body of a `post`, `put` or `patch` request
115
+ * `headers` - a hash of HTTP headers
116
+ * `params` - parameters of a HTTP request
117
+ * `username` - used for a BasicAuth login
118
+ * `password` - used for a BasicAuth login
119
+ * `timeout` - set a custom timeout per request (the default is 3 seconds)
120
+ * `cache` - optionally overwrite the cache store set in `Connection` in any request
121
+
122
+ Example:
123
+
124
+ ```ruby
125
+ connection.post(
126
+ :users,
127
+ body: { name: "Andy" },
128
+ params: { origin: `Twitter`},
129
+ headers: { "Authorization" => "Bearer #{token}" },
130
+ timeout: 10,
131
+ cache: nil
132
+ )
133
+ ```
134
+
135
+ #### Basic auth
136
+
137
+ In case you need to use an API that is protected by **basic_auth** just pass the credentials as optional parameters:
138
+ `username: 'admin', password: 'secret'`
139
+
140
+ #### Timeout duration
43
141
 
44
142
  The default timeout duration is **3 seconds**.
45
143
 
46
144
  If you want to use a different timeout, you can pass the key `timeout` when initializing the `Connection`. You can also overwrite it on every call.
47
145
 
48
- ### Custom logger
146
+ #### Custom logger
49
147
 
50
148
  By default no logging is happening. If you need request logging, you can pass your custom Logger to the key `logger` when initializing the `Connection`. It will write to `logger.info` when starting and when completing a request.
51
149
 
52
- ### Caching responses
150
+ #### Caching responses
53
151
 
54
152
  To cache all the reponses of a connection, just pass the optional parameter `cache` to its initializer. You can also overwrite the connection's cache configuration by passing the parameter `cache` to any `get` call.
55
153
 
154
+ It could be an instance of an implementation as simple as this:
155
+
156
+ ```ruby
157
+ class Cache
158
+ def initialize
159
+ @memory = {}
160
+ end
161
+
162
+ def get(request)
163
+ @memory[request]
164
+ end
165
+
166
+ def set(request, response)
167
+ @memory[request] = response
168
+ end
169
+ end
170
+ ```
171
+
172
+ Or use an adapter for Dalli, Redis, or Rails cache that also support an optional time-to-live `default_ttl` parameter.
173
+
56
174
  Read more about how to use it: https://github.com/typhoeus/typhoeus#caching
57
175
 
58
176
  ### Example usage
@@ -180,6 +298,52 @@ The error classes and their corresponding http error codes:
180
298
  ServerError # 500..599
181
299
  TimeoutError # timeout
182
300
 
301
+ ## The Queue class
302
+
303
+ Instead of making single requests immediately, the ChimeraHttpClient allows to queue requests and run them in **parallel**.
304
+
305
+ The number of parallel requests is limited by your system. There is a hard limit for 200 concurrent requests. You will have to measure yourself where the sweet spot for optimal performance is - and when things start to get flaky. I recommend to queue not much more than 20 requests before running them.
306
+
307
+ ### Queueing requests
308
+
309
+ The initializer of the `Queue` class expects and handles the same parameters as the `Connection` class.
310
+
311
+ ```ruby
312
+ queue = ChimeraHttpClient::Queue.new(base_url: 'http://localhost:3000/v1')
313
+ ```
314
+
315
+ `queue.add` expects and handles the same parameters as the requests methods of a connection.
316
+
317
+ ```ruby
318
+ queue.add(method, endpoint, options = {})
319
+ ```
320
+
321
+ The only difference is that a parameter to set the HTTP method has to prepended. Valid options for `method` are:
322
+
323
+ * `:get` / `'get'` / `'GET'`
324
+ * `:post` / `'post'` / `'POST'`
325
+ * `:put` / `'put'` / `'PUT'`
326
+ * `:patch` / `'patch'` / `'PATCH'`
327
+ * `:delete` / `'delete'` / `'DELETE'`
328
+
329
+ ### Executing requests in parallel
330
+
331
+ Once the queue is filled, run all the requests concurrently with:
332
+
333
+ ```ruby
334
+ responses = queue.execute
335
+ ```
336
+
337
+ `responses` will contain an Array of `ChimeraHttpClient::Response` objects when all calls succeed. If any calls fail, the Array will also contain `ChimeraHttpClient::Error` objects. It is in your responsibility to handle the errors.
338
+
339
+ > Tip: every `Response` and every `Error` make the underlying `Typheous::Request` available over `object.response.request`, which could help with debugging, or with building your own retry mechanism.
340
+
341
+ ### Empty the queue
342
+
343
+ The queue is emptied after execution. You could also empty it at any other point before by calling `queue.empty`.
344
+
345
+ To inspect the requests waiting for execution, call `queue.queued_requests`.
346
+
183
347
  ## Installation
184
348
 
185
349
  Add this line to your application's Gemfile:
@@ -196,7 +360,7 @@ When updating the version, do not forget to run
196
360
 
197
361
  ## Maintainers and Contributors
198
362
 
199
- After checking out the repo, run `rake` to run the **tests and rubocop**.
363
+ After checking out the repo, run `bundle install` and then `bundle execute rake` to run the **tests and rubocop**.
200
364
 
201
365
  You can also run `rake console` to open an irb session with the `ChimeraHttpClient` pre-loaded that will allow you to experiment.
202
366
 
data/Rakefile CHANGED
@@ -5,7 +5,12 @@ RSpec::Core::RakeTask.new(:rspec)
5
5
 
6
6
  desc "Open a console with the ChimeraHttpClient loaded"
7
7
  task :console do
8
- system "irb -r lib/chimera_http_client.rb"
8
+ puts "Console with the gem and awesome_print loaded:"
9
+ ARGV.clear
10
+ require "irb"
11
+ require "ap"
12
+ load "lib/chimera_http_client.rb"
13
+ IRB.start
9
14
  end
10
15
 
11
16
  desc "Run Rubocop"
data/TODO.markdown CHANGED
@@ -15,11 +15,11 @@ _none known_
15
15
 
16
16
  ### Logger
17
17
 
18
- * ~allow to pass a logger~
19
- * ~add logger.info when starting a http call~
20
- * ~add logger.info when finishing a successful http call~
21
- * ~include the total_time of the requests in the log~
22
- * ~add (example) to README~
18
+ * ~~allow to pass a logger~~
19
+ * ~~add logger.info when starting a http call~~
20
+ * ~~add logger.info when finishing a successful http call~~
21
+ * ~~include the total_time of the requests in the log~~
22
+ * ~~add (example) to README~~
23
23
  * add logger.warn / .error for error cases (?)
24
24
 
25
25
  ### Custom Serializer
@@ -35,28 +35,46 @@ _none known_
35
35
  * use custom deserializer in #parsed_body instead of default JSON parsing
36
36
  * add example to README
37
37
 
38
- ### Queueing
38
+ ### Queueing / running in parallel
39
39
 
40
- * allow to queue multiple calls
41
- * execute (up to 10) calls in parallel
40
+ * ~~allow to queue multiple requests~~
41
+ * ~~execute (up to 200) requests in parallel~~
42
+ * allow to pass one proc / block (for all requests) to use as on_complete handler for each request
42
43
  * add example to README
43
44
 
44
- ### Caching
45
+ ### Queueing / run requests serialized
45
46
 
46
- * optional per connection or call
47
+ * allow to queue multiple requests
48
+ * execute (up to 5) queued requests
49
+ * allow to pass a proc (per request) to use the response for the next request
50
+ * or just explain how to code that yourself?
47
51
  * add example to README
48
52
 
53
+ ### Caching
54
+
55
+ * ~~optional per connection or call~~
56
+ * ~~add example to README~~
57
+
49
58
  ### Timeout
50
59
 
51
- * ~allow to set custom timeout per connection~
52
- * ~allow to set custom timeout per call~
53
- * ~add (example) to README~
60
+ * ~~allow to set custom timeout per connection~~
61
+ * ~~allow to set custom timeout per call~~
62
+ * ~~add (example) to README~~
54
63
 
55
64
  ### Release
56
65
 
57
- * ~rename module to have unique namespace~
58
- * ~release to rubygems to add to the plethora of similar gems~
59
- * ~make repo public~
66
+ * ~~rename module to have unique namespace~~
67
+ * ~~release to rubygems to add to the plethora of similar gems~~
68
+ * ~~make repo public~~
60
69
  * hook up Travis-CI
61
70
  * ensure it runs with Ruby 2.4 and newer
62
71
  * get feedback
72
+
73
+ ### File Uploads
74
+
75
+ * add example to README
76
+
77
+ ### Streaming response bodies
78
+
79
+ * enable to pass on_headers, on_body, on_complete procs
80
+ * add example to README
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency "typhoeus", "~> 1.1"
22
22
 
23
+ spec.add_development_dependency "awesome_print", "~> 1.8"
23
24
  spec.add_development_dependency "bundler", "~> 1.13"
24
25
  spec.add_development_dependency "irb", "~> 1.0"
25
26
  spec.add_development_dependency "rake", ">= 10.0"
@@ -0,0 +1,54 @@
1
+ module ChimeraHttpClient
2
+ class Base
3
+ USER_AGENT = "ChimeraHttpClient (by mediafinger)".freeze
4
+
5
+ def initialize(base_url:, logger: nil, timeout: nil, user_agent: USER_AGENT, verbose: false, cache: nil)
6
+ fail(ChimeraHttpClient::ParameterMissingError, "base_url expected, but not given") if base_url.nil?
7
+
8
+ @base_url = base_url
9
+ @logger = logger
10
+ @timeout = timeout
11
+
12
+ Typhoeus::Config.user_agent = user_agent
13
+ Typhoeus::Config.verbose = verbose
14
+ Typhoeus::Config.memoize = false
15
+ Typhoeus::Config.cache = cache
16
+ end
17
+
18
+ private
19
+
20
+ # Add default values to call options
21
+ def augmented_options(options)
22
+ options[:timeout] ||= @timeout
23
+
24
+ options
25
+ end
26
+
27
+ def extract_body(options)
28
+ body = options.delete(:body)
29
+ body_optional = options.delete(:body_optional)
30
+ fail(ChimeraHttpClient::ParameterMissingError, "body expected, but not given") if body.nil? && !body_optional
31
+ body
32
+ end
33
+
34
+ def extract_headers(options, headers)
35
+ given_headers = options.delete(:headers) || {}
36
+ headers.merge(given_headers)
37
+ end
38
+
39
+ def default_headers
40
+ { "Content-Type" => "application/json" }
41
+ end
42
+
43
+ # Build URL out of @base_url and endpoint given as String or Array, while trimming redundant "/"
44
+ def url(endpoint)
45
+ trimmed_endpoint = Array(endpoint).map { |e| trim(e) }
46
+ [@base_url.chomp("/"), trimmed_endpoint].flatten.reject(&:empty?).join("/")
47
+ end
48
+
49
+ # Remove leading and trailing "/" from a give part of a String (usually URL or endpoint)
50
+ def trim(element)
51
+ element.to_s.sub(%r{^\/}, "").chomp("/")
52
+ end
53
+ end
54
+ end
@@ -2,22 +2,11 @@
2
2
  # The bang methods get!, post!, put!, patch! and delete! raise a Error in case of failure
3
3
 
4
4
  module ChimeraHttpClient
5
- class Connection
6
- USER_AGENT = "ChimeraHttpClient (by mediafinger)".freeze
7
-
8
- def initialize(base_url:, logger: nil, timeout: nil, user_agent: USER_AGENT, verbose: false, cache: nil)
9
- fail(ChimeraHttpClient::ParameterMissingError, "base_url expected, but not given") if base_url.nil?
10
-
11
- @base_url = base_url
12
- @logger = logger
13
- @timeout = timeout
5
+ class Connection < Base
6
+ def initialize(options = {})
7
+ super(options)
14
8
 
15
9
  define_bang_methods
16
-
17
- Typhoeus::Config.user_agent = user_agent
18
- Typhoeus::Config.verbose = verbose
19
- Typhoeus::Config.memoize = false
20
- Typhoeus::Config.cache = cache
21
10
  end
22
11
 
23
12
  def request
@@ -25,70 +14,34 @@ module ChimeraHttpClient
25
14
  end
26
15
 
27
16
  def get(endpoint, options = {})
28
- headers = extract_headers(options, default_headers)
29
-
30
- request.run(url: url(endpoint), method: :get, options: augmented_options(options), headers: headers)
17
+ run(:get, endpoint, options.merge(body_optional: true))
31
18
  end
32
19
 
33
20
  def post(endpoint, options = {})
34
- run_with_body(:post, endpoint, options)
21
+ run(:post, endpoint, options)
35
22
  end
36
23
 
37
24
  def put(endpoint, options = {})
38
- run_with_body(:put, endpoint, options)
25
+ run(:put, endpoint, options)
39
26
  end
40
27
 
41
28
  def patch(endpoint, options = {})
42
- run_with_body(:patch, endpoint, options)
29
+ run(:patch, endpoint, options)
43
30
  end
44
31
 
45
32
  def delete(endpoint, options = {})
46
- run_with_body(:delete, endpoint, options.merge(body_optional: true))
33
+ run(:delete, endpoint, options.merge(body_optional: true))
47
34
  end
48
35
 
49
36
  private
50
37
 
51
- # Add default values to call options
52
- def augmented_options(options)
53
- options[:timeout] ||= @timeout
54
-
55
- options
56
- end
57
-
58
- def run_with_body(method, endpoint, options = {})
38
+ def run(method, endpoint, options = {})
59
39
  body = extract_body(options)
60
40
  headers = extract_headers(options, default_headers)
61
41
 
62
42
  request.run(url: url(endpoint), method: method, body: body, options: augmented_options(options), headers: headers)
63
43
  end
64
44
 
65
- # Build URL out of @base_url and endpoint given as String or Array, while trimming redundant "/"
66
- def url(endpoint)
67
- trimmed_endpoint = Array(endpoint).map { |e| trim(e) }
68
- [@base_url.chomp("/"), trimmed_endpoint].flatten.reject(&:empty?).join("/")
69
- end
70
-
71
- # Remove leading and trailing "/" from a give part of a String (usually URL or endpoint)
72
- def trim(element)
73
- element.to_s.sub(%r{^\/}, "").chomp("/")
74
- end
75
-
76
- def extract_body(options)
77
- body = options.delete(:body)
78
- body_optional = options.delete(:body_optional)
79
- fail(ChimeraHttpClient::ParameterMissingError, "body expected, but not given") if body.nil? && !body_optional
80
- body
81
- end
82
-
83
- def extract_headers(options, headers)
84
- given_headers = options.delete(:headers) || {}
85
- headers.merge(given_headers)
86
- end
87
-
88
- def default_headers
89
- { "Content-Type" => "application/json" }
90
- end
91
-
92
45
  # get! post! put! patch! delete! return an Response when successful, but raise an Error otherwise
93
46
  def define_bang_methods
94
47
  {
@@ -0,0 +1,49 @@
1
+ module ChimeraHttpClient
2
+ class Queue < Base
3
+ def add(method, endpoint, options = {})
4
+ http_method = method.downcase.to_sym
5
+ options[:body_optional] = true if %i[get delete].include?(http_method)
6
+
7
+ body = extract_body(options)
8
+ headers = extract_headers(options, default_headers)
9
+
10
+ req = Request.new(logger: @logger).create(
11
+ url: url(endpoint),
12
+ method: http_method,
13
+ body: body,
14
+ options: augmented_options(options),
15
+ headers: headers
16
+ )
17
+
18
+ queued_requests << req
19
+ end
20
+
21
+ def execute
22
+ queued_requests.each do |request|
23
+ hydra.queue(request.request)
24
+ end
25
+
26
+ hydra.run
27
+
28
+ responses = queued_requests.map { |request| request.result }
29
+
30
+ empty
31
+
32
+ responses
33
+ end
34
+
35
+ def empty
36
+ @queued_requests = []
37
+ end
38
+
39
+ def queued_requests
40
+ @queued_requests ||= []
41
+ end
42
+
43
+ private
44
+
45
+ def hydra
46
+ @hydra ||= Typhoeus::Hydra.new
47
+ end
48
+ end
49
+ end
@@ -2,11 +2,21 @@ module ChimeraHttpClient
2
2
  class Request
3
3
  TIMEOUT_SECONDS = 3
4
4
 
5
+ attr_reader :request, :result
6
+
5
7
  def initialize(logger: nil)
6
8
  @logger = logger
7
9
  end
8
10
 
9
11
  def run(url:, method:, body: nil, options: {}, headers: {})
12
+ create(url: url, method: method, body: body, options: options, headers: headers)
13
+
14
+ @request.run
15
+
16
+ @result
17
+ end
18
+
19
+ def create(url:, method:, body: nil, options: {}, headers: {})
10
20
  request_params = {
11
21
  method: method,
12
22
  body: body,
@@ -22,20 +32,19 @@ module ChimeraHttpClient
22
32
  password = options.fetch(:password, nil)
23
33
  request_params[:userpwd] = "#{username}:#{password}" if username && password
24
34
 
25
- request = Typhoeus::Request.new(url, request_params)
35
+ @request = Typhoeus::Request.new(url, request_params)
26
36
 
27
- result = nil
28
- request.on_complete do |response|
37
+ @result = nil
38
+ @request.on_complete do |response|
29
39
  @logger&.info("Completed HTTP request: #{method.upcase} #{url} " \
30
40
  "in #{response.total_time&.round(3)}sec with status code #{response.code}")
31
41
 
32
- result = on_complete_handler(response)
42
+ @result = on_complete_handler(response)
33
43
  end
34
44
 
35
45
  @logger&.info("Starting HTTP request: #{method.upcase} #{url}")
36
- request.run
37
46
 
38
- result
47
+ self
39
48
  end
40
49
 
41
50
  private
@@ -1,3 +1,3 @@
1
1
  module ChimeraHttpClient
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "0.5.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chimera_http_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Finger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-15 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: awesome_print
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -126,8 +140,10 @@ files:
126
140
  - TODO.markdown
127
141
  - chimera_http_client.gemspec
128
142
  - lib/chimera_http_client.rb
143
+ - lib/chimera_http_client/base.rb
129
144
  - lib/chimera_http_client/connection.rb
130
145
  - lib/chimera_http_client/error.rb
146
+ - lib/chimera_http_client/queue.rb
131
147
  - lib/chimera_http_client/request.rb
132
148
  - lib/chimera_http_client/response.rb
133
149
  - lib/chimera_http_client/version.rb