http_event_logger 0.1.0.rc1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/lib/http_event_logger/adapter/ethon.rb +56 -0
- data/lib/http_event_logger/adapter/excon.rb +64 -0
- data/lib/http_event_logger/adapter/httpclient.rb +60 -0
- data/lib/http_event_logger/adapter/net_http.rb +65 -0
- data/lib/http_event_logger/adapter/patron.rb +40 -0
- data/lib/http_event_logger/configuration.rb +9 -0
- data/lib/http_event_logger/event/connection.rb +21 -0
- data/lib/http_event_logger/event/headers.rb +21 -0
- data/lib/http_event_logger/event/observer.rb +13 -0
- data/lib/http_event_logger/event/request.rb +24 -0
- data/lib/http_event_logger/event/response.rb +47 -0
- data/lib/http_event_logger/logger.rb +47 -0
- data/lib/http_event_logger/version.rb +3 -0
- data/lib/http_event_logger.rb +43 -0
- data/spec/http_event_logger_integration_spec.rb +151 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/custom_logger.rb +25 -0
- data/spec/support/driver/base.rb +48 -0
- data/spec/support/driver/ethon.rb +29 -0
- data/spec/support/driver/excon.rb +21 -0
- data/spec/support/driver/faraday.rb +36 -0
- data/spec/support/driver/httparty.rb +21 -0
- data/spec/support/driver/httpclient.rb +29 -0
- data/spec/support/driver/net_http.rb +24 -0
- data/spec/support/driver/open_uri.rb +19 -0
- data/spec/support/driver/patron.rb +27 -0
- data/spec/support/driver/typhoeus.rb +34 -0
- data/spec/support/index.html +8 -0
- data/spec/support/server.rb +28 -0
- metadata +299 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
describe HttpEventLogger do
|
2
|
+
|
3
|
+
let(:host) { "localhost" }
|
4
|
+
let(:port) { 9292 }
|
5
|
+
let(:path) { "/index.html" }
|
6
|
+
let(:data) { "foo=bar&bar=foo" }
|
7
|
+
|
8
|
+
DRIVERS = [
|
9
|
+
HttpEventLogger::Test::Driver::Ethon,
|
10
|
+
HttpEventLogger::Test::Driver::Excon,
|
11
|
+
HttpEventLogger::Test::Driver::Faraday,
|
12
|
+
HttpEventLogger::Test::Driver::HTTParty,
|
13
|
+
HttpEventLogger::Test::Driver::HTTPClient,
|
14
|
+
HttpEventLogger::Test::Driver::NetHTTP,
|
15
|
+
HttpEventLogger::Test::Driver::OpenUri,
|
16
|
+
HttpEventLogger::Test::Driver::Patron,
|
17
|
+
HttpEventLogger::Test::Driver::Typhoeus
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
DRIVERS.each do |driver_class|
|
21
|
+
|
22
|
+
connection_event_supported = !driver_class.is_libcurl?
|
23
|
+
|
24
|
+
context "when #{driver_class.library_name} is in use" do
|
25
|
+
|
26
|
+
let(:driver_class) { driver_class }
|
27
|
+
let(:connection_event_supported) { connection_event_supported }
|
28
|
+
let(:expected_response_type) { driver_class.expected_response_type }
|
29
|
+
let(:driver) { driver_class.new(host, port, path) }
|
30
|
+
|
31
|
+
context "and the defaults are configured" do
|
32
|
+
|
33
|
+
it "logs GET requests" do
|
34
|
+
res = driver.send_get_request
|
35
|
+
|
36
|
+
expect(log).to include_message("Connected") if connection_event_supported
|
37
|
+
|
38
|
+
expect(log).to include_message("Sent - GET http://#{host}:#{port}#{path}")
|
39
|
+
expect(log).to include_message("Sent - Headers:")
|
40
|
+
expect(log).to_not include_message("Sent - Body:")
|
41
|
+
|
42
|
+
expect(log).to include_message("Benchmark:")
|
43
|
+
expect(log).to include_message("Received - Status: 200")
|
44
|
+
expect(log).to include_message("Received - Headers:")
|
45
|
+
expect(log).to include_message("Received - Body:#{driver_class.expected_response_body}")
|
46
|
+
|
47
|
+
expect(res).to be_a(expected_response_type) if expected_response_type
|
48
|
+
end if driver_class.method_defined?(:send_get_request)
|
49
|
+
|
50
|
+
it "logs POST requests" do
|
51
|
+
res = driver.send_post_request
|
52
|
+
|
53
|
+
expect(log).to include_message("Connected") if connection_event_supported
|
54
|
+
|
55
|
+
expect(log).to include_message("Sent - POST http://#{host}:#{port}#{path}")
|
56
|
+
expect(log).to include_message("Sent - Headers:")
|
57
|
+
expect(log).to include_message("Sent - Body: #{data}")
|
58
|
+
|
59
|
+
expect(log).to include_message("Benchmark:")
|
60
|
+
expect(log).to include_message("Received - Status: 200")
|
61
|
+
expect(log).to include_message("Received - Headers:")
|
62
|
+
expect(log).to include_message("Received - Body:#{driver_class.expected_response_body}")
|
63
|
+
|
64
|
+
expect(res).to be_a(expected_response_type) if expected_response_type
|
65
|
+
end if driver_class.method_defined?(:send_post_request)
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
context "and the default logger is configured with a custom log level" do
|
70
|
+
|
71
|
+
before(:example) { configure(HttpEventLogger::Logger.new(logger: @logger, severity: ::Logger::Severity::INFO)) }
|
72
|
+
|
73
|
+
it "logs at the configured level" do
|
74
|
+
driver.send_get_request
|
75
|
+
|
76
|
+
expect(log).to include("INFO")
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
context "and the default logger is configured with a uri blacklist pattern" do
|
82
|
+
|
83
|
+
before(:example) do
|
84
|
+
configure(HttpEventLogger::Logger.new(logger: @logger, blacklist_pattern: blacklist_pattern))
|
85
|
+
end
|
86
|
+
|
87
|
+
context "and a request is made matching the pattern" do
|
88
|
+
|
89
|
+
let(:blacklist_pattern) { /localhost/ }
|
90
|
+
|
91
|
+
it "should not log anything" do
|
92
|
+
driver.send_get_request
|
93
|
+
|
94
|
+
expect(log).to be_empty
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
context "and a request is made that does not match the pattern" do
|
100
|
+
|
101
|
+
let(:blacklist_pattern) { /does_not_match/ }
|
102
|
+
|
103
|
+
it "logs all events" do
|
104
|
+
driver.send_get_request
|
105
|
+
|
106
|
+
expect(log).to include_message("Sent")
|
107
|
+
expect(log).to include_message("Benchmark")
|
108
|
+
expect(log).to include_message("Received")
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context "and a custom logger is configured" do
|
116
|
+
|
117
|
+
before(:example) { configure(HttpEventLogger::Test::CustomLogger.new(@logger)) }
|
118
|
+
|
119
|
+
it "logs connection events" do
|
120
|
+
driver.send_get_request
|
121
|
+
|
122
|
+
expect(log).to include("Custom - Connected: #{host}:#{port}")
|
123
|
+
end if connection_event_supported
|
124
|
+
|
125
|
+
it "logs request events" do
|
126
|
+
driver.send_get_request
|
127
|
+
|
128
|
+
expect(log).to include("Custom - Sent: Request Event")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "logs repsonse events" do
|
132
|
+
driver.send_get_request
|
133
|
+
|
134
|
+
expect(log).to include("Custom - Received: Response Event")
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
def include_message(message)
|
144
|
+
include("[#{host}:#{port}] #{message}")
|
145
|
+
end
|
146
|
+
|
147
|
+
def configure(logger)
|
148
|
+
HttpEventLogger.configuration.logger = logger
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require(:development)
|
3
|
+
|
4
|
+
SimpleCov.start do
|
5
|
+
coverage_dir "tmp/coverage"
|
6
|
+
|
7
|
+
add_filter "/spec/"
|
8
|
+
|
9
|
+
refuse_coverage_drop
|
10
|
+
end if ENV["coverage"]
|
11
|
+
|
12
|
+
require 'stringio'
|
13
|
+
|
14
|
+
require_relative '../lib/http_event_logger'
|
15
|
+
|
16
|
+
require_relative 'support/driver/base'
|
17
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |file| require file }
|
18
|
+
|
19
|
+
# Server for test endpoints
|
20
|
+
@server_thread = Thread.new { Rack::Handler::Thin.run(HttpEventLogger::Test::Server.new, Port: 9292) }
|
21
|
+
sleep(1) # Wait for server
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
|
25
|
+
config.before(:example) do
|
26
|
+
@log = StringIO.new
|
27
|
+
@logger = ::Logger.new(@log)
|
28
|
+
|
29
|
+
HttpEventLogger.configure { |config| config.logger = HttpEventLogger::Logger.new(logger: @logger) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def log
|
33
|
+
@log.string
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HttpEventLogger
|
2
|
+
module Test
|
3
|
+
|
4
|
+
class CustomLogger < HttpEventLogger::Logger
|
5
|
+
|
6
|
+
def initialize(logger)
|
7
|
+
super(logger: logger)
|
8
|
+
end
|
9
|
+
|
10
|
+
def connected(connection)
|
11
|
+
log "Custom - Connected: #{connection.uri}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def sent(request)
|
15
|
+
log "Custom - Sent: Request Event"
|
16
|
+
end
|
17
|
+
|
18
|
+
def received(response)
|
19
|
+
log "Custom - Received: Response Event"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module HttpEventLogger
|
2
|
+
module Test
|
3
|
+
module Driver
|
4
|
+
|
5
|
+
class Base
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def library_name
|
10
|
+
self.name.demodulize
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_libcurl?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def expected_response_type
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def expected_response_body
|
22
|
+
"\n<html>"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(host, port, path, protocol="http")
|
28
|
+
@host = host
|
29
|
+
@port = port
|
30
|
+
@path = path
|
31
|
+
@protocol = protocol
|
32
|
+
@headers = { "accept" => "*/*", "foo" => "bar" }
|
33
|
+
@data = "foo=bar&bar=foo"
|
34
|
+
@params = { "foo" => 'bar', "bar" => "foo" }
|
35
|
+
end
|
36
|
+
|
37
|
+
def uri
|
38
|
+
"#{@protocol}://#{@host}:#{@port}#{@path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_post_form_request
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'ethon'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class Ethon < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def self.is_libcurl?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_get_request
|
14
|
+
easy = ::Ethon::Easy.new
|
15
|
+
easy.http_request(uri, :get, { headers: @headers })
|
16
|
+
easy.perform
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_post_request
|
20
|
+
easy = ::Ethon::Easy.new
|
21
|
+
easy.http_request(uri, :post, { headers: @headers, body: @data })
|
22
|
+
easy.perform
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'excon'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class Excon < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def send_get_request
|
10
|
+
::Excon.get(uri, headers: @headers )
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_post_request
|
14
|
+
::Excon.post(uri, body: @data, headers: @headers)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class Faraday < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def send_get_request
|
10
|
+
connection.get do |req|
|
11
|
+
req.url(uri)
|
12
|
+
req.headers = @headers
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def send_post_request
|
17
|
+
connection.post do |req|
|
18
|
+
req.url(uri)
|
19
|
+
req.headers = @headers
|
20
|
+
req.body = @data
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def connection
|
27
|
+
::Faraday.new(url: "#{@protocol}://#{@host}:#{@port}") do |faraday|
|
28
|
+
faraday.adapter(::Faraday.default_adapter) # Uses Net::HTTP
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class HTTParty < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def send_get_request
|
10
|
+
::HTTParty.get(uri, headers: @headers)
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_post_request
|
14
|
+
::HTTParty.post(uri, body: @data, headers: @headers)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class HTTPClient < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def self.expected_response_type
|
10
|
+
HTTP::Message
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_get_request
|
14
|
+
::HTTPClient.get(uri, header: @headers)
|
15
|
+
end
|
16
|
+
|
17
|
+
def send_post_request
|
18
|
+
::HTTPClient.post(uri, body: @data, header: @headers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_post_form_request(params)
|
22
|
+
::HTTPClient.post_content(uri, params, @headers)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module HttpEventLogger
|
2
|
+
module Test
|
3
|
+
module Driver
|
4
|
+
|
5
|
+
class NetHTTP < HttpEventLogger::Test::Driver::Base
|
6
|
+
|
7
|
+
def send_get_request
|
8
|
+
Net::HTTP.get_response(@host, "#{@path}?#{@data}", @port)
|
9
|
+
end
|
10
|
+
|
11
|
+
def send_post_request
|
12
|
+
http = Net::HTTP.new(@host, @port)
|
13
|
+
http.post(@path, @data)
|
14
|
+
end
|
15
|
+
|
16
|
+
def send_post_form_request
|
17
|
+
Net::HTTP.post_form(uri, @params)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HttpEventLogger
|
2
|
+
module Test
|
3
|
+
module Driver
|
4
|
+
|
5
|
+
class OpenUri < HttpEventLogger::Test::Driver::Base
|
6
|
+
|
7
|
+
def self.expected_response_body
|
8
|
+
"[not available]"
|
9
|
+
end
|
10
|
+
|
11
|
+
def send_get_request
|
12
|
+
open(uri)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'patron'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class Patron < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
def self.is_libcurl?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_get_request
|
14
|
+
session = ::Patron::Session.new
|
15
|
+
session.get(uri, @headers)
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_post_request
|
19
|
+
session = ::Patron::Session.new
|
20
|
+
session.post(uri, @data, @headers)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
module Driver
|
6
|
+
|
7
|
+
class Typhoeus < HttpEventLogger::Test::Driver::Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def is_libcurl?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# Note: Last supported Typhoeus version is 0.5.3
|
16
|
+
def expected_response_body
|
17
|
+
""
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_get_request
|
23
|
+
::Typhoeus.get(uri, headers: @headers)
|
24
|
+
end
|
25
|
+
|
26
|
+
def send_post_request
|
27
|
+
::Typhoeus.post(uri, body: @data, headers: @headers)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module HttpEventLogger
|
4
|
+
module Test
|
5
|
+
|
6
|
+
class Server
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
@root = File.expand_path(File.dirname(__FILE__))
|
10
|
+
path = Rack::Utils.unescape(env["PATH_INFO"])
|
11
|
+
path += "index.html" if path == "/"
|
12
|
+
file = @root + "#{path}"
|
13
|
+
|
14
|
+
params = Rack::Utils.parse_nested_query(env["QUERY_STRING"])
|
15
|
+
|
16
|
+
if params["redirect"]
|
17
|
+
[ 301, { "Location" => "/index.html" }, "" ]
|
18
|
+
elsif File.exists?(file)
|
19
|
+
[ 200, { "Content-Type" => "text/html" }, File.read(file) ]
|
20
|
+
else
|
21
|
+
[ 404, { "Content-Type" => "text/plain" }, "file not found" ]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|