sniffer 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: 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