chimera_http_client 0.5.0 → 1.0.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: 5e2fa666cf4ec3fe21e1f4a8ecfb3932c5dac1cb6d0c7d16762eea73bf76fb44
4
- data.tar.gz: df72864e42844dd77dcc9f64bfc23f69d73a66ee66f7589c8ef1e460524b831c
3
+ metadata.gz: 1a58fb6d4a20a8a2bef43186a46663abc494844ccc30cf6f2e467dd043519861
4
+ data.tar.gz: '08c871044cb14bfbe9de820547ec7531a2719302f30d84e8aa9d658ed9ebf197'
5
5
  SHA512:
6
- metadata.gz: 52cd8916ab3bd1956753eac56a54a0c9b6130fdfbb38e9d7f2083b137097e1a585a8d205ad75f6e3b6713ee55cf66c1443b8136c22f7d48c8e0045da397612c5
7
- data.tar.gz: 70f7a691115d59909ec1831d48ed1fc02f4aa7ce8057bc35cf015a4254ee1f09318b45a20cf30686548d2b0bd686644ac0df6f5f6e9e9c2303b09b5cedfbb611
6
+ metadata.gz: 28b48b1d2fe9b723a9b567b30be1dabdd2bdc76313f9392e4ebe30bf3a8568f729a00f7b0dbdc362099196dd5aea62ddfcceb09db15481b67ada604271a75546
7
+ data.tar.gz: c211bc5978a7623c8f9ddaf1a069bd4f7d0aeb8bd680b2c8e61e6f9e4b32b281768da1b3bfa364b6ef69382763ae2f03324b37fa54d5277b1ae68e1468bc5b73
data/.rubocop.yml CHANGED
@@ -5,10 +5,13 @@ AllCops:
5
5
  - vendor/**/*
6
6
  - config.ru
7
7
 
8
+ Layout/AlignHash:
9
+ Enabled: false
10
+
8
11
  # Cop supports --auto-correct.
9
12
  # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
10
13
  # SupportedStyles: special_inside_parentheses, consistent, align_braces
11
- Layout/IndentHash:
14
+ Layout/IndentFirstHashElement:
12
15
  EnforcedStyle: consistent
13
16
 
14
17
  Metrics/AbcSize:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.2
1
+ 2.6.3
data/.travis.yml ADDED
@@ -0,0 +1,26 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - ruby-head
5
+ - 2.6
6
+ - 2.5
7
+ - 2.4
8
+ - jruby
9
+ - truffleruby
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: jruby
14
+ - rvm: truffleruby
15
+ fast_finish: true
16
+
17
+ before_install:
18
+ - 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc'
19
+
20
+ bundler_args: --jobs 3 --retry 3
21
+
22
+ before_script:
23
+
24
+ # execute rspec tests, rubocop and bundle:audit
25
+ script:
26
+ bundle exec rake
data/README.markdown CHANGED
@@ -4,13 +4,17 @@ When starting to split monolithic apps into smaller services, you need an easy w
4
4
 
