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,25 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(::HTTP::Client) && defined?(::HTTP::Connection)
2
- module ::HTTP
4
+ module ::HTTP # rubocop:disable Style/ClassAndModuleChildren
3
5
  class Client
4
-
5
- #
6
6
  request_method = respond_to?('make_request') ? 'make_request' : 'perform'
7
7
  orig_request_method = "orig_#{request_method}"
8
8
  alias_method(orig_request_method, request_method) unless method_defined?(orig_request_method)
9
9
 
10
10
  define_method request_method do |req, options|
11
-
12
11
  log_enabled = HttpLog.url_approved?(req.uri)
13
12
 
14
13
  if log_enabled
15
14
  HttpLog.log_request(req.verb, req.uri)
16
15
  HttpLog.log_headers(req.headers.to_h)
17
16
 
18
- if defined?(::HTTP::Request::Body)
19
- body = req.body.respond_to?(:source) ? req.body.source : req.body.instance_variable_get(:@body)
20
- else
21
- body = req.body
22
- end
17
+ body = if defined?(::HTTP::Request::Body)
18
+ req.body.respond_to?(:source) ? req.body.source : req.body.instance_variable_get(:@body)
19
+ else
20
+ req.body
21
+ end
23
22
 
24
23
  HttpLog.log_data(body.to_s)
25
24
  body.rewind if body.respond_to?(:rewind)
@@ -43,7 +42,7 @@ if defined?(::HTTP::Client) && defined?(::HTTP::Connection)
43
42
  end
44
43
 
45
44
  class Connection
46
- alias_method(:orig_initialize, :initialize) unless method_defined?(:orig_initialize)
45
+ alias orig_initialize initialize unless method_defined?(:orig_initialize)
47
46
 
48
47
  def initialize(req, options)
49
48
  HttpLog.log_connection(req.uri.host, req.uri.port) if HttpLog.url_approved?(req.uri)
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(::HTTPClient)
2
4
  class HTTPClient
3
5
  private
4
- alias_method :orig_do_get_block, :do_get_block
6
+
7
+ alias orig_do_get_block do_get_block
5
8
 
6
9
  def do_get_block(req, proxy, conn, &block)
7
10
  log_enabled = HttpLog.url_approved?(req.header.request_uri)
@@ -32,11 +35,11 @@ if defined?(::HTTPClient)
32
35
  conn.push(res)
33
36
  end
34
37
 
35
- raise retryable_response if retryable_response != nil
38
+ raise retryable_response unless retryable_response.nil?
36
39
  end
37
40
 
38
41
  class Session
39
- alias_method :orig_create_socket, :create_socket
42
+ alias orig_create_socket create_socket
40
43
 
41
44
  # up to version 2.6, the method signature is `create_socket(site)`; after that,
42
45
  # it's `create_socket(hort, port)`
@@ -53,7 +56,7 @@ if defined?(::HTTPClient)
53
56
  if HttpLog.url_approved?("#{host}:#{port}")
54
57
  HttpLog.log_connection(host, port)
55
58
  end
56
- orig_create_socket(host,port)
59
+ orig_create_socket(host, port)
57
60
  end
58
61
  end
59
62
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Net
2
4
  class HTTP
3
- alias_method(:orig_request, :request) unless method_defined?(:orig_request)
4
- alias_method(:orig_connect, :connect) unless method_defined?(:orig_connect)
5
+ alias orig_request request unless method_defined?(:orig_request)
6
+ alias orig_connect connect unless method_defined?(:orig_connect)
5
7
 
6
8
  def request(req, body = nil, &block)
7
-
8
9
  url = "http://#{@address}:#{@port}#{req.path}"
9
10
 
10
11
  log_enabled = HttpLog.url_approved?(url)
@@ -14,7 +15,7 @@ module Net
14
15
  HttpLog.log_headers(req.each_header.collect)
15
16
  # A bit convoluted becase post_form uses form_data= to assign the data, so
16
17
  # in that case req.body will be empty.
