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,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?