5
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
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.
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 and simple aggregating of distributed data.
8
+
9
+ [![Build Status](https://travis-ci.com/mediafinger/chimera_http_client.svg?branch=master)](https://travis-ci.com/mediafinger/chimera_http_client)
8
10
 
9
11
  ## Dependencies
10
12
 
11
- The `chimera_http_client` gem is using the _libcurl_ wrapper [**Typhoeus**](https://typhoeus.github.io/). This allows for fast requests, for caching, and for queueing requests to run them in parallel (not all features are implemented in the gem yet).
13
+ The `chimera_http_client` gem is wrapping the **libcurl** wrapper [**Typhoeus**](https://typhoeus.github.io/) to have a more convenient interface. This allows for fast requests, for caching responses, and for queueing requests to run them in parallel. Connections are persistent by default, which saves subsequent requests from establishing a connection.
14
+
15
+ The only other runtime dependency is Ruby's latest code loader [**zeitwerk**](https://github.com/fxn/zeitwerk) which is also part of Rails 6.
12
16
 
13
- It does not have any other runtime dependencies.
17
+ All Ruby versions newer than **2.4** are supported.
14
18
 
15
19
  ### ENV variables
16
20
 
@@ -169,7 +173,13 @@ class Cache
169
173
  end
170
174
  ```
171
175
 
172
- Or use an adapter for Dalli, Redis, or Rails cache that also support an optional time-to-live `default_ttl` parameter.
176
+ Or use an adapter for Dalli, Redis, or Rails cache that also support an optional time-to-live `default_ttl` parameter. If you use `Rails.cache` with the adapter `:memory_store` or `:mem_cache_store`, the object you would have to pass looks like this:
177
+
178
+ ```ruby
179
+ require "typhoeus/cache/rails"
180
+
181
+ cache: Typhoeus::Cache::Rails.new(Rails.cache, default_ttl: 600) # 600 seconds
182
+ ```
173
183
 
174
184
  Read more about how to use it: https://github.com/typhoeus/typhoeus#caching
175
185
 
@@ -348,7 +358,7 @@ To inspect the requests waiting for execution, call `queue.queued_requests`.
348
358
 
349
359
  Add this line to your application's Gemfile:
350
360
 
351
- gem 'chimera_http_client', '~> 0.3'
361
+ gem 'chimera_http_client', '~> 0.5'
352
362
 
353
363
  And then execute:
354
364
 
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
+ require "bundler/audit/task"
1
2
  require "bundler/gem_tasks"
2
3
  require "rspec/core/rake_task"
3
4
 
5
+ Bundler::Audit::Task.new
4
6
  RSpec::Core::RakeTask.new(:rspec)
5
7
 
6
8
  desc "Open a console with the ChimeraHttpClient loaded"
@@ -24,4 +26,4 @@ task :rubocopa do
24
26
  end
25
27
 
26
28
  desc "Run all the tests"
27
- task default: %i[rspec rubocop]
29
+ task default: %i[rspec rubocop bundle:audit]
data/TODO.markdown CHANGED
@@ -6,75 +6,119 @@ _none known_
6
6
 
7
7
  ## Features
8
8
 
9
- ### HTTP Headers
9
+ ### Logger
10
10
 
11
- * make Connection#default_headers configurable
12
- * allow to set default_headers via ENV vars
13
- * give example how to use default_headers (e.g. request_id)
14
- * explain in README how to benefit from this gem in a given setting
11
+ * [x] ~~allow to pass a logger~~
12
+ * [x] ~~add logger.info when starting a http call~~
13
+ * [x] ~~add logger.info when finishing a successful http call~~
14
+ * [x] ~~include the total_time of the requests in the log~~
15
+ * [x] ~~add (example) to README~~
16
+ * [ ] add logger.warn / .error for error cases (?)
15
17
 
16
- ### Logger
18
+ ### Custom De-serializer
17
19
 
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
- * add logger.warn / .error for error cases (?)
20
+ * [ ] allow to pass custom deserializer
21
+ * [ ] use custom deserializer in #parsed_body instead of default JSON parsing
22
+ * [ ] add example to README
23
+
24
+ ### Queueing / running in parallel
25
+
26
+ * [x] ~~allow to queue multiple requests~~
27
+ * [x] ~~execute (up to 200) requests in parallel~~
28
+ * [ ] allow to pass one proc / block (for all requests) to use as on_complete handler for each request
29
+ * [ ] allow to pass one proc / block per requests) to use as on_complete handler
30
+ * [ ] add example to README
31
+
32
+ ### Add server for testing
33
+
34
+ * [ ] add a simple (Sinatra) server for testing
35
+ * [ ] run (all?) tests against the server (with capybara_discoball?)
36
+ * [ ] make server also available for console testing
37
+ * [ ] add example to README
38
+
39
+ ### Enable more Typhoeus functionality
40
+
41
+ * [ ] accept_encoding: "gzip"
42
+ * [ ] connecttimeout: 1
43
+ * [ ] cookiefile: "/path/to/file"
44
+ * [ ] cookiejar: "/path/to/file"
45
+ * [ ] followlocation: true
46
+ * [ ] forbid_reuse: true
47
+ * [ ] memoize: false
48
+ * [ ] ssl_verifyhost: 0
49
+ * [ ] ssl_verifypeer: false
50
+ * [ ] verbose: true
51
+ * [ ] Cache adapters
52
+ * [ ] or enable to access the Typhoeos directly through Chimera?
53
+ * [ ] add example to README
24
54
 
25
55
  ### Custom Serializer
26
56
 
27
- * allow to pass custom serializer
28
- * use custom serializer instead of expecting a JSON (or other) body
29
- * set header for the serializer
30
- * add example to README
57
+ * [ ] allow to pass custom serializer
58
+ * [ ] use custom serializer instead of expecting a JSON (or other) body
59
+ * [ ] set header for the serializer
60
+ * [ ] add example to README
31
61
 
32
- ### Custom De-serializer
62
+ ### File Uploads
33
63
 
34
- * allow to pass custom deserializer
35
- * use custom deserializer in #parsed_body instead of default JSON parsing
36
- * add example to README
64
+ * [ ] add example to README
37
65
 
38
- ### Queueing / running in parallel
66
+ ### Streaming response bodies
39
67
 
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
43
- * add example to README
68
+ * [ ] enable to pass on_headers, on_body, on_complete procs
69
+ * [ ] add example to README
44
70
 
45
- ### Queueing / run requests serialized
71
+ ### HTTP Headers
46
72
 
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?
51
- * add example to README
73
+ * [ ] make Connection#default_headers configurable
74
+ * [ ] allow to set default_headers via ENV vars
75
+ * [ ] give example how to use default_headers (e.g. request_id)
76
+ * [ ] explain in README how to benefit from this gem in a given setting
52
77
 
53
- ### Caching
78
+ ### ~~Caching~~
54
79
 
55
- * ~~optional per connection or call~~
56
- * ~~add example to README~~
80
+ * [x] ~~optional per connection or call~~
81
+ * [x] ~~add example to README~~
57
82
 
58
- ### Timeout
83
+ ### ~~Timeout~~
59
84
 
60
- * ~~allow to set custom timeout per connection~~
61
- * ~~allow to set custom timeout per call~~
62
- * ~~add (example) to README~~
85
+ * [x] ~~allow to set custom timeout per connection~~
86
+ * [x] ~~allow to set custom timeout per call~~
87
+ * [x] ~~add (example) to README~~
63
88
 
64
89
  ### Release
65
90
 
66
- * ~~rename module to have unique namespace~~
67
- * ~~release to rubygems to add to the plethora of similar gems~~
68
- * ~~make repo public~~
69
- * hook up Travis-CI
70
- * ensure it runs with Ruby 2.4 and newer
71
- * get feedback
91
+ * [x] ~~rename module to have unique namespace~~
92
+ * [x] ~~release to rubygems to add to the plethora of similar gems~~
93
+ * [x] ~~make repo public~~
94
+ * [x] ~~hook up Travis-CI~~
95
+ * [x] ~~ensure it runs with Ruby 2.4 and newer~~
72
96
 
73
- ### File Uploads
97
+ ### Retry Requests
74
98
 
75
- * add example to README
99
+ * [ ] either leverage Hydra to retry failed calls
100
+ * [ ] configure number of retries
101
+ * [ ] configure delay between retries
102
+ * [ ] retry idempotent calls GET, PUT, DELETE, HEAD automatically
103
+ * [ ] maybe implement retries with wait and Redis (external dependency!)
104
+ * [ ] or document in README how to build a retry mechanism
105
+ * [ ] https://gist.github.com/kunalmodi/2939288
76
106
 
77
- ### Streaming response bodies
107
+ ### Queueing / run requests serialized
78
108
 
79
- * enable to pass on_headers, on_body, on_complete procs
80
- * add example to README
109
+ * [ ] allow to queue multiple requests
110
+ * [ ] execute (up to 5) queued requests
111
+ * [ ] allow to pass a on_handler proc (per request) that could involve queueing new requests
112
+ * [ ] or just explain how to code that yourself?
113
+ * [ ] add example to README
114
+
115
+ ### Rate limiting
116
+
117
+ * [ ] implement with different strategies
118
+ * [ ] max concurrent requests
119
+ * [ ] max requests in fixed time frame
120
+ * [ ] max requests in sliding time window
121
+ * [ ] implement counters in Redis (external dependency!)
122
+ * [ ] add metrics / monitoring
123
+ * [ ] don't add throttling?
124
+ * [ ] add example to README
@@ -19,9 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_runtime_dependency "typhoeus", "~> 1.1"
22
+ spec.add_runtime_dependency "zeitwerk", ">= 2.0"
22
23
 
23
24
  spec.add_development_dependency "awesome_print", "~> 1.8"
24
- spec.add_development_dependency "bundler", "~> 1.13"
25
+ spec.add_development_dependency "bundler", ">= 1.0"
26
+ spec.add_development_dependency "bundler-audit", "~> 0.6"
25
27
  spec.add_development_dependency "irb", "~> 1.0"
26
28
  spec.add_development_dependency "rake", ">= 10.0"
27
29
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -9,10 +9,10 @@ module ChimeraHttpClient
9
9
  @logger = logger
10
10
  @timeout = timeout
11
11
 
12
+ Typhoeus::Config.cache = cache
13
+ Typhoeus::Config.memoize = false # hydra setting, prevents a possible memory leak
12
14
  Typhoeus::Config.user_agent = user_agent
13
15
  Typhoeus::Config.verbose = verbose
14
- Typhoeus::Config.memoize = false
15
- Typhoeus::Config.cache = cache
16
16
  end
17
17
 
18
18
  private
@@ -27,7 +27,9 @@ module ChimeraHttpClient
27
27
  def extract_body(options)
28
28
  body = options.delete(:body)
29
29
  body_optional = options.delete(:body_optional)
30
+
30
31
  fail(ChimeraHttpClient::ParameterMissingError, "body expected, but not given") if body.nil? && !body_optional
32
+
31
33
  body
32
34
  end
33
35
 
@@ -6,6 +6,7 @@ module ChimeraHttpClient
6
6
  def initialize(options = {})
7
7
  super(options)
8
8
 
9
+ define_http_methods
9
10
  define_bang_methods
10
11
  end
11
12
 
@@ -13,43 +14,41 @@ module ChimeraHttpClient
13
14
  @request ||= Request.new(logger: @logger)
14
15
  end
15
16
 
16
- def get(endpoint, options = {})
17
- run(:get, endpoint, options.merge(body_optional: true))
18
- end
19
-
20
- def post(endpoint, options = {})
21
- run(:post, endpoint, options)
22
- end
23
-
24
- def put(endpoint, options = {})
25
- run(:put, endpoint, options)
26
- end
27
-
28
- def patch(endpoint, options = {})
29
- run(:patch, endpoint, options)
30
- end
31
-
32
- def delete(endpoint, options = {})
33
- run(:delete, endpoint, options.merge(body_optional: true))
34
- end
35
-
36
17
  private
37
18
 
38
19
  def run(method, endpoint, options = {})
20
+ options[:body_optional] = true if %i[get delete head options trace].include?(method)
39
21
  body = extract_body(options)
40
22
  headers = extract_headers(options, default_headers)
41
23
 
42
24
  request.run(url: url(endpoint), method: method, body: body, options: augmented_options(options), headers: headers)
43
25
  end
44
26
 
45
- # get! post! put! patch! delete! return an Response when successful, but raise an Error otherwise
27
+ # Define simple access methods that return a Response object in success case and an Error object otherwise
28
+ #
29
+ # def get(endpoint, options = {})
30
+ # run(:get, endpoint, options)
31
+ # end
32
+ #
33
+ def define_http_methods
34
+ %i[get post put patch delete head options trace].each do |method_name|
35
+ self.class.send(:define_method, method_name) do |endpoint, options = {}|
36
+ send(:run, method_name, endpoint, options)
37
+ end
38
+ end
39
+ end
40
+
41
+ # get! post! put! patch! delete! ... return a Response object when successful, but raise an Error otherwise
46
42
  def define_bang_methods
47
43
  {
48
- get!: :get,
49
- post!: :post,
50
- put!: :put,
51
- patch!: :patch,
52
- delete!: :delete,
44
+ get!: :get,
45
+ post!: :post,
46
+ put!: :put,
47
+ patch!: :patch,
48
+ delete!: :delete,
49
+ head!: :head,
50
+ options!: :options,
51
+ trace!: :trace,
53
52
  }.each do |method_name, implemented_method|
54
53
  self.class.send(:define_method, method_name) do |endpoint, options = {}|
55
54
  result = public_send(implemented_method, endpoint, options)
@@ -29,7 +29,7 @@ module ChimeraHttpClient
29
29
  error
30
30
  end
31
31
 
32
- def to_json
32
+ def to_json(_options = {})
33
33
  error = {
34
34
  code: code,
35
35
  error_class: self.class.name,
@@ -2,20 +2,15 @@ module ChimeraHttpClient
2
2
  class Queue < Base
3
3
  def add(method, endpoint, options = {})
4
4
  http_method = method.downcase.to_sym
5
- options[:body_optional] = true if %i[get delete].include?(http_method)
5
+ options[:body_optional] = true if %i[get delete head options trace].include?(http_method)
6
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),
7
+ queued_requests << create_request(
12
8
  method: http_method,
13
- body: body,
14
- options: augmented_options(options),
15
- headers: headers
9
+ url: url(endpoint),
10
+ body: extract_body(options),
11
+ headers: extract_headers(options, default_headers),
12
+ options: augmented_options(options)
16
13
  )
17
-
18
- queued_requests << req
19
14
  end
20
15
 
21
16
  def execute
@@ -42,6 +37,16 @@ module ChimeraHttpClient
42
37
 
43
38
  private
44
39
 
40
+ def create_request(method:, url:, body:, headers:, options:)
41
+ Request.new(logger: @logger).create(
42
+ method: method,
43
+ url: url,
44
+ body: body,
45
+ headers: headers,
46
+ options: options
47
+ )
48
+ end
49
+
45
50
  def hydra
46
51
  @hydra ||= Typhoeus::Hydra.new
47
52
  end
@@ -1,3 +1,3 @@
1
1
  module ChimeraHttpClient
2
- VERSION = "0.5.0".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
@@ -1,8 +1,8 @@
1
1
  module ChimeraHttpClient
2
- ROOT_PATH = File.expand_path("..", __dir__)
3
-
4
2
  require "json"
5
3
  require "typhoeus"
4
+ require "zeitwerk"
6
5
 
7
- Dir.glob(ROOT_PATH + "/lib/chimera_http_client/*.rb") { |file| require file }
6
+ loader = Zeitwerk::Loader.for_gem
7
+ loader.setup
8
8
  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.5.0
4
+ version: 1.0.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-16 00:00:00.000000000 Z
11
+ date: 2019-06-14 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: zeitwerk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: awesome_print
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -40,18 +54,32 @@ dependencies:
40
54
  version: '1.8'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler-audit
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - "~>"
46
74
  - !ruby/object:Gem::Version
47
- version: '1.13'
75
+ version: '0.6'
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
- version: '1.13'
82
+ version: '0.6'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: irb
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -133,6 +161,7 @@ files:
133
161
  - ".rspec"
134
162
  - ".rubocop.yml"
135
163
  - ".ruby-version"
164
+ - ".travis.yml"
136
165
  - Gemfile
137
166
  - LICENSE
138
167
  - README.markdown