httplog 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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>