17
- HttpLog::log_data(req.body.nil? || req.body.size == 0 ? body : req.body) #if req.method == 'POST'
18
+ HttpLog.log_data(req.body.nil? || req.body.empty? ? body : req.body) # if req.method == 'POST'
18
19
  end
19
20
 
20
21
  bm = Benchmark.realtime do
@@ -38,5 +39,4 @@ module Net
38
39
  orig_connect
39
40
  end
40
41
  end
41
-
42
42
  end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(Patron)
2
4
  module Patron
3
5
  class Session
4
- alias_method :orig_request, :request
6
+ alias orig_request request
5
7
  def request(action_name, url, headers, options = {})
6
8
  log_enabled = HttpLog.url_approved?(url)
7
9
 
8
10
  if log_enabled
9
11
  HttpLog.log_request(action_name, url)
10
12
  HttpLog.log_headers(headers)
11
- HttpLog.log_data(options[:data])# if action_name == :post
13
+ HttpLog.log_data(options[:data]) # if action_name == :post
12
14
  end
13
15
 
14
16
  bm = Benchmark.realtime do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HttpLog
2
4
  class Configuration
3
5
  attr_accessor :enabled,
@@ -12,7 +14,6 @@ module HttpLog
12
14
  :log_status,
13
15
  :log_response,
14
16
  :log_benchmark,
15
- :compact_log,
16
17
  :url_whitelist_pattern,
17
18
  :url_blacklist_pattern,
18
19
  :color,
@@ -33,7 +34,6 @@ module HttpLog
33
34
  @log_status = true
34
35
  @log_response = true
35
36
  @log_benchmark = true
36
- @compact_log = false
37
37
  @url_whitelist_pattern = /.*/
38
38
  @url_blacklist_pattern = nil
39
39
  @color = false
@@ -44,9 +44,8 @@ module HttpLog
44
44
 
45
45
  # TODO: remove in 1.0.0
46
46
  def []=(key, value)
47
- $stderr.puts "DEPRECATION WARNING: Assignment to HttpLog.options will be removed in version 1.0.0. Please use HttpLog.configure block instead as described here: https://github.com/trusche/httplog#configuration"
48
- self.send("#{key.to_s}=", value)
47
+ warn 'DEPRECATION WARNING: Assignment to HttpLog.options will be removed in version 1.0.0. Please use HttpLog.configure block instead as described here: https://github.com/trusche/httplog#configuration'
48
+ send("#{key}=", value)
49
49
  end
50
-
51
50
  end
52
51
  end
@@ -1,21 +1,22 @@
1
- require "net/http"
2
- require "logger"
3
- require "benchmark"
4
- require "colorize"
5
- require "rack"
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'logger'
5
+ require 'benchmark'
6
+ require 'colorize'
7
+ require 'rack'
6
8
 
7
9
  module HttpLog
8
- LOG_PREFIX = "[httplog] ".freeze
10
+ LOG_PREFIX = '[httplog] '.freeze
9
11
 
10
12
  class << self
11
-
12
- attr_accessor :configuration
13
+ attr_writer :configuration
13
14
 
14
15
  def configuration
15
16
  @configuration ||= Configuration.new
16
17
  end
17
- alias_method :config, :configuration
18
- alias_method :options, :configuration # TODO: remove with 1.0.0
18
+ alias config configuration
19
+ alias options configuration # TODO: remove with 1.0.0
19
20
 
20
21
  def reset!
21
22
  @configuration = nil
@@ -37,7 +38,7 @@ module HttpLog
37
38
 
38
39
  def log_connection(host, port = nil)
39
40
  return if config.compact_log || !config.log_connect
40
- log("Connecting: #{[host, port].compact.join(":")}")
41
+ log("Connecting: #{[host, port].compact.join(':')}")
41
42
  end
42
43
 
43
44
  def log_request(method, uri)
@@ -47,7 +48,7 @@ module HttpLog
47
48
 
48
49
  def log_headers(headers = {})
49
50
  return if config.compact_log || !config.log_headers
