sniffer 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50fc6c81f9d42483702b1f7c58c784bb34098d4b687bb14463cdff1a115ca9b7
4
- data.tar.gz: e075f394c7b28b95468039faf893f5cc3cb5a548111a065f69b81fbda715bfe2
3
+ metadata.gz: 25c004fd4e29948699cec6a077433d3b0d98f3571c361be81c4f15626f2143a3
4
+ data.tar.gz: f08cbb6c16a3d572a3536c2a08eff0978f87e4f4d35b489d4cbfdf3ea60c6af9
5
5
  SHA512:
6
- metadata.gz: 71103bf582fe917cda1c4ad52c7e238c851c2aeb5459c5375b7157394cf0893e0cc2d2d1d100f3006d0a176accf083c6bf55d90d21d4f9f8b8ba395d50eefd60
7
- data.tar.gz: d765279e5adb997fd1021a131587a96ae6057f8ee808af9debe657c1f67fdaecd537c23d62d8663729e79ae24f81e5f4f7f6bf54326870bf3a29e939bc04af05
6
+ metadata.gz: 9548307ea9f504e05ce9fa1f789a1e0d697906841f34a317f5c67c3e1c0ae669f69afab0537fe5e331550e10b531016227ff68321c1f4eadb4bc3f3d6d7a896b
7
+ data.tar.gz: 1cacd254ba99b6167c4d2221061ebbba0cb2565c281fe100df31190ac0e37035c14e008544d5f2f02b980a08609187841886d700354c6e76a95cd31afb84781e
@@ -12,13 +12,13 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- ruby: ["2.5.x", "2.6.x"]
15
+ ruby-version: ['3.1', '3.0', '2.7', '2.6', '2.5']
16
16
  steps:
17
- - uses: actions/checkout@v1
18
- - name: Set up Ruby
19
- uses: actions/setup-ruby@v1
17
+ - uses: actions/checkout@v2
18
+ - name: Set up Ruby ${{ matrix.ruby-version }}
19
+ uses: ruby/setup-ruby@v1
20
20
  with:
21
- ruby-version: ${{ matrix.ruby }}
21
+ ruby-version: ${{ matrix.ruby-version }}
22
22
  - name: Install Bundler
23
23
  run: |
24
24
  gem install bundler
@@ -31,4 +31,7 @@ jobs:
31
31
  bundle install --jobs 4 --retry 3
32
32
  - name: Run RSpec
33
33
  run: |
