httplog 1.0.2 → 1.0.3

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +55 -0
  3. data/.rubocop_todo.yml +36 -0
  4. data/.travis.yml +0 -1
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +2 -2
  7. data/Guardfile +10 -9
  8. data/README.md +7 -1
  9. data/Rakefile +7 -5
  10. data/gemfiles/http2.gemfile +5 -3
  11. data/gemfiles/http3.gemfile +5 -3
  12. data/gemfiles/http4.gemfile +5 -3
  13. data/gemfiles/rack1.gemfile +5 -3
  14. data/gemfiles/rack2.gemfile +5 -3
  15. data/httplog.gemspec +29 -28
  16. data/lib/httplog.rb +11 -9
  17. data/lib/httplog/adapters/ethon.rb +7 -9
  18. data/lib/httplog/adapters/excon.rb +9 -11
  19. data/lib/httplog/adapters/http.rb +9 -10
  20. data/lib/httplog/adapters/httpclient.rb +7 -4
  21. data/lib/httplog/adapters/net_http.rb +5 -5
  22. data/lib/httplog/adapters/patron.rb +4 -2
  23. data/lib/httplog/configuration.rb +4 -5
  24. data/lib/httplog/http_log.rb +33 -26
  25. data/lib/httplog/version.rb +3 -1
  26. data/spec/adapters/ethon_adapter.rb +6 -4
  27. data/spec/adapters/excon_adapter.rb +3 -1
  28. data/spec/adapters/faraday_adapter.rb +3 -1
  29. data/spec/adapters/http_adapter.rb +2 -0
  30. data/spec/adapters/http_base_adapter.rb +10 -8
  31. data/spec/adapters/httparty_adapter.rb +2 -0
  32. data/spec/adapters/httpclient_adapter.rb +2 -0
  33. data/spec/adapters/net_http_adapter.rb +5 -5
  34. data/spec/adapters/open_uri_adapter.rb +4 -2
  35. data/spec/adapters/patron_adapter.rb +4 -2
  36. data/spec/adapters/typhoeus_adapter.rb +2 -1
  37. data/spec/configuration_spec.rb +5 -6
  38. data/spec/lib/http_client_spec.rb +15 -0
  39. data/spec/lib/http_log_spec.rb +333 -0
  40. data/spec/spec_helper.rb +7 -7
  41. data/spec/support/not_gzipped.html.gz +8 -0
  42. data/spec/support/test_server.rb +16 -14
  43. metadata +43 -39
  44. data/spec/http_log_spec.rb +0 -358
@@ -1,4 +1,6 @@
1
- require "patron"
1
+ # frozen_string_literal: true
2
+
3
+ require 'patron'
2
4
  class PatronAdapter < HTTPBaseAdapter
3
5
  def send_get_request
4
6
  session = Patron::Session.new
@@ -25,7 +27,7 @@ class PatronAdapter < HTTPBaseAdapter
25
27
  file = @params.delete('file')
26
28
 
27
29
  session = Patron::Session.new
28
- session.post_multipart(parse_uri.to_s, data, {file: file.path}, @headers)
30
+ session.post_multipart(parse_uri.to_s, data, { file: file.path }, @headers)
29
31
  end
30
32
 
31
33
  def self.is_libcurl?
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'excon'
2
4
  class TyphoeusAdapter < HTTPBaseAdapter
3
-
4
5
  def send_get_request
5
6
  Typhoeus.get(parse_uri.to_s, headers: @headers)
6
7
  end
@@ -1,20 +1,19 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
5
  module HttpLog
6
6
  describe Configuration do
7
-
8
7
  let(:config) { Configuration.new }
9
8
 
10
- describe "#compact_log" do
11
- it "defaults to false" do
9
+ describe '#compact_log' do
10
+ it 'defaults to false' do
12
11
  expect(config.compact_log).to eq(false)
13
12
  end
14
13
  end
15
14
 
16
- describe "#compact_log=" do
17
- it "sets values" do
15
+ describe '#compact_log=' do
16
+ it 'sets values' do
18
17
  config.compact_log = true
19
18
  expect(config.compact_log).to eq(true)