50
- headers.each do |key,value|
51
+ headers.each do |key, value|
51
52
  log("Header: #{key}: #{value}")
52
53
  end
53
54
  end
@@ -63,36 +64,39 @@ module HttpLog
63
64
  log("Benchmark: #{seconds.to_f.round(6)} seconds")
64
65
  end
65
66
 
66
- def log_body(body, encoding = nil, content_type=nil)
67
+ def log_body(body, encoding = nil, content_type = nil)
67
68
  return if config.compact_log || !config.log_response
68
69
 
69
70
  unless text_based?(content_type)
70
- log("Response: (not showing binary data)")
71
+ log('Response: (not showing binary data)')
71
72
  return
72
73
  end
73
74
 
74
75
  if body.is_a?(Net::ReadAdapter)
75
76
  # open-uri wraps the response in a Net::ReadAdapter that defers reading
76
77
  # the content, so the reponse body is not available here.
77
- log("Response: (not available yet)")
78
+ log('Response: (not available yet)')
78
79
  return
79
80
  end
80
81
 
81
82
  if encoding =~ /gzip/ && body && !body.empty?
82
- sio = StringIO.new( body.to_s )
83
- gz = Zlib::GzipReader.new( sio )
84
- body = gz.read
83
+ begin
84
+ sio = StringIO.new(body.to_s)
85
+ gz = Zlib::GzipReader.new(sio)
86
+ body = gz.read
87
+ rescue Zlib::GzipFile::Error => e
88
+ log("(gzip decompression failed)")
89
+ end
85
90
  end
86
91
 
87
92
  data = utf_encoded(body.to_s, content_type)
88
93
 
89
94
  if config.prefix_response_lines
90
- log("Response:")
95
+ log('Response:')
91
96
  log_data_lines(data)
92
97
  else
93
98
  log("Response:\n#{data}")
94
99
  end
95
-
96
100
  end
97
101
 
98
102
  def log_data(data)
@@ -100,7 +104,7 @@ module HttpLog
100
104
  data = utf_encoded(data.to_s.dup)
101
105
 
102
106
  if config.prefix_data_lines
103
- log("Data:")
107
+ log('Data:')
104
108
  log_data_lines(data)
105
109
  else
106
110
  log("Data: #{data}")
@@ -120,10 +124,14 @@ module HttpLog
120
124
 
121
125
  private
122
126
 
123
- def utf_encoded(data, content_type=nil)
127
+ def utf_encoded(data, content_type = nil)
124
128
  charset = content_type.to_s.scan(/; charset=(\S+)/).flatten.first || 'UTF-8'
125
- data.force_encoding(charset) rescue data.force_encoding('UTF-8')
126
- data.encode('UTF-8', :invalid => :replace, :undef => :replace)
129
+ begin
130
+ data.force_encoding(charset)
131
+ rescue StandardError
132
+ data.force_encoding('UTF-8')
133
+ end
134
+ data.encode('UTF-8', invalid: :replace, undef: :replace)
127
135
  end
128
136
 
129
137
  def text_based?(content_type)
@@ -131,7 +139,7 @@ module HttpLog
131
139
  # it will allow application/json and the like without having to resort to more
132
140
  # heavy-handed checks.
133
141
  content_type =~ /^text/ ||
134
- content_type =~ /^application/ && content_type != 'application/octet-stream'
142
+ content_type =~ /^application/ && content_type != 'application/octet-stream'
135
143
  end
136
144
 
137
145
  def log_data_lines(data)
@@ -151,6 +159,5 @@ module HttpLog
151
159
  config.prefix.to_s
152
160
  end
153
161
  end
154
-
155
162
  end
156
163
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HttpLog
2
- VERSION = "1.0.2"
4
+ VERSION = '1.0.3'.freeze
3
5
  end
@@ -1,20 +1,22 @@
1
- require "ethon"
1
+ # frozen_string_literal: true
2
+
3
+ require 'ethon'
2
4
  class EthonAdapter < HTTPBaseAdapter