34
- bundle exec rake spec
34
+ bundle exec rspec
35
+ - name: Run RSpec (prepended)
36
+ run: |
37
+ bundle exec rspec -r all_prepend
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
+ ## 0.5.0 (May 6, 2022) ##
2
+
3
+ * Added prepend of all adapters by [@nate-at-gusto](https://github.com/nate-at-gusto)
4
+ * Replaced `active_attr` to `dry-initializer`
5
+ * Added rubies `2.7`, `3.0`, `3.1` support
6
+
7
+
1
8
  ## 0.4.0 (March 19, 2020) ##
2
9
 
3
- * Added middleware support
10
+ * Added middleware support by [@dsalahutdinov](https://github.com/dsalahutdinov)
4
11
 
5
12
 
6
13
  ## 0.3.2 (January 12, 2018) ##
data/README.md CHANGED
@@ -31,6 +31,20 @@ Add this line to your application's Gemfile:
31
31
  gem 'sniffer'
32
32
  ```
33
33
 
34
+ If you wish Sniffer to use `Module#prepend` instead of `alias_method`, you can cause individual adapters to use `prepend` instead with:
35
+
36
+ ```ruby
37
+ gem 'sniffer', require: ['http_prepend', 'httpclient_prepend', 'sniffer']
38
+ ```
39
+
40
+ It's important that `'sniffer'` is the last item in the list. See the `lib` directory for a list of prependable adapters.
41
+
42
+ If you want all adapters to use `prepend`:
43
+
44
+ ```ruby
45
+ gem 'sniffer', require: ['all_prepend', 'sniffer']
46
+ ```
47
+
34
48
  And then execute:
35
49
 
36
50
  $ bundle
@@ -203,6 +217,15 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
203
217
 
204
218
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
205
219
 
220
+
221
+ ## Development (with Docker)
222
+
223
+ Get local development environment working and tests running is very easy with docker-compose:
224
+ ```sh
225
+ docker-compose run app bundle
226
+ docker-compose run app bundle exec rspec
227
+ ```
228
+
206
229
  ## Contributing
207
230
 
208
231
  Bug reports and pull requests are welcome on GitHub at https://github.com/aderyabin/sniffer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -215,6 +238,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/aderya
215
238
  * [Stanislav Chereshkevich](https://github.com/dissident)
216
239
  * [Anatoliy Kurichev](https://github.com/russo-matrosso)
217
240
  * [Dmitriy Ivliev](https://github.com/moofkit)
241
+ * [Nate Berkopec](https://github.com/nate-at-gusto)
218
242
 
219
243
  ## License
220
244
 
@@ -0,0 +1,18 @@
1
+ version: '3.4'
2
+
3
+ services:
4
+ app:
5
+ image: ruby:latest
6
+ environment:
7
+ - BUNDLE_PATH=/bundle
8
+ - BUNDLE_CONFIG=/app/.bundle/config
9
+ command: bash
10
+ working_dir: /app
11
+ volumes:
12
+ - .:/app:cached
13
+ - bundler_data:/bundle
14
+ tmpfs:
15
+ - /tmp
16
+
17
+ volumes:
18
+ bundler_data:
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'curb_prepend'
4
+ require 'ethon_prepend'
5
+ require 'eventmachine_prepend'
6
+ require 'excon_prepend'
7
+ require 'http_prepend'
8
+ require 'httpclient_prepend'
9
+ require 'net_http_prepend'
10
+ require 'patron_prepend'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module CurlAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module EthonAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module EventMachineAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module ExconAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module HTTPAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module HTTPClientAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module NetHttpAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sniffer
4
+ module Adapters
5
+ module PatronAdapter
6
+ PREPEND = true
7
+ end
8
+ end
9
+ end
@@ -4,16 +4,6 @@ module Sniffer
4
4
  module Adapters
5
5
  # Curl adapter
6
6
  module CurlAdapter
7
- def self.included(base)
8
- base.class_eval do
9
- alias_method :http_without_sniffer, :http
10
- alias_method :http, :http_with_sniffer
11
-
12
- alias_method :http_post_without_sniffer, :http_post
13
- alias_method :http_post, :http_post_with_sniffer
14
- end
15
- end
16
-
17
7
  def http_with_sniffer(verb)
18
8
  sniffer_request(verb)
19
9
 
@@ -40,6 +30,37 @@ module Sniffer
40
30
  @res
41
31
  end
42
32
 
33
+ # Only used when prepending, see all_prepend.rb
34
+ module Prepend
35
+ include CurlAdapter
36
+
37
+ def http(verb)
38
+ sniffer_request(verb)
39
+
40
+ super(verb)
41
+
42
+ bm = Benchmark.realtime do
43
+ @res = super(verb)
44
+ end
45
+
46
+ sniffer_response(bm)
47
+
48
+ @res
49
+ end
50
+
51
+ def http_post(*args)
52
+ sniffer_request(:POST, *args)
53
+
54
+ bm = Benchmark.realtime do
55
+ @res = super(*args)
56
+ end
57
+
58
+ sniffer_response(bm)
59
+
60
+ @res
61
+ end
62
+ end
63
+
43
64
  private
44
65
 
45
66
  def data_item
@@ -82,4 +103,17 @@ module Sniffer
82
103
  end
83
104
  end
84
105
 
85
- Curl::Easy.include Sniffer::Adapters::CurlAdapter if defined?(::Curl::Easy)
106
+ if defined?(::Curl::Easy)
107
+ if defined?(Sniffer::Adapters::CurlAdapter::PREPEND)
108
+ Curl::Easy.prepend Sniffer::Adapters::CurlAdapter::Prepend
109
+ else
110
+ Curl::Easy.class_eval do
111
+ include Sniffer::Adapters::CurlAdapter
112
+ alias_method :http_without_sniffer, :http
113
+ alias_method :http, :http_with_sniffer
114
+
115
+ alias_method :http_post_without_sniffer, :http_post
116
+ alias_method :http_post, :http_post_with_sniffer
117
+ end
118
+ end
119
+ end
@@ -6,42 +6,43 @@ module Sniffer
6
6
  module EthonAdapter
7
7
  # overrides http_request method
8
8
  module Http
9
- def self.included(base)
10
- base.class_eval do
11
- alias_method :http_request_without_sniffer, :http_request
12
- alias_method :http_request, :http_request_with_sniffer
13
- end
9
+ def http_request_with_sniffer(url, action_name, options = {})
10
+ make_sniffer_request(url, action_name, options)
11
+
12
+ http_request_without_sniffer(url, action_name, options)
14
13
  end
15
14
 
16
- # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
17
- def http_request_with_sniffer(url, action_name, options = {})
18
- if Sniffer.enabled?
19
- @data_item = Sniffer::DataItem.new
20
- uri = URI("http://" + url)
15
+ private
21
16
 
22
- @data_item.request = Sniffer::DataItem::Request.new(host: uri.host,
23
- method: action_name.upcase,
24
- port: options[:port] || uri.port,
25
- headers: options[:headers].to_h,
26
- body: options[:body].to_s)
17
+ def make_sniffer_request(url, action_name, options)
18
+ return unless Sniffer.enabled?
27
19
 
28
- Sniffer.store(@data_item)
29
- end
20
+ @data_item = Sniffer::DataItem.new
21
+ uri = URI("http://#{url}")
30
22
 
31
- http_request_without_sniffer(url, action_name, options)
23
+ @data_item.request = Sniffer::DataItem::Request.new(host: uri.host,
24
+ method: action_name.upcase,
25
+ port: options[:port] || uri.port,
26
+ headers: options[:headers].to_h,
27
+ body: options[:body].to_s)
28
+
29
+ Sniffer.store(@data_item)
32
30
  end
33
- end
34
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
35
31
 
36
- # overrides perform method
37
- module Operations
38
- def self.included(base)
39
- base.class_eval do
40
- alias_method :perform_without_sniffer, :perform
41
- alias_method :perform, :perform_with_sniffer
32
+ # Only used when prepending, see all_prepend.rb
33
+ module Prepend
34
+ include Http
35
+
36
+ def http_request(url, action_name, options = {})
37
+ make_sniffer_request(url, action_name, options)
38
+
39
+ super(url, action_name, options)
42
40
  end
43
41
  end
42
+ end
44
43
 
44
+ # overrides perform method
45
+ module Operations
45
46
  # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
46
47
  def perform_with_sniffer
47
48
  bm = Benchmark.realtime do
@@ -49,12 +50,12 @@ module Sniffer
49
50
  end
50
51
 
51
52
  if Sniffer.enabled?
52
- uri = URI("http://" + @url)
53
+ uri = URI("http://#{@url}")
53
54
  query = uri.path
54
55
  query += "?#{uri.query}" if uri.query
55
56
  @data_item.request.query = query
56
57
 
57
- status = @response_headers.scan(%r{HTTP\/... (\d{3})}).flatten[0].to_i
58
+ status = @response_headers.scan(%r{HTTP/... (\d{3})}).flatten[0].to_i
58
59
  hash_headers = @response_headers
59
60
  .split(/\r?\n/)[1..-1]
60
61
  .each_with_object({}) do |item, res|
@@ -76,12 +77,33 @@ module Sniffer
76
77
  @return_code
77
78
  end
78
79
  # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
80
+
81
+ # Only used when prepending, see all_prepend.rb
82
+ module Prepend
83
+ include Operations
84
+
85
+ def perform
86
+ perform_with_sniffer
87
+ end
88
+ end
79
89
  end
80
90
  end
81
91
  end
82
92
  end
83
93
 
84
94
  if defined?(::Ethon::Easy)
85
- Ethon::Easy::Http.include Sniffer::Adapters::EthonAdapter::Http
86
- Ethon::Easy::Operations.include Sniffer::Adapters::EthonAdapter::Operations
95
+ if defined?(Sniffer::Adapters::EthonAdapter::PREPEND)
96
+ Ethon::Easy.prepend Sniffer::Adapters::EthonAdapter::Http::Prepend
97
+ Ethon::Easy.prepend Sniffer::Adapters::EthonAdapter::Operations::Prepend
98
+ else
99
+ Ethon::Easy.class_eval do
100
+ include Sniffer::Adapters::EthonAdapter::Http
101
+ alias_method :http_request_without_sniffer, :http_request
102
+ alias_method :http_request, :http_request_with_sniffer
103
+
104
+ include Sniffer::Adapters::EthonAdapter::Operations
105
+ alias_method :perform_without_sniffer, :perform
106
+ alias_method :perform, :perform_with_sniffer
107
+ end
108
+ end
87
109
  end
@@ -6,54 +6,74 @@ module Sniffer
6
6
  module EventMachineAdapter
7
7
  # Overrides #send_request, #parse_response, #on_body_data
8
8
  module Client
9
- def self.included(base)
10
- base.class_eval do
11
- alias_method :send_request_without_sniffer, :send_request
12
- alias_method :send_request, :send_request_with_sniffer
13
- alias_method :parse_response_header_without_sniffer, :parse_response_header
14
- alias_method :parse_response_header, :parse_response_header_with_sniffer
15
- alias_method :on_body_data_without_sniffer, :on_body_data
16
- alias_method :on_body_data, :on_body_data_with_sniffer
17
- end
18
- end
19
-
20
- # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
21
9
  def send_request_with_sniffer(head, body)
22
- if Sniffer.enabled?
23
- @data_item = Sniffer::DataItem.new
24
- @data_item.response = Sniffer::DataItem::Response.new
25
- @data_item.request = Sniffer::DataItem::Request.new(host: @req.host,
26
- method: @req.method.to_sym,
27
- query: encode_query(@req.uri, @req.query),
28
- headers: @req.headers,
29
- body: @req.body.to_s,
30
- port: @req.port)
31
- Sniffer.store(@data_item)
32
-
33
- @start_time = Time.now
34
- end
35
-
10
+ send_request_sniffer(head, body)
36
11
  send_request_without_sniffer(head, body)
37
12
  end
38
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
39
13
 
40
14
  def parse_response_header_with_sniffer(header, version, status)
41
- if Sniffer.enabled?
42
- @data_item.response.timing = Time.now - @start_time
43
- @data_item.response.status = status
44
- @data_item.response.headers = header
45
- end
46
-
15
+ parse_response_header_sniffer(header, version, status)
47
16
  parse_response_header_without_sniffer(header, version, status)
48
17
  end
49
18
 
50
19
  def on_body_data_with_sniffer(data)
51
- if Sniffer.enabled?
52
- @data_item.response.body = data
53
- Sniffer.notify_response(@data_item)
20
+ on_body_data_sniffer(data)
21
+ on_body_data_without_sniffer(data)
22
+ end
23
+
24
+ private
25
+
26
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
27
+ def send_request_sniffer(_head, _body)
28
+ return unless Sniffer.enabled?
29
+
30
+ @data_item = Sniffer::DataItem.new
31
+ @data_item.response = Sniffer::DataItem::Response.new
32
+ @data_item.request = Sniffer::DataItem::Request.new(host: @req.host,
33
+ method: @req.method.to_sym,
34
+ query: encode_query(@req.uri, @req.query),
35
+ headers: @req.headers,
36
+ body: @req.body.to_s,
37
+ port: @req.port)
38
+ Sniffer.store(@data_item)
39
+
40
+ @start_time = Time.now
41
+ end
42
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
43
+
44
+ def parse_response_header_sniffer(header, _version, status)
45
+ return unless Sniffer.enabled?
46
+
47
+ @data_item.response.timing = Time.now - @start_time
48
+ @data_item.response.status = status
49
+ @data_item.response.headers = header
50
+ end
51
+
52
+ def on_body_data_sniffer(data)
53
+ return unless Sniffer.enabled?
54
+
55
+ @data_item.response.body = data
56
+ Sniffer.notify_response(@data_item)
57
+ end
58
+
59
+ # Only used when prepending, see all_prepend.rb
60
+ module Prepend
61
+ include Client
62
+
63
+ def send_request(head, body)
64
+ send_request_sniffer(head, body)
65
+ super(head, body)
54
66
  end
55
67
 
56
- on_body_data_without_sniffer(data)
68
+ def parse_response_header(header, version, status)
69
+ parse_response_header_sniffer(header, version, status)
70
+ super(header, version, status)
71
+ end
72
+
73
+ def on_body_data(data)
74
+ on_body_data_sniffer(data)
75
+ super(data)
76
+ end
57
77
  end
58
78
  end
59
79
  end
@@ -61,3 +81,19 @@ module Sniffer
61
81
  end
62
82
 
63
83
  EventMachine::HttpClient.include Sniffer::Adapters::EventMachineAdapter::Client if defined?(::EventMachine::HttpClient)
84
+
85
+ if defined?(::EventMachine::HttpClient)
86
+ if defined?(Sniffer::Adapters::EventMachineAdapter::PREPEND)
87
+ EventMachine::HttpClient.prepend Sniffer::Adapters::EventMachineAdapter::Client::Prepend
88
+ else
89
+ EventMachine::HttpClient.class_eval do
90
+ include Sniffer::Adapters::EventMachineAdapter::Client
91
+ alias_method :send_request_without_sniffer, :send_request
92
+ alias_method :send_request, :send_request_with_sniffer
93
+ alias_method :parse_response_header_without_sniffer, :parse_response_header
94
+ alias_method :parse_response_header, :parse_response_header_with_sniffer
95
+ alias_method :on_body_data_without_sniffer, :on_body_data
96
+ alias_method :on_body_data, :on_body_data_with_sniffer
97
+ end
98
+ end
99
+ end
@@ -4,46 +4,76 @@ module Sniffer
4
4
  module Adapters
5
5
  # Excon adapter
6
6
  module ExconAdapter
7
- def self.included(base)
8
- base.class_eval do
9
- alias_method :request_without_sniffer, :request
10
- alias_method :request, :request_with_sniffer
11
- end
12
- end
13
-
14
- # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
15
7
  def request_with_sniffer(params = {}, &block)
16
- if Sniffer.enabled?
17
- datum = data.merge(params)
18
- data_item = Sniffer::DataItem.new
19
- data_item.request = Sniffer::DataItem::Request.new(host: datum[:host],
20
- method: datum[:method],
21
- query: datum[:path] + ::Excon::Utils.query_string(datum),
22
- headers: datum[:headers] || {},
23
- body: datum[:body].to_s,
24
- port: datum[:port])
25
-
26
- Sniffer.store(data_item)
27
- end
8
+ data_item = request_sniffer_before(params)
28
9
 
29
10
  bm = Benchmark.realtime do
30
11
  @response = request_without_sniffer(params, &block)
31
12
  end
32
13
 
33
- if Sniffer.enabled?
34
- data_item.response = Sniffer::DataItem::Response.new(status: @response.status,
35
- headers: @response.headers,
36
- body: @response.body,
37
- timing: bm)
14
+ request_sniffer_after(params, bm, data_item)
15
+ @response
16
+ end
17
+
18
+ private
38
19
 
39
- Sniffer.notify_response(data_item)
40
- end
20
+ # rubocop:disable Metrics/MethodLength
21
+ def request_sniffer_before(params)
22
+ return unless Sniffer.enabled?
41
23
 
42
- @response
24
+ datum = data.merge(params)
25
+ data_item = Sniffer::DataItem.new
26
+ data_item.request = Sniffer::DataItem::Request.new(host: datum[:host],
27
+ method: datum[:method],
28
+ query: datum[:path] + ::Excon::Utils.query_string(datum),
29
+ headers: datum[:headers] || {},
30
+ body: datum[:body].to_s,
31
+ port: datum[:port])
32
+
33
+ Sniffer.store(data_item)
34
+
35
+ data_item
36
+ end
37
+ # rubocop:enable Metrics/MethodLength
38
+
39
+ def request_sniffer_after(_params, benchmark, data_item)
40
+ return unless Sniffer.enabled?
41
+
42
+ data_item.response = Sniffer::DataItem::Response.new(status: @response.status,
43
+ headers: @response.headers,
44
+ body: @response.body,
45
+ timing: benchmark)
46
+
47
+ Sniffer.notify_response(data_item)
48
+ end
49
+
50
+ # Only used when prepending, see all_prepend.rb
51
+ module Prepend
52
+ include ExconAdapter
53
+
54
+ def request(params = {}, &block)
55
+ data_item = request_sniffer_before(params)
56
+
57
+ bm = Benchmark.realtime do
58
+ @response = super(params, &block)
59
+ end
60
+
61
+ request_sniffer_after(params, bm, data_item)
62
+ @response
63
+ end
43
64
  end
44
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
45
65
  end
46
66
  end
47
67
  end
48
68
 
49
- ::Excon::Connection.include Sniffer::Adapters::ExconAdapter if defined?(::Excon::Connection)
69
+ if defined?(::Excon::Connection)
70
+ if defined?(Sniffer::Adapters::ExconAdapter::PREPEND)
71
+ ::Excon::Connection.prepend Sniffer::Adapters::ExconAdapter::Prepend
72
+ else
73
+ ::Excon::Connection.class_eval do
74
+ include Sniffer::Adapters::ExconAdapter
75
+ alias_method :request_without_sniffer, :request
76
+ alias_method :request, :request_with_sniffer
77
+ end
78
+ end
79
+ end
@@ -4,13 +4,6 @@ module Sniffer
4
4
  module Adapters
5
5
  # HTTP adapter
6
6
  module HTTPAdapter
7
- def self.included(base)
8
- base.class_eval do
9
- alias_method :request_without_sniffer, :request
10
- alias_method :request, :request_with_sniffer
11
- end
12
- end
13
-
14
7
  # private
15
8
 
16
9
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@@ -65,8 +58,27 @@ module Sniffer
65
58
  end
66
59
  end
67
60
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
61
+
62
+ # Only used when prepending, see all_prepend.rb
63
+ module Prepend
64
+ include HTTPAdapter
65
+
66
+ def request(*args)
67
+ request_with_sniffer(*args)
68
+ end
69
+ end
68
70
  end
69
71
  end
70
72
  end
71
73
 
72
- HTTP::Client.include Sniffer::Adapters::HTTPAdapter if defined?(::HTTP::Client)
74
+ if defined?(::HTTP::Client)
75
+ if defined?(Sniffer::Adapters::HTTPAdapter::PREPEND)
76
+ HTTP::Client.prepend Sniffer::Adapters::HTTPAdapter::Prepend
77
+ else
78
+ HTTP::Client.class_eval do
79
+ include Sniffer::Adapters::HTTPAdapter
80
+ alias_method :request_without_sniffer, :request
81
+ alias_method :request, :request_with_sniffer
82
+ end
83
+ end
84
+ end
@@ -4,28 +4,8 @@ module Sniffer
4
4
  module Adapters
5
5
  # HttpClient adapter
6
6
  module HTTPClientAdapter
7
- def self.included(base)
8
- base.class_eval do
9
- alias_method :do_get_block_without_sniffer, :do_get_block
10
- alias_method :do_get_block, :do_get_block_with_sniffer
11
- end
12
- end
13
-
14
- # private
15
-
16
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
17
7
  def do_get_block_with_sniffer(req, proxy, conn, &block)
18
- if Sniffer.enabled?
19
- data_item = Sniffer::DataItem.new
20
- data_item.request = Sniffer::DataItem::Request.new(host: req.header.request_uri.host,
21
- query: req.header.create_query_uri,
22
- method: req.header.request_method,
23
- headers: req.headers,
24
- body: req.body,
25
- port: req.header.request_uri.port)
26
-
27
- Sniffer.store(data_item)
28
- end
8
+ data_item = do_get_block_sniffer_before(req)
29
9
 
30
10
  retryable_response = nil
31
11
 
@@ -35,23 +15,77 @@ module Sniffer
35
15
  retryable_response = e
36
16
  end
37
17
 
38
- if Sniffer.enabled?
39
- res = conn.pop
40
- data_item.response = Sniffer::DataItem::Response.new(status: res.status_code.to_i,
41
- headers: res.headers,
42
- body: res.body,
43
- timing: bm)
18
+ do_get_block_sniffer_after(data_item, conn, bm)
19
+
20
+ raise retryable_response unless retryable_response.nil?
21
+ end
22
+
23
+ private
44
24
 
45
- conn.push(res)
25
+ # rubocop:disable Metrics/AbcSize
26
+ def do_get_block_sniffer_before(req)
27
+ return unless Sniffer.enabled?
46
28
 
47
- Sniffer.notify_response(data_item)
48
- end
29
+ data_item = Sniffer::DataItem.new
30
+ data_item.request = Sniffer::DataItem::Request.new(host: req.header.request_uri.host,
31
+ query: req.header.create_query_uri,
32
+ method: req.header.request_method,
33
+ headers: req.headers,
34
+ body: req.body,
35
+ port: req.header.request_uri.port)
49
36
 
50
- raise retryable_response unless retryable_response.nil?
37
+ Sniffer.store(data_item)
38
+
39
+ data_item
40
+ end
41
+ # rubocop:enable Metrics/AbcSize
42
+
43
+ def do_get_block_sniffer_after(data_item, conn, benchmark)
44
+ return unless Sniffer.enabled?
45
+
46
+ res = conn.pop
47
+ data_item.response = Sniffer::DataItem::Response.new(status: res.status_code.to_i,
48
+ headers: res.headers,
49
+ body: res.body,
50
+ timing: benchmark)
51
+
52
+ conn.push(res)
53
+
54
+ Sniffer.notify_response(data_item)
55
+ end
56
+
57
+ # Only used when prepending, see all_prepend.rb
58
+ module Prepend
59
+ include HTTPClientAdapter
60
+
61
+ def do_get_block(req, proxy, conn, &block)
62
+ data_item = do_get_block_sniffer_before(req)
63
+
64
+ retryable_response = nil
65
+
66
+ bm = Benchmark.realtime do
67
+ super(req, proxy, conn, &block)
68
+ rescue HTTPClient::RetryableResponse => e
69
+ retryable_response = e
70
+ end
71
+
72
+ do_get_block_sniffer_after(data_item, conn, bm)
73
+
74
+ raise retryable_response unless retryable_response.nil?
75
+ end
51
76
  end
52
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
53
77
  end
54
78
  end
55
79
  end
56
80
 
57
- HTTPClient.include Sniffer::Adapters::HTTPClientAdapter if defined?(::HTTPClient)
81
+ if defined?(::HTTPClient)
82
+ if defined?(Sniffer::Adapters::HTTPClientAdapter::PREPEND)
83
+ HTTPClient.prepend Sniffer::Adapters::HTTPClientAdapter::Prepend
84
+ else
85
+ HTTPClient.class_eval do
86
+ include Sniffer::Adapters::HTTPClientAdapter
87
+ alias_method :do_get_block_without_sniffer, :do_get_block
88
+ alias_method :do_get_block, :do_get_block_with_sniffer
89
+ end
90
+ end
91
+ end
@@ -7,44 +7,75 @@ module Sniffer
7
7
  module Adapters
8
8
  # Net::HTTP adapter
9
9
  module NetHttpAdapter
10
- def self.included(base)
11
- base.class_eval do
12
- alias_method :request_without_sniffer, :request
13
- alias_method :request, :request_with_sniffer
14
- end
15
- end
16
-
17
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
18
10
  def request_with_sniffer(req, body = nil, &block)
19
- if started? && Sniffer.enabled?
20
- data_item = Sniffer::DataItem.new
21
- data_item.request = Sniffer::DataItem::Request.new(host: @address,
22
- method: req.method,
23
- query: req.path,
24
- port: @port,
25
- headers: req.each_header.collect.to_h,
26
- body: req.body.to_s)
27
-
28
- Sniffer.store(data_item)
29
- end
11
+ data_item = request_sniffer_before(req)
30
12
 
31
13
  bm = Benchmark.realtime do
32
14
  @response = request_without_sniffer(req, body, &block)
33
15
  end
34
16
 
35
- if started? && Sniffer.enabled?
36
- data_item.response = Sniffer::DataItem::Response.new(status: @response.code.to_i,
37
- headers: @response.each_header.collect.to_h,
38
- body: @response.body.to_s,
39
- timing: bm)
40
-
41
- Sniffer.notify_response(data_item)
42
- end
17
+ request_sniffer_after(data_item, bm)
43
18
 
44
19
  @response
45
20
  end
46
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
21
+
22
+ private
23
+
24
+ def request_sniffer_before(req)
25
+ return unless started? && Sniffer.enabled?
26
+
27
+ data_item = Sniffer::DataItem.new
28
+ data_item.request = Sniffer::DataItem::Request.new(host: @address,
29
+ method: req.method,
30
+ query: req.path,
31
+ port: @port,
32
+ headers: req.each_header.collect.to_h,
33
+ body: req.body.to_s)
34
+
35
+ Sniffer.store(data_item)
36
+
37
+ data_item
38
+ end
39
+
40
+ def request_sniffer_after(data_item, benchmark)
41
+ return unless started? && Sniffer.enabled?
42
+
43
+ data_item.response = Sniffer::DataItem::Response.new(status: @response.code.to_i,
44
+ headers: @response.each_header.collect.to_h,
45
+ body: @response.body.to_s,
46
+ timing: benchmark)
47
+
48
+ Sniffer.notify_response(data_item)
49
+ end
50
+
51
+ # Only used when prepending, see all_prepend.rb
52
+ module Prepend
53
+ include NetHttpAdapter
54
+
55
+ def request(req, body = nil, &block)
56
+ data_item = request_sniffer_before(req)
57
+
58
+ bm = Benchmark.realtime do
59
+ @response = super(req, body, &block)
60
+ end
61
+
62
+ request_sniffer_after(data_item, bm)
63
+
64
+ @response
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ if defined?(::Net::HTTP)
72
+ if defined?(Sniffer::Adapters::NetHttpAdapter::PREPEND)
73
+ Net::HTTP.prepend Sniffer::Adapters::NetHttpAdapter::Prepend
74
+ else
75
+ Net::HTTP.class_eval do
76
+ include Sniffer::Adapters::NetHttpAdapter
77
+ alias_method :request_without_sniffer, :request
78
+ alias_method :request, :request_with_sniffer
47
79
  end
48
80
  end
49
81
  end
50
- Net::HTTP.include Sniffer::Adapters::NetHttpAdapter
@@ -4,46 +4,78 @@ module Sniffer
4
4
  module Adapters
5
5
  # HTTP adapter
6
6
  module PatronAdapter
7
- def self.included(base)
8
- base.class_eval do
9
- alias_method :request_without_sniffer, :request
10
- alias_method :request, :request_with_sniffer
11
- end
12
- end
13
-
14
- # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
15
7
  def request_with_sniffer(action_name, url, headers, options = {})
16
- if Sniffer.enabled?
17
- data_item = Sniffer::DataItem.new
18
- uri = URI(base_url)
19
- data_item.request = Sniffer::DataItem::Request.new(host: uri.host,
20
- method: action_name,
21
- query: url,
22
- headers: headers.dup,
23
- body: options[:data].to_s,
24
- port: uri.port)
25
-
26
- Sniffer.store(data_item)
27
- end
8
+ data_item = request_sniffer_before(action_name, url, headers, options)
28
9
 
29
10
  bm = Benchmark.realtime do
30
11
  @res = request_without_sniffer(action_name, url, headers, options)
31
12
  end
32
13
 
33
- if Sniffer.enabled?
34
- data_item.response = Sniffer::DataItem::Response.new(status: @res.status,
35
- headers: @res.headers,
36
- body: @res.body.to_s,
37
- timing: bm)
38
-
39
- Sniffer.notify_response(data_item)
40
- end
14
+ request_sniffer_after(data_item, bm)
41
15
 
42
16
  @res
43
17
  end
44
- # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
18
+
19
+ private
20
+
21
+ # rubocop:disable Metrics/MethodLength
22
+ def request_sniffer_before(action_name, url, headers, options)
23
+ return unless Sniffer.enabled?
24
+
25
+ data_item = Sniffer::DataItem.new
26
+ uri = URI(base_url)
27
+ data_item.request = Sniffer::DataItem::Request.new(host: uri.host,
28
+ method: action_name,
29
+ query: url,
30
+ headers: headers.dup,
31
+ body: options[:data].to_s,
32
+ port: uri.port)
33
+
34
+ Sniffer.store(data_item)
35
+
36
+ data_item
37
+ end
38
+ # rubocop:enable Metrics/MethodLength
39
+
40
+ def request_sniffer_after(data_item, benchmark)
41
+ return unless Sniffer.enabled?
42
+
43
+ data_item.response = Sniffer::DataItem::Response.new(status: @res.status,
44
+ headers: @res.headers,
45
+ body: @res.body.to_s,
46
+ timing: benchmark)
47
+
48
+ Sniffer.notify_response(data_item)
49
+ end
50
+
51
+ # Only used when prepending, see all_prepend.rb
52
+ module Prepend
53
+ include PatronAdapter
54
+
55
+ def request(action_name, url, headers, options = {})
56
+ data_item = request_sniffer_before(action_name, url, headers, options)
57
+
58
+ bm = Benchmark.realtime do
59
+ @res = super(action_name, url, headers, options)
60
+ end
61
+
62
+ request_sniffer_after(data_item, bm)
63
+
64
+ @res
65
+ end
66
+ end
45
67
  end
46
68
  end
47
69
  end
48
70
 
49
- ::Patron::Session.include Sniffer::Adapters::PatronAdapter if defined?(::Patron::Session)
71
+ if defined?(::Patron::Session)
72
+ if defined?(Sniffer::Adapters::PatronAdapter::PREPEND)
73
+ Patron::Session.prepend Sniffer::Adapters::PatronAdapter::Prepend
74
+ else
75
+ Patron::Session.class_eval do
76
+ include Sniffer::Adapters::PatronAdapter
77
+ alias_method :request_without_sniffer, :request
78
+ alias_method :request, :request_with_sniffer
79
+ end
80
+ end
81
+ end
@@ -27,10 +27,8 @@ module Sniffer
27
27
  url_blacklist: nil
28
28
 
29
29
  def middleware
30
- @middleware ||= begin
31
- Middleware::Chain.new.tap do |chain|
32
- chain.add(Sniffer::Middleware::Logger, logger, severity)
33
- end
30
+ @middleware ||= Middleware::Chain.new.tap do |chain|
31
+ chain.add(Sniffer::Middleware::Logger, logger, severity)
34
32
  end
35
33
 
36
34
  yield @middleware if block_given?
@@ -1,33 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_attr'
3
+ require 'dry-initializer'
4
4
  require 'json'
5
5
  require_relative 'request_policy'
6
6
 
7
7
  module Sniffer
8
8
  # Sniffer data item stores a request info
9
9
  class DataItem
10
- include ActiveAttr::MassAssignment
11
- attr_accessor :request, :response
10
+ extend Dry::Initializer
11
+
12
+ attr_writer :request, :response
13
+
14
+ option :request, optional: true
15
+ option :response, optional: true
12
16
 
13
17
  def to_h
14
18
  {
15
- request: # frozen_string_literal: true
16
- # Sniffer data item stores a request info
17
- # Basic object for request and response objects
18
- # Stores http request data
19
- # rubocop:enable
20
- # Stores http response data
21
-
22
- request&.to_h,
23
- response: # frozen_string_literal: true
24
- # Sniffer data item stores a request info
25
- # Basic object for request and response objects
26
- # Stores http request data
27
- # rubocop:enable
28
- # Stores http response data
29
-
30
- response&.to_h
19
+ request: request&.to_h,
20
+ response: response&.to_h
31
21
  }
32
22
  end
33
23
 
@@ -49,7 +39,7 @@ response&.to_h
49
39
 
50
40
  # Basic object for request and response objects
51
41
  class HttpObject
52
- include ActiveAttr::MassAssignment
42
+ extend Dry::Initializer
53
43
 
54
44
  def log_message
55
45
  raise NotImplementedError
@@ -62,7 +52,14 @@ response&.to_h
62
52
 
63
53
  # Stores http request data
64
54
  class Request < HttpObject
65
- attr_accessor :host, :port, :query, :method, :headers, :body
55
+ option :host, optional: true
56
+ option :port, optional: true
57
+ option :query, optional: true
58
+ option :method, optional: true
59
+ option :headers, optional: true
60
+ option :body, optional: true
61
+
62
+ attr_writer :host, :port, :query, :method, :headers, :body
66
63
 
67
64
  def to_h
68
65
  {
@@ -70,14 +67,7 @@ response&.to_h
70
67
  query: query,
71
68
  port: port,
72
69
  headers: headers,
73
- body: # frozen_string_literal: true
74
- # Sniffer data item stores a request info
75
- # Basic object for request and response objects
76
- # Stores http request data
77
- # rubocop:enable
78
- # Stores http response data
79
-
80
- body&.to_s,
70
+ body: body&.to_s,
81
71
  method: method
82
72
  }
83
73
  end
@@ -106,20 +96,18 @@ body&.to_s,
106
96
 
107
97
  # Stores http response data
108
98
  class Response < HttpObject
109
- attr_accessor :status, :headers, :body, :timing
99
+ attr_writer :status, :headers, :body, :timing
100
+
101
+ option :status, optional: true
102
+ option :headers, optional: true
103
+ option :body, optional: true
104
+ option :timing, optional: true
110
105
 
111
106
  def to_h
112
107
  {
113
108
  status: status,
114
109
  headers: headers,
115
- body: # frozen_string_literal: true
116
- # Sniffer data item stores a request info
117
- # Basic object for request and response objects
118
- # Stores http request data
119
- # rubocop:enable
120
- # Stores http response data
121
-
122
- body&.to_s,
110
+ body: body&.to_s,
123
111
  timing: timing
124
112
  }
125
113
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sniffer
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/sniffer.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_dependency "anyway_config", ">= 1.0"
23
- spec.add_dependency "active_attr", ">= 0.10.2"
23
+ spec.add_dependency "dry-initializer", "~> 3"
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 2"
26
26
  spec.add_development_dependency "rake", ">= 12.3.3"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sniffer
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
  - Andrey Deryabin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-19 00:00:00.000000000 Z
11
+ date: 2022-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: active_attr
28
+ name: dry-initializer
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.10.2
33
+ version: '3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.10.2
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -272,6 +272,16 @@ files:
272
272
  - assets/demo.gif
273
273
  - bin/console
274
274
  - bin/setup
275
+ - docker-compose.yml
276
+ - lib/all_prepend.rb
277
+ - lib/curb_prepend.rb
278
+ - lib/ethon_prepend.rb
279
+ - lib/eventmachine_prepend.rb
280
+ - lib/excon_prepend.rb
281
+ - lib/http_prepend.rb
282
+ - lib/httpclient_prepend.rb
283
+ - lib/net_http_prepend.rb
284
+ - lib/patron_prepend.rb
275
285
  - lib/sniffer.rb
276
286
  - lib/sniffer/adapters/curb_adapter.rb
277
287
  - lib/sniffer/adapters/ethon_adapter.rb
@@ -309,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
309
319
  - !ruby/object:Gem::Version
310
320
  version: '0'
311
321
  requirements: []
312
- rubygems_version: 3.0.1
322
+ rubygems_version: 3.0.3
313
323
  signing_key:
314
324
  specification_version: 4
315
325
  summary: Analyze HTTP Requests