20
19
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe HTTPClient do
6
+ let(:client) { HTTPClient.new }
7
+
8
+ it 'works with transparent_gzip_decompression' do
9
+ client.transparent_gzip_decompression = true
10
+ expect { client.get("http://localhost:9292/index.html.gz") }.to_not(raise_error)
11
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Status: 200')
12
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Data:')
13
+ expect(log).to include(HttpLog::LOG_PREFIX + "Response:\n<html>")
14
+ end
15
+ end
@@ -0,0 +1,333 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe HttpLog do
6
+ let(:host) { 'localhost' }
7
+ let(:port) { 9292 }
8
+ let(:path) { '/index.html' }
9
+ let(:headers) { { 'accept' => '*/*', 'foo' => 'bar' } }
10
+ let(:data) { 'foo=bar&bar=foo' }
11
+ let(:params) { { 'foo' => 'bar:form-data', 'bar' => 'foo' } }
12
+
13
+ ADAPTERS = [
14
+ NetHTTPAdapter,
15
+ OpenUriAdapter,
16
+ HTTPClientAdapter,
17
+ HTTPartyAdapter,
18
+ FaradayAdapter,
19
+ ExconAdapter,
20
+ EthonAdapter,
21
+ PatronAdapter,
22
+ HTTPAdapter
23
+ ].freeze
24
+
25
+ ADAPTERS.each do |adapter_class|
26
+ context adapter_class, adapter: adapter_class.to_s do
27
+ let(:adapter) { adapter_class.new(host: host, port: port, path: path, headers: headers, data: data, params: params) }
28
+
29
+ context 'with default configuration' do
30
+ connection_test_method = adapter_class.is_libcurl? ? :to_not : :to
31
+
32
+ if adapter_class.method_defined? :send_get_request
33
+ it 'should log GET requests' do
34
+ res = adapter.send_get_request
35
+
36
+ expect(log).send(connection_test_method, include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}"))
37
+
38
+ expect(log).to include(HttpLog::LOG_PREFIX + "Sending: GET http://#{host}:#{port}#{path}")
39
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Data:')
40
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
41
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Status: 200')
42
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Benchmark: ')
43
+ expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
44
+
45
+ expect(log.colorized?).to be_falsey
46
+
47
+ expect(res).to be_a adapter.response if adapter.respond_to? :response
48
+ end
49
+
50
+ context 'with gzip encoding' do
51
+ let(:path) { '/index.html.gz' }
52
+ let(:data) { nil }
53
+
54
+ it 'decompresses gzipped response body' do
55
+ adapter.send_get_request
56
+ expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
57
+ end
58
+
59
+ if adapter_class.method_defined? :send_head_request
60
+ it "doesn't try to decompress body for HEAD requests" do
61
+ adapter.send_head_request
62
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'with UTF-8 response body' do
68
+ let(:path) { '/utf8.html' }
69
+ let(:data) { nil }
70
+
71
+ it 'works' do
72
+ adapter.send_get_request
73
+ expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
74
+ if adapter.logs_data?
75
+ expect(log).to include(' <title>Блог Яндекса</title>')
76
+ end
77
+ end
78
+ end
79
+
80
+ context 'with binary response body' do
81
+ let(:path) { '/test.bin' }
82
+ let(:data) { nil }
83
+
84
+ it "doesn't log response" do
85
+ adapter.send_get_request
86
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response: (not showing binary data)')
87
+ end
88
+ end
89
+ end
90
+
91
+ if adapter_class.method_defined? :send_post_request
92
+ it 'logs POST requests' do
93
+ res = adapter.send_post_request
94
+
95
+ expect(log).send(connection_test_method, include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}"))
96
+
97
+ expect(log).to include(HttpLog::LOG_PREFIX + "Sending: POST http://#{host}:#{port}#{path}")
98
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Data: foo=bar&bar=foo')
99
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
100
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Status: 200')
101
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Benchmark: ')
102
+ expect(log).to include(HttpLog::LOG_PREFIX + "Response:#{adapter.expected_response_body}")
103
+ expect(log.colorized?).to be_falsey
104
+
105
+ expect(res).to be_a adapter.response if adapter.respond_to? :response
106
+ end
107
+
108
+ context 'with non-UTF request data' do
109
+ let(:data) { "a UTF-8 striñg with an 8BIT-ASCII character: \xC3" }
110
+ it 'does not raise and error' do
111
+ expect { adapter.send_post_request }.to_not raise_error
112
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
113
+ end
114
+ end
115
+
116
+ context 'with URI encoded non-UTF data' do
117
+ let(:data) { 'a UTF-8 striñg with a URI encoded 8BIT-ASCII character: %c3' }
118
+ it 'does not raise and error' do
119
+ expect { adapter.send_post_request }.to_not raise_error
120
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ context 'with custom configuration' do
127
+ context 'GET requests' do
128
+ it 'should not log anything unless enabled is set' do
129
+ HttpLog.configure { |c| c.enabled = false }
130
+ adapter.send_get_request
131
+ expect(log).to eq('')
132
+ end
133
+
134
+ it 'should log at other levels' do
135
+ HttpLog.configure { |c| c.severity = Logger::Severity::INFO }
136
+ adapter.send_get_request
137
+ expect(log).to include('INFO')
138
+ end
139
+
140
+ it 'should log headers if enabled' do
141
+ HttpLog.configure { |c| c.log_headers = true }
142
+ adapter.send_get_request
143
+ # request header
144
+ expect(log.downcase).to include(HttpLog::LOG_PREFIX + 'Header: accept: */*'.downcase)
145
+ # response header
146
+ expect(log.downcase).to include(HttpLog::LOG_PREFIX + 'Header: server: thin'.downcase)
147
+ end
148
+
149
+ it 'should not log headers if disabled' do
150
+ HttpLog.configure { |c| c.log_headers = false }
151
+ adapter.send_get_request
152
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Header:')
153
+ end
154
+
155
+ it 'should log the request if url does not match blacklist pattern' do
156
+ HttpLog.configure { |c| c.url_blacklist_pattern = /example.com/ }
157
+ adapter.send_get_request
158
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Sending: GET')
159
+ end
160
+
161
+ it 'should log the request if url matches whitelist pattern and not the blacklist pattern' do
162
+ HttpLog.configure { |c| c.url_blacklist_pattern = /example.com/ }
163
+ HttpLog.configure { |c| c.url_whitelist_pattern = /#{host}:#{port}/ }
164
+ adapter.send_get_request
165
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Sending: GET')
166
+ end
167
+
168
+ it 'should not log the request if url matches blacklist pattern' do
169
+ HttpLog.configure { |c| c.url_blacklist_pattern = /#{host}:#{port}/ }
170
+ adapter.send_get_request
171
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
172
+ end
173
+
174
+ it 'should not log the request if url does not match whitelist pattern' do
175
+ HttpLog.configure { |c| c.url_whitelist_pattern = /example.com/ }
176
+ adapter.send_get_request
177
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
178
+ end
179
+
180
+ it 'should not log the request if url matches blacklist pattern and the whitelist pattern' do
181
+ HttpLog.configure { |c| c.url_blacklist_pattern = /#{host}:#{port}/ }
182
+ HttpLog.configure { |c| c.url_whitelist_pattern = /#{host}:#{port}/ }
183
+ adapter.send_get_request
184
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
185
+ end
186
+
187
+ it 'should not log the request if disabled' do
188
+ HttpLog.configure { |c| c.log_request = false }
189
+ adapter.send_get_request
190
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Sending: GET')
191
+ end
192
+
193
+ it 'should not log the connection if disabled' do
194
+ HttpLog.configure { |c| c.log_connect = false }
195
+ adapter.send_get_request
196
+ expect(log).to_not include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}")
197
+ end
198
+
199
+ it 'should not log data if disabled' do
200
+ HttpLog.configure { |c| c.log_data = false }
201
+ adapter.send_get_request
202
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
203
+ end
204
+
205
+ it 'should colorized output' do
206
+ HttpLog.configure { |c| c.color = :red }
207
+ adapter.send_get_request
208
+ expect(log.colorized?).to be_truthy
209
+ end
210
+
211
+ it 'should log with custom string prefix' do
212
+ HttpLog.configure { |c| c.prefix = '[my logger]' }
213
+ adapter.send_get_request
214
+ expect(log).to include('[my logger]')
215
+ expect(log).to_not include(HttpLog::LOG_PREFIX)
216
+ end
217
+
218
+ it 'should log with custom lambda prefix' do
219
+ HttpLog.configure { |c| c.prefix = -> { '[custom prefix]' } }
220
+ adapter.send_get_request
221
+ expect(log).to include('[custom prefix]')
222
+ expect(log).to_not include(HttpLog::LOG_PREFIX)
223
+ end
224
+ end
225
+
226
+ context 'POST requests' do
227
+ if adapter_class.method_defined? :send_post_request
228
+ it 'should not log data if disabled' do
229
+ HttpLog.configure { |c| c.log_data = false }
230
+ adapter.send_post_request
231
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
232
+ end
233
+
234
+ it 'should not log the response if disabled' do
235
+ HttpLog.configure { |c| c.log_response = false }
236
+ adapter.send_post_request
237
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
238
+ end
239
+
240
+ it 'should prefix all response lines' do
241
+ HttpLog.configure { |c| c.prefix_response_lines = true }
242
+
243
+ adapter.send_post_request
244
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
245
+ expect(log).to include(HttpLog::LOG_PREFIX + '<html>')
246
+ end
247
+
248
+ it 'should prefix all response lines with line numbers' do
249
+ HttpLog.configure { |c| c.prefix_response_lines = true }
250
+ HttpLog.configure { |c| c.prefix_line_numbers = true }
251
+
252
+ adapter.send_post_request
253
+ expect(log).to include(HttpLog::LOG_PREFIX + 'Response:')
254
+ expect(log).to include(HttpLog::LOG_PREFIX + '1: <html>')
255
+ end
256
+
257
+ it 'should not log the benchmark if disabled' do
258
+ HttpLog.configure { |c| c.log_benchmark = false }
259
+ adapter.send_post_request
260
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
261
+ end
262
+
263
+ it 'should colorized output' do
264
+ HttpLog.configure { |c| c.color = :red }
265
+ adapter.send_post_request
266
+ expect(log.colorized?).to be_truthy
267
+ end
268
+ end
269
+ end
270
+
271
+ context 'POST form data requests' do
272
+ if adapter_class.method_defined? :send_post_form_request
273
+ it 'should not log data if disabled' do
274
+ HttpLog.configure { |c| c.log_data = false }
275
+ adapter.send_post_form_request
276
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
277
+ end
278
+
279
+ it 'should not log the response if disabled' do
280
+ HttpLog.configure { |c| c.log_response = false }
281
+ adapter.send_post_form_request
282
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
283
+ end
284
+
285
+ it 'should not log the benchmark if disabled' do
286
+ HttpLog.configure { |c| c.log_benchmark = false }
287
+ adapter.send_post_form_request
288
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
289
+ end
290
+ end
291
+ end
292
+
293
+ context 'POST multi-part requests (file upload)' do
294
+ let(:upload) { Tempfile.new('http-log') }
295
+ let(:params) { { 'foo' => 'bar', 'file' => upload } }
296
+
297
+ if adapter_class.method_defined? :send_multipart_post_request
298
+ it 'should not log data if disabled' do
299
+ HttpLog.configure { |c| c.log_data = false }
300
+ adapter.send_multipart_post_request
301
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
302
+ end
303
+
304
+ it 'should not log the response if disabled' do
305
+ HttpLog.configure { |c| c.log_response = false }
306
+ adapter.send_multipart_post_request
307
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Reponse:')
308
+ end
309
+
310
+ it 'should not log the benchmark if disabled' do
311
+ HttpLog.configure { |c| c.log_benchmark = false }
312
+ adapter.send_multipart_post_request
313
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark:')
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ context 'with compact config' do
320
+ before(:each) { HttpLog.configure { |c| c.compact_log = true } }
321
+
322
+ it 'should log a single line with status and benchmark' do
323
+ adapter.send_get_request
324
+ expect(log).to match(%r{\[httplog\] GET http://#{host}:#{port}#{path}(\?.*)? completed with status code \d{3} in (\d|\.)+})
325
+ expect(log).to_not include(HttpLog::LOG_PREFIX + "Connecting: #{host}:#{port}")
326
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Response:')
327
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Data:')
328
+ expect(log).to_not include(HttpLog::LOG_PREFIX + 'Benchmark: ')
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $:.unshift(File.dirname(__FILE__))
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
5
  require 'rspec'
4
6
  require 'httpclient'
5
7
  require 'excon'
@@ -15,30 +17,28 @@ require 'httplog'
15
17
 
16
18
  require 'adapters/http_base_adapter'
17
19
  Dir[File.dirname(__FILE__) + '/adapters/*.rb'].each { |f| require f }
18
- Dir["./spec/support/**/*.rb"].each {|f| require f}
20
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
19
21
 
20
22
  # Start a local rack server to serve up test pages.
21
23
  @server_thread = Thread.new do
22
- Rack::Handler::Thin.run Httplog::Test::Server.new, :Port => 9292
24
+ Rack::Handler::Thin.run Httplog::Test::Server.new, Port: 9292
23
25
  end
24
26
  sleep(3) # wait a moment for the server to be booted
25
27
 
26
28
  RSpec.configure do |config|
27
-
28
29
  config.before(:each) do
29
30
  require 'stringio'
30
31
 
31
32
  @log = StringIO.new
32
33
  @logger = Logger.new @log
33
34
 
34
- HttpLog.configure{ |c| c.logger = @logger }
35
+ HttpLog.configure { |c| c.logger = @logger }
35
36
  end
36
37
 
37
38
  config.after(:each) do
38
39
  HttpLog.reset!
39
40
  end
40
41
 
41
-
42
42
  def log
43
43
  @log.string
44
44
  end
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Test Page</title>
4
+ </head>
5
+ <body>
6
+ <h1>This is the test page.</h1>
7
+ </body>
8
+ </html>