3
5
  def send_get_request
4
6
  easy = Ethon::Easy.new
5
- easy.http_request(parse_uri.to_s, :get, { headers: @headers })
7
+ easy.http_request(parse_uri.to_s, :get, headers: @headers)
6
8
  easy.perform
7
9
  end
8
10
 
9
11
  def send_head_request
10
12
  easy = Ethon::Easy.new
11
- easy.http_request(parse_uri.to_s, :head, { headers: @headers })
13
+ easy.http_request(parse_uri.to_s, :head, headers: @headers)
12
14
  easy.perform
13
15
  end
14
16
 
15
17
  def send_post_request
16
18
  easy = Ethon::Easy.new
17
- easy.http_request(parse_uri.to_s, :post, { headers: @headers, body: @data })
19
+ easy.http_request(parse_uri.to_s, :post, headers: @headers, body: @data)
18
20
  easy.perform
19
21
  end
20
22
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'excon'
2
4
  class ExconAdapter < HTTPBaseAdapter
3
5
  def send_get_request
4
- Excon.get(parse_uri.to_s, headers: @headers )
6
+ Excon.get(parse_uri.to_s, headers: @headers)
5
7
  end
6
8
 
7
9
  def send_head_request
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  class FaradayAdapter < HTTPBaseAdapter
3
5
  def send_get_request
@@ -47,7 +49,7 @@ class FaradayAdapter < HTTPBaseAdapter
47
49
  faraday.request :multipart
48
50
  faraday.request :url_encoded
49
51
 
50
- faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
52
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
51
53
  end
52
54
  end
53
55
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'http'
2
4
  class HTTPAdapter < HTTPBaseAdapter
3
5
  def send_get_request
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class HTTPBaseAdapter
2
- def initialize(host, port, path, headers, data, params, protocol = 'http')
3
- @host = host
4
- @port = port
5
- @path = path
6
- @headers = headers
7
- @data = data
8
- @params = params
9
- @protocol = protocol
4
+ def initialize(options = {})
5
+ @host = options.fetch(:host, 'localhost')
6
+ @port = options.fetch(:port, 80)
7
+ @path = options.fetch(:path, '/')
8
+ @headers = options.fetch(:headers, {})
9
+ @data = options.fetch(:data, nil)
10
+ @params = options.fetch(:params, {})
11
+ @protocol = options.fetch(:protocol, 'http')
10
12
  end
11
13
 
12
14
  def logs_data?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'httparty'
2
4
  class HTTPartyAdapter < HTTPBaseAdapter
3
5
  def send_get_request
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class HTTPClientAdapter < HTTPBaseAdapter
2
4
  def send_get_request
3
5
  ::HTTPClient.get(parse_uri, header: @headers)
@@ -1,19 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class NetHTTPAdapter < HTTPBaseAdapter
2
4
  def send_get_request
3
5
  Net::HTTP.get_response(@host, [@path, @data].compact.join('?'), @port)
4
6
  end
5
7
 
6
8
  def send_head_request
7
- http = Net::HTTP.new(@host, @port)
8
- http.head(@path, @headers)
9
+ Net::HTTP.new(@host, @port).head(@path, @headers)
9
10
  end
10
11
 
11
12
  def send_post_request
12
- http = Net::HTTP.new(@host, @port)
13
- resp = http.post(@path, @data)
13
+ Net::HTTP.new(@host, @port).post(@path, @data)
14
14
  end
15
15
 
16
16
  def send_post_form_request
17
- res = Net::HTTP.post_form(parse_uri, @params)
17
+ Net::HTTP.post_form(parse_uri, @params)
18
18
  end
19
19
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class OpenUriAdapter < HTTPBaseAdapter
2
4
  def send_get_request
3
- open(parse_uri)
5
+ open(parse_uri) # rubocop:disable Security/Open
4
6
  end
5
7
 
6
8
  def expected_response_body
7
- " (not available yet)"
9
+ ' (not available yet)'
8
10
  end
9
11
 
10
12
  def self.should_log_headers?