sniffer 0.3.1 → 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 +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +23 -0
- data/.github/workflows/rspec.yml +37 -0
- data/.github/workflows/rubocop.yml +23 -0
- data/.rubocop.yml +14 -20
- data/CHANGELOG.md +16 -2
- data/README.md +53 -9
- data/docker-compose.yml +18 -0
- data/lib/all_prepend.rb +10 -0
- data/lib/curb_prepend.rb +9 -0
- data/lib/ethon_prepend.rb +9 -0
- data/lib/eventmachine_prepend.rb +9 -0
- data/lib/excon_prepend.rb +9 -0
- data/lib/http_prepend.rb +9 -0
- data/lib/httpclient_prepend.rb +9 -0
- data/lib/net_http_prepend.rb +9 -0
- data/lib/patron_prepend.rb +9 -0
- data/lib/sniffer/adapters/curb_adapter.rb +46 -12
- data/lib/sniffer/adapters/ethon_adapter.rb +53 -31
- data/lib/sniffer/adapters/eventmachine_adapter.rb +74 -38
- data/lib/sniffer/adapters/excon_adapter.rb +60 -30
- data/lib/sniffer/adapters/http_adapter.rb +22 -10
- data/lib/sniffer/adapters/httpclient_adapter.rb +68 -36
- data/lib/sniffer/adapters/net_http_adapter.rb +60 -29
- data/lib/sniffer/adapters/patron_adapter.rb +62 -30
- data/lib/sniffer/config.rb +12 -0
- data/lib/sniffer/data.rb +0 -2
- data/lib/sniffer/data_item.rb +29 -16
- data/lib/sniffer/middleware/chain.rb +73 -0
- data/lib/sniffer/middleware/entry.rb +19 -0
- data/lib/sniffer/middleware/logger.rb +27 -0
- data/lib/sniffer/version.rb +1 -1
- data/lib/sniffer.rb +12 -3
- data/sniffer.gemspec +5 -5
- metadata +38 -22
- data/.travis.yml +0 -6
@@ -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
|
-
|
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
|
-
|
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
|
-
data_item.log
|
40
|
-
end
|
14
|
+
request_sniffer_after(data_item, bm)
|
41
15
|
|
42
16
|
@res
|
43
17
|
end
|
44
|
-
|
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
|
-
|
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
|
data/lib/sniffer/config.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "anyway_config"
|
4
|
+
require_relative "middleware/chain"
|
5
|
+
require_relative "middleware/logger"
|
4
6
|
|
5
7
|
module Sniffer
|
6
8
|
# Sniffer configuration
|
@@ -24,6 +26,15 @@ module Sniffer
|
|
24
26
|
url_whitelist: nil,
|
25
27
|
url_blacklist: nil
|
26
28
|
|
29
|
+
def middleware
|
30
|
+
@middleware ||= Middleware::Chain.new.tap do |chain|
|
31
|
+
chain.add(Sniffer::Middleware::Logger, logger, severity)
|
32
|
+
end
|
33
|
+
|
34
|
+
yield @middleware if block_given?
|
35
|
+
@middleware
|
36
|
+
end
|
37
|
+
|
27
38
|
def capacity?
|
28
39
|
store.is_a?(Hash) && store.key?(:capacity)
|
29
40
|
end
|
@@ -34,6 +45,7 @@ module Sniffer
|
|
34
45
|
|
35
46
|
def rotate?
|
36
47
|
return false unless capacity?
|
48
|
+
|
37
49
|
store.fetch(:rotate, true)
|
38
50
|
end
|
39
51
|
end
|
data/lib/sniffer/data.rb
CHANGED
data/lib/sniffer/data_item.rb
CHANGED
@@ -1,44 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
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
|
-
|
11
|
-
|
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: request
|
16
|
-
response: response
|
19
|
+
request: request&.to_h,
|
20
|
+
response: response&.to_h
|
17
21
|
}
|
18
22
|
end
|
19
23
|
|
20
|
-
def log
|
21
|
-
return unless Sniffer.logger && allowed_to_sniff?
|
22
|
-
Sniffer.logger.log(Sniffer.config.severity, to_json)
|
23
|
-
end
|
24
|
-
|
25
24
|
def to_log
|
26
25
|
return {} unless Sniffer.config.logger
|
26
|
+
|
27
27
|
request.to_log.merge(response.to_log)
|
28
28
|
end
|
29
29
|
|
30
|
-
def to_json
|
30
|
+
def to_json(*_args)
|
31
31
|
to_log.to_json
|
32
32
|
end
|
33
33
|
|
34
34
|
def allowed_to_sniff?
|
35
35
|
return true unless request
|
36
|
+
|
36
37
|
RequestPolicy.call(request)
|
37
38
|
end
|
38
39
|
|
39
40
|
# Basic object for request and response objects
|
40
41
|
class HttpObject
|
41
|
-
|
42
|
+
extend Dry::Initializer
|
42
43
|
|
43
44
|
def log_message
|
44
45
|
raise NotImplementedError
|
@@ -51,7 +52,14 @@ module Sniffer
|
|
51
52
|
|
52
53
|
# Stores http request data
|
53
54
|
class Request < HttpObject
|
54
|
-
|
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
|
55
63
|
|
56
64
|
def to_h
|
57
65
|
{
|
@@ -59,7 +67,7 @@ module Sniffer
|
|
59
67
|
query: query,
|
60
68
|
port: port,
|
61
69
|
headers: headers,
|
62
|
-
body: body
|
70
|
+
body: body&.to_s,
|
63
71
|
method: method
|
64
72
|
}
|
65
73
|
end
|
@@ -88,13 +96,18 @@ module Sniffer
|
|
88
96
|
|
89
97
|
# Stores http response data
|
90
98
|
class Response < HttpObject
|
91
|
-
|
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
|
92
105
|
|
93
106
|
def to_h
|
94
107
|
{
|
95
108
|
status: status,
|
96
109
|
headers: headers,
|
97
|
-
body: body
|
110
|
+
body: body&.to_s,
|
98
111
|
timing: timing
|
99
112
|
}
|
100
113
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "entry"
|
4
|
+
|
5
|
+
module Sniffer
|
6
|
+
# Middleware is code configured to run before/after
|
7
|
+
# storing sniffed request/response
|
8
|
+
# To add middleware
|
9
|
+
#
|
10
|
+
# Sniffer.middleware do |chain|
|
11
|
+
# chain.add MyHook
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class MyHook
|
15
|
+
# def request(data_item)
|
16
|
+
# puts "Before request work"
|
17
|
+
# yield
|
18
|
+
# puts "After request work"
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def response(data_item)
|
22
|
+
# puts "Before response work"
|
23
|
+
# yield
|
24
|
+
# puts "After response work"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
module Middleware
|
28
|
+
# Stores all the middleware configs
|
29
|
+
class Chain
|
30
|
+
include Enumerable
|
31
|
+
|
32
|
+
def entries
|
33
|
+
@entries ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def each(&block)
|
37
|
+
entries.each(&block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(klass, *args)
|
41
|
+
entries.push(Entry.new(klass, *args))
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove(klass)
|
45
|
+
entries.delete_if { |entry| entry.klass == klass }
|
46
|
+
end
|
47
|
+
|
48
|
+
def invoke_request(*args)
|
49
|
+
chain = map(&:make_new).dup
|
50
|
+
traverse_chain = lambda do
|
51
|
+
if chain.empty?
|
52
|
+
yield
|
53
|
+
else
|
54
|
+
chain.shift.request(*args, &traverse_chain)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
traverse_chain.call
|
58
|
+
end
|
59
|
+
|
60
|
+
def invoke_response(*args)
|
61
|
+
chain = map(&:make_new).dup
|
62
|
+
traverse_chain = lambda do
|
63
|
+
if chain.empty?
|
64
|
+
yield
|
65
|
+
else
|
66
|
+
chain.shift.response(*args, &traverse_chain)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
traverse_chain.call
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sniffer
|
4
|
+
module Middleware
|
5
|
+
# Middleware entry, represented with klass and arguments for initializer
|
6
|
+
class Entry
|
7
|
+
attr_reader :klass
|
8
|
+
|
9
|
+
def initialize(klass, *args)
|
10
|
+
@klass = klass
|
11
|
+
@args = args
|
12
|
+
end
|
13
|
+
|
14
|
+
def make_new
|
15
|
+
@klass.new(*@args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sniffer
|
4
|
+
module Middleware
|
5
|
+
# Response logging build-in middleware
|
6
|
+
class Logger
|
7
|
+
attr_reader :logger, :severity
|
8
|
+
|
9
|
+
def initialize(logger, severity)
|
10
|
+
@logger = logger
|
11
|
+
@severity = severity
|
12
|
+
end
|
13
|
+
|
14
|
+
def request(_data_item)
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
|
18
|
+
def response(data_item)
|
19
|
+
yield
|
20
|
+
|
21
|
+
return unless logger
|
22
|
+
|
23
|
+
logger.log(severity, data_item.to_json)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/sniffer/version.rb
CHANGED
data/lib/sniffer.rb
CHANGED
@@ -48,11 +48,20 @@ module Sniffer
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def store(data_item)
|
51
|
-
|
51
|
+
return unless config.store
|
52
|
+
return unless data_item.allowed_to_sniff?
|
53
|
+
|
54
|
+
config.middleware.invoke_request(data_item) do
|
55
|
+
data.store(data_item)
|
56
|
+
end
|
52
57
|
end
|
53
58
|
|
54
|
-
def
|
55
|
-
config.
|
59
|
+
def notify_response(data_item)
|
60
|
+
return unless config.store
|
61
|
+
return unless data_item.allowed_to_sniff?
|
62
|
+
|
63
|
+
config.middleware.invoke_response(data_item) do
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
data/sniffer.gemspec
CHANGED
@@ -19,13 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
end
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_dependency "anyway_config", "
|
23
|
-
spec.add_dependency "
|
22
|
+
spec.add_dependency "anyway_config", ">= 1.0"
|
23
|
+
spec.add_dependency "dry-initializer", "~> 3"
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake", "
|
25
|
+
spec.add_development_dependency "bundler", "~> 2"
|
26
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
27
27
|
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
-
spec.add_development_dependency "rubocop"
|
28
|
+
spec.add_development_dependency "rubocop"
|
29
29
|
spec.add_development_dependency "pry-byebug"
|
30
30
|
spec.add_development_dependency "sinatra", "~> 2.0"
|
31
31
|
spec.add_development_dependency "puma", ">= 3.10.0"
|
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sniffer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 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:
|
11
|
+
date: 2022-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anyway_config
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: dry-initializer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
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:
|
40
|
+
version: '3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 12.3.3
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 12.3.3
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: pry-byebug
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -255,10 +255,14 @@ executables: []
|
|
255
255
|
extensions: []
|
256
256
|
extra_rdoc_files: []
|
257
257
|
files:
|
258
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
259
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
260
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
261
|
+
- ".github/workflows/rspec.yml"
|
262
|
+
- ".github/workflows/rubocop.yml"
|
258
263
|
- ".gitignore"
|
259
264
|
- ".rspec"
|
260
265
|
- ".rubocop.yml"
|
261
|
-
- ".travis.yml"
|
262
266
|
- CHANGELOG.md
|
263
267
|
- CODE_OF_CONDUCT.md
|
264
268
|
- Gemfile
|
@@ -268,6 +272,16 @@ files:
|
|
268
272
|
- assets/demo.gif
|
269
273
|
- bin/console
|
270
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
|
271
285
|
- lib/sniffer.rb
|
272
286
|
- lib/sniffer/adapters/curb_adapter.rb
|
273
287
|
- lib/sniffer/adapters/ethon_adapter.rb
|
@@ -280,6 +294,9 @@ files:
|
|
280
294
|
- lib/sniffer/config.rb
|
281
295
|
- lib/sniffer/data.rb
|
282
296
|
- lib/sniffer/data_item.rb
|
297
|
+
- lib/sniffer/middleware/chain.rb
|
298
|
+
- lib/sniffer/middleware/entry.rb
|
299
|
+
- lib/sniffer/middleware/logger.rb
|
283
300
|
- lib/sniffer/request_policy.rb
|
284
301
|
- lib/sniffer/version.rb
|
285
302
|
- sniffer.gemspec
|
@@ -302,8 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
319
|
- !ruby/object:Gem::Version
|
303
320
|
version: '0'
|
304
321
|
requirements: []
|
305
|
-
|
306
|
-
rubygems_version: 2.7.4
|
322
|
+
rubygems_version: 3.0.3
|
307
323
|
signing_key:
|
308
324
|
specification_version: 4
|
309
325
|
summary: Analyze HTTP Requests
|