httplog 1.2.2 → 1.3.0
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 +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +2 -3
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +2 -2
- data/README.md +45 -17
- data/gemfiles/http4.gemfile +1 -1
- data/gemfiles/{http2.gemfile → http5.gemfile} +1 -1
- data/lib/httplog/adapters/excon.rb +1 -1
- data/lib/httplog/configuration.rb +3 -7
- data/lib/httplog/http_log.rb +53 -9
- data/lib/httplog/version.rb +1 -1
- data/spec/adapters/ethon_adapter.rb +1 -1
- data/spec/adapters/excon_adapter.rb +1 -1
- data/spec/adapters/faraday_adapter.rb +5 -1
- data/spec/adapters/http_adapter.rb +1 -1
- data/spec/adapters/http_base_adapter.rb +8 -2
- data/spec/adapters/httparty_adapter.rb +1 -1
- data/spec/adapters/httpclient_adapter.rb +5 -1
- data/spec/adapters/net_http_adapter.rb +3 -1
- data/spec/adapters/open_uri_adapter.rb +1 -1
- data/spec/adapters/patron_adapter.rb +1 -1
- data/spec/adapters/typhoeus_adapter.rb +1 -1
- data/spec/lib/http_log_spec.rb +16 -7
- data/spec/support/shared_examples.rb +18 -2
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bd063a60dafd4b6bcc29fa80d877f8bd650375f4633fb0f0bc4398075677b583
|
4
|
+
data.tar.gz: 136a0fe30f033ad30f8867e327e18109255735b371cc9ab5a7d8e973d3b6e201
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4de29f881f37f1149400324e8c97de77dd7d7ef21e983dd513e411ae4c5b3d67d886807accdfddccbcc388d03e242e4597457d42783525e8ddcf8dbf9064799
|
7
|
+
data.tar.gz: 46df8a4e8dff1054f60b8545db22df35159c20ee0ab405d78795d476cc990efffd7d8cfe635f7641667d78cbac38fc0d5709ae8e802d040989356a883d3a4cd8
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.2
|
data/.travis.yml
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- "2.3.8"
|
4
3
|
- "2.4.5"
|
5
4
|
- "2.5.3"
|
6
|
-
- "2.6.
|
5
|
+
- "2.6.2"
|
7
6
|
gemfile:
|
8
|
-
- gemfiles/http2.gemfile
|
9
7
|
- gemfiles/http3.gemfile
|
10
8
|
- gemfiles/http4.gemfile
|
9
|
+
- gemfiles/http5.gemfile
|
11
10
|
- gemfiles/rack1.gemfile
|
12
11
|
- gemfiles/rack2.gemfile
|
13
12
|
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.3.0 - 2019-05-18
|
2
|
+
|
3
|
+
* [#74](https://github.com/trusche/httplog/pull/74) Added ability to filter sensitive parameter values in the request (based on [#73](https://github.com/trusche/httplog/pull/73)). Default masking of `password` parameter
|
4
|
+
* Removed explicit support and tests for ruby 2.3 and http gem v2
|
5
|
+
* [#71](https://github.com/trusche/httplog/pull/71) Rounding benchmark in compact mode
|
6
|
+
|
7
|
+
## 1.2.2 - 2019-03-15
|
8
|
+
|
9
|
+
* [#70](https://github.com/trusche/httplog/pull/70) Fixed a bug where blacklisting caused requests to not be sent with HTTP adapter
|
10
|
+
|
1
11
|
## 1.2.1 - 2019-01-28
|
2
12
|
|
3
13
|
* [#67](https://github.com/trusche/httplog/pull/67) Gracefully handling empty response headers in Ethon
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Log outgoing HTTP requests made from your application. Helps with debugging pesky API error responses, or just generally understanding what's going on under the hood.
|
7
7
|
|
8
|
-
Requires ruby >= 2.
|
8
|
+
Requires ruby >= 2.4.
|
9
9
|
|
10
10
|
This gem works with the following ruby modules and libraries:
|
11
11
|
|
@@ -81,6 +81,9 @@ HttpLog.configure do |config|
|
|
81
81
|
# Limit logging based on URL patterns
|
82
82
|
config.url_whitelist_pattern = nil
|
83
83
|
config.url_blacklist_pattern = nil
|
84
|
+
|
85
|
+
# Mask the values of sensitive requestparameters
|
86
|
+
config.filter_parameters = %w[password]
|
84
87
|
end
|
85
88
|
```
|
86
89
|
|
@@ -121,15 +124,40 @@ If the log is too noisy for you, but you don't want to completely disable it eit
|
|
121
124
|
|
122
125
|
If you want to log HTTP requests in a JSON format, set the `json_log` option to `true`. You can combine this with `compact_log` to only log the basic request metrics without headers and bodies.
|
123
126
|
|
127
|
+
### Parameter filtering
|
128
|
+
|
129
|
+
Just like in Rails, you can filter the values of sensitive parameters by setting the `filter_parameters` to an array of (lower case) keys. The value for "password" is filtered by default.
|
130
|
+
|
131
|
+
**Please note** that this will **only filter the request data** with well-formed parameters (in the URL, the headers, and the request data) but **not the response**. It does not currently filter JSON request data either, just standard "key=value" pairs in the request body.
|
132
|
+
|
124
133
|
### Example
|
125
134
|
|
126
135
|
With the default configuration, the log output might look like this:
|
127
136
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
137
|
+
[httplog] Connecting: localhost:80
|
138
|
+
[httplog] Sending: GET http://localhost:9292/index.html
|
139
|
+
[httplog] Status: 200
|
140
|
+
[httplog] Benchmark: 0.00057 seconds
|
141
|
+
[httplog] Response:
|
142
|
+
<html>
|
143
|
+
<head>
|
144
|
+
<title>Test Page</title>
|
145
|
+
</head>
|
146
|
+
<body>
|
147
|
+
<h1>This is the test page.</h1>
|
148
|
+
</body>
|
149
|
+
</html>
|
150
|
+
|
151
|
+
With `log_headers = true` and a parameter 'password' in the request query and headers:
|
152
|
+
|
153
|
+
|
154
|
+
[httplog] Connecting: localhost:80
|
155
|
+
[httplog] Sending: GET http://localhost:9292/index.html?password=[FILTERED]
|
156
|
+
[httplog] Header: accept: *.*
|
157
|
+
[httplog] Header: password=[FILTERED]
|
158
|
+
[httplog] Status: 200
|
159
|
+
[httplog] Benchmark: 0.00057 seconds
|
160
|
+
[httplog] Response:
|
133
161
|
<html>
|
134
162
|
<head>
|
135
163
|
<title>Test Page</title>
|
@@ -163,21 +191,21 @@ a suggestion for a fix, please open an issue or, even better, submit a pull requ
|
|
163
191
|
* When using OpenURI, the reading of the HTTP response body is deferred,
|
164
192
|
so it is not available for logging. This will be noted in the logging statement:
|
165
193
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
194
|
+
[httplog] Connecting: localhost:80
|
195
|
+
[httplog] Sending: GET http://localhost:9292/index.html
|
196
|
+
[httplog] Status: 200
|
197
|
+
[httplog] Benchmark: 0.000617 seconds
|
198
|
+
[httplog] Response: (not available yet)
|
171
199
|
|
172
200
|
* When using HTTPClient, the TCP connection establishment will be logged
|
173
201
|
*after* the HTTP request and headers, due to the way HTTPClient is organized.
|
174
202
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
203
|
+
[httplog] Sending: GET http://localhost:9292/index.html
|
204
|
+
[httplog] Header: accept: */*
|
205
|
+
[httplog] Header: foo: bar
|
206
|
+
[httplog] Connecting: localhost:9292
|
207
|
+
[httplog] Status: 200
|
208
|
+
[httplog] Benchmark: 0.001562 seconds
|
181
209
|
|
182
210
|
* Also when using HTTPClient, make sure you include `httplog` **after** `httpclient` in your `Gemfile`.
|
183
211
|
|
data/gemfiles/http4.gemfile
CHANGED
@@ -4,7 +4,7 @@ if defined?(Excon)
|
|
4
4
|
module Excon
|
5
5
|
module HttpLogHelper
|
6
6
|
def httplog_url(datum)
|
7
|
-
@httplog_url ||= "#{datum[:scheme]}://#{datum[:host]}:#{datum[:port]}#{datum[:path]}
|
7
|
+
@httplog_url ||= ["#{datum[:scheme]}://#{datum[:host]}:#{datum[:port]}#{datum[:path]}", datum[:query]].compact.join('?')
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -20,7 +20,8 @@ module HttpLog
|
|
20
20
|
:color,
|
21
21
|
:prefix_data_lines,
|
22
22
|
:prefix_response_lines,
|
23
|
-
:prefix_line_numbers
|
23
|
+
:prefix_line_numbers,
|
24
|
+
:filter_parameters
|
24
25
|
|
25
26
|
def initialize
|
26
27
|
@enabled = true
|
@@ -42,12 +43,7 @@ module HttpLog
|
|
42
43
|
@prefix_data_lines = false
|
43
44
|
@prefix_response_lines = false
|
44
45
|
@prefix_line_numbers = false
|
45
|
-
|
46
|
-
|
47
|
-
# TODO: remove in 1.0.0
|
48
|
-
def []=(key, value)
|
49
|
-
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'
|
50
|
-
send("#{key}=", value)
|
46
|
+
@filter_parameters = []
|
51
47
|
end
|
52
48
|
end
|
53
49
|
end
|
data/lib/httplog/http_log.rb
CHANGED
@@ -8,6 +8,8 @@ require 'rack'
|
|
8
8
|
|
9
9
|
module HttpLog
|
10
10
|
LOG_PREFIX = '[httplog] '.freeze
|
11
|
+
PARAM_MASK = '[FILTERED]'
|
12
|
+
|
11
13
|
class BodyParsingError < StandardError; end
|
12
14
|
|
13
15
|
class << self
|
@@ -17,7 +19,6 @@ module HttpLog
|
|
17
19
|
@configuration ||= Configuration.new
|
18
20
|
end
|
19
21
|
alias config configuration
|
20
|
-
alias options configuration # TODO: remove with 1.0.0
|
21
22
|
|
22
23
|
def reset!
|
23
24
|
@configuration = nil
|
@@ -64,13 +65,13 @@ module HttpLog
|
|
64
65
|
def log_request(method, uri)
|
65
66
|
return unless config.log_request
|
66
67
|
|
67
|
-
log("Sending: #{method.to_s.upcase} #{uri}")
|
68
|
+
log("Sending: #{method.to_s.upcase} #{masked(uri)}")
|
68
69
|
end
|
69
70
|
|
70
71
|
def log_headers(headers = {})
|
71
72
|
return unless config.log_headers
|
72
73
|
|
73
|
-
headers.each do |key, value|
|
74
|
+
masked(headers).each do |key, value|
|
74
75
|
log("Header: #{key}: #{value}")
|
75
76
|
end
|
76
77
|
end
|
@@ -129,7 +130,8 @@ module HttpLog
|
|
129
130
|
|
130
131
|
def log_data(data)
|
131
132
|
return unless config.log_data
|
132
|
-
|
133
|
+
|
134
|
+
data = utf_encoded(masked(data.dup).to_s) unless data.nil?
|
133
135
|
|
134
136
|
if config.prefix_data_lines
|
135
137
|
log('Data:')
|
@@ -142,7 +144,7 @@ module HttpLog
|
|
142
144
|
def log_compact(method, uri, status, seconds)
|
143
145
|
return unless config.compact_log
|
144
146
|
status = Rack::Utils.status_code(status) unless status == /\d{3}/
|
145
|
-
log("#{method.to_s.upcase} #{uri} completed with status code #{status} in #{seconds} seconds")
|
147
|
+
log("#{method.to_s.upcase} #{masked(uri)} completed with status code #{status} in #{seconds.to_f.round(6)} seconds")
|
146
148
|
end
|
147
149
|
|
148
150
|
def log_json(data = {})
|
@@ -159,16 +161,16 @@ module HttpLog
|
|
159
161
|
if config.compact_log
|
160
162
|
log({
|
161
163
|
method: data[:method].to_s.upcase,
|
162
|
-
url: data[:url],
|
164
|
+
url: masked(data[:url]),
|
163
165
|
response_code: data[:response_code].to_i,
|
164
166
|
benchmark: data[:benchmark]
|
165
167
|
}.to_json)
|
166
168
|
else
|
167
169
|
log({
|
168
170
|
method: data[:method].to_s.upcase,
|
169
|
-
url: data[:url],
|
170
|
-
request_body: data[:request_body],
|
171
|
-
request_headers: data[:request_headers].to_h,
|
171
|
+
url: masked(data[:url]),
|
172
|
+
request_body: masked(data[:request_body]),
|
173
|
+
request_headers: masked(data[:request_headers].to_h),
|
172
174
|
response_code: data[:response_code].to_i,
|
173
175
|
response_body: parsed_body,
|
174
176
|
response_headers: data[:response_headers].to_h,
|
@@ -197,6 +199,48 @@ module HttpLog
|
|
197
199
|
|
198
200
|
private
|
199
201
|
|
202
|
+
def masked(msg, key=nil)
|
203
|
+
return msg if config.filter_parameters.empty?
|
204
|
+
return msg if msg.nil?
|
205
|
+
|
206
|
+
# If a key is given, msg is just the value and can be replaced
|
207
|
+
# in its entirety.
|
208
|
+
return (config.filter_parameters.include?(key.downcase) ? PARAM_MASK : msg) if key
|
209
|
+
|
210
|
+
# Otherwise, we'll parse Strings for key=valye pairs...
|
211
|
+
case msg
|
212
|
+
when *string_classes
|
213
|
+
config.filter_parameters.reduce(msg) do |m,key|
|
214
|
+
m.to_s.gsub(/(#{key})=[^&]+/i, "#{key}=#{PARAM_MASK}")
|
215
|
+
end
|
216
|
+
# ...and recurse over hashes
|
217
|
+
when *hash_classes
|
218
|
+
Hash[msg.map {|k,v| [k, masked(v, k)]}]
|
219
|
+
else
|
220
|
+
log "*** FILTERING NOT APPLIED BECAUSE #{msg.class} IS UNEXPECTED ***"
|
221
|
+
msg
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def string_classes
|
226
|
+
@string_classes ||= begin
|
227
|
+
string_classes = [String]
|
228
|
+
string_classes << HTTP::Response::Body if defined?(HTTP::Response::Body)
|
229
|
+
string_classes << HTTP::URI if defined?(HTTP::URI)
|
230
|
+
string_classes << URI::HTTP if defined?(URI::HTTP)
|
231
|
+
string_classes << HTTP::FormData::Urlencoded if defined?(HTTP::FormData::Urlencoded)
|
232
|
+
string_classes
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def hash_classes
|
237
|
+
@hash_classes ||= begin
|
238
|
+
hash_classes = [Hash, Enumerator]
|
239
|
+
hash_classes << HTTP::Headers if defined?(HTTP::Headers)
|
240
|
+
hash_classes
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
200
244
|
def utf_encoded(data, content_type = nil)
|
201
245
|
charset = content_type.to_s.scan(/; charset=(\S+)/).flatten.first || 'UTF-8'
|
202
246
|
begin
|
data/lib/httplog/version.rb
CHANGED
@@ -4,7 +4,7 @@ require 'faraday'
|
|
4
4
|
class FaradayAdapter < HTTPBaseAdapter
|
5
5
|
def send_get_request
|
6
6
|
connection.get do |req|
|
7
|
-
req.url parse_uri.to_s
|
7
|
+
req.url parse_uri(true).to_s
|
8
8
|
req.headers = @headers
|
9
9
|
end
|
10
10
|
end
|
@@ -42,6 +42,10 @@ class FaradayAdapter < HTTPBaseAdapter
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
def logs_form_data?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
45
49
|
private
|
46
50
|
|
47
51
|
def connection
|
@@ -15,8 +15,14 @@ class HTTPBaseAdapter
|
|
15
15
|
true
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def logs_form_data?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_uri(query=false)
|
23
|
+
uri = "#{@protocol}://#{@host}:#{@port}#{@path}"
|
24
|
+
uri = [uri, URI::encode(@data)].join('?') if query && @data
|
25
|
+
URI.parse(uri)
|
20
26
|
end
|
21
27
|
|
22
28
|
def expected_response_body
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class HTTPClientAdapter < HTTPBaseAdapter
|
4
4
|
def send_get_request
|
5
|
-
::HTTPClient.get(parse_uri, header: @headers)
|
5
|
+
::HTTPClient.get(parse_uri(true), header: @headers)
|
6
6
|
end
|
7
7
|
|
8
8
|
def send_head_request
|
@@ -24,4 +24,8 @@ class HTTPClientAdapter < HTTPBaseAdapter
|
|
24
24
|
def self.response_should_be
|
25
25
|
HTTP::Message
|
26
26
|
end
|
27
|
+
|
28
|
+
def logs_form_data?
|
29
|
+
false
|
30
|
+
end
|
27
31
|
end
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
class NetHTTPAdapter < HTTPBaseAdapter
|
4
4
|
def send_get_request
|
5
|
-
|
5
|
+
path = @path
|
6
|
+
path = [@path, URI::encode(@data)].join('?') if @data
|
7
|
+
Net::HTTP.get_response(@host, path, @port)
|
6
8
|
end
|
7
9
|
|
8
10
|
def send_head_request
|
data/spec/lib/http_log_spec.rb
CHANGED
@@ -5,16 +5,17 @@ require 'spec_helper'
|
|
5
5
|
describe HttpLog do
|
6
6
|
subject { log } # see spec_helper
|
7
7
|
|
8
|
+
let(:secret) { 'my secret' }
|
8
9
|
let(:host) { 'localhost' }
|
9
10
|
let(:port) { 9292 }
|
10
11
|
let(:path) { '/index.html' }
|
11
|
-
let(:headers) { { 'accept' => '*/*', 'foo' =>
|
12
|
-
let(:data) {
|
13
|
-
let(:params) { { 'foo' =>
|
12
|
+
let(:headers) { { 'accept' => '*/*', 'foo' => secret } }
|
13
|
+
let(:data) { "foo=#{secret}&bar=foo" }
|
14
|
+
let(:params) { { 'foo' => secret, 'bar' => 'foo:form-data' } }
|
14
15
|
let(:html) { File.read('./spec/support/index.html') }
|
15
16
|
let(:json) { JSON.parse(log.match(/\[httplog\]\s(.*)/).captures.first) }
|
16
17
|
|
17
|
-
#
|
18
|
+
# Default configuration
|
18
19
|
let(:enabled) { HttpLog.configuration.enabled }
|
19
20
|
let(:severity) { HttpLog.configuration.severity }
|
20
21
|
let(:log_headers) { HttpLog.configuration.log_headers }
|
@@ -31,6 +32,7 @@ describe HttpLog do
|
|
31
32
|
let(:compact_log) { HttpLog.configuration.compact_log }
|
32
33
|
let(:url_blacklist_pattern) { HttpLog.configuration.url_blacklist_pattern }
|
33
34
|
let(:url_whitelist_pattern) { HttpLog.configuration.url_whitelist_pattern }
|
35
|
+
let(:filter_parameters) { HttpLog.configuration.filter_parameters }
|
34
36
|
|
35
37
|
def configure
|
36
38
|
HttpLog.configure do |c|
|
@@ -50,6 +52,7 @@ describe HttpLog do
|
|
50
52
|
c.compact_log = compact_log
|
51
53
|
c.url_blacklist_pattern = url_blacklist_pattern
|
52
54
|
c.url_whitelist_pattern = url_whitelist_pattern
|
55
|
+
c.filter_parameters = filter_parameters
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -135,7 +138,7 @@ describe HttpLog do
|
|
135
138
|
|
136
139
|
it_behaves_like 'logs request', 'POST'
|
137
140
|
it_behaves_like 'logs expected response'
|
138
|
-
it_behaves_like 'logs data'
|
141
|
+
it_behaves_like 'logs data'
|
139
142
|
it_behaves_like 'logs status', 200
|
140
143
|
it_behaves_like 'logs benchmark'
|
141
144
|
|
@@ -174,6 +177,7 @@ describe HttpLog do
|
|
174
177
|
let(:log_headers) { true }
|
175
178
|
it { is_expected.to match(%r{Header: accept: */*}i) } # request
|
176
179
|
it { is_expected.to match(/Header: Server: thin/i) } # response
|
180
|
+
it_behaves_like 'filtered parameters'
|
177
181
|
end
|
178
182
|
|
179
183
|
context 'with blacklist hit' do
|
@@ -206,6 +210,7 @@ describe HttpLog do
|
|
206
210
|
it_behaves_like 'data logging disabled'
|
207
211
|
it_behaves_like 'response logging disabled'
|
208
212
|
it_behaves_like 'benchmark logging disabled'
|
213
|
+
it_behaves_like 'filtered parameters'
|
209
214
|
|
210
215
|
context 'with single color' do
|
211
216
|
let(:color) { :red }
|
@@ -231,7 +236,7 @@ describe HttpLog do
|
|
231
236
|
|
232
237
|
context 'with compact config' do
|
233
238
|
let(:compact_log) { true }
|
234
|
-
it { is_expected.to match(%r{\[httplog\] GET http://#{host}:#{port}#{path}(\?.*)? completed with status code \d{3} in
|
239
|
+
it { is_expected.to match(%r{\[httplog\] GET http://#{host}:#{port}#{path}(\?.*)? completed with status code \d{3} in \d+\.\d{1,6} }) }
|
235
240
|
it { is_expected.to_not include("Connecting: #{host}:#{port}") }
|
236
241
|
it { is_expected.to_not include('Response:') }
|
237
242
|
it { is_expected.to_not include('Data:') }
|
@@ -248,6 +253,7 @@ describe HttpLog do
|
|
248
253
|
it_behaves_like 'benchmark logging disabled'
|
249
254
|
it_behaves_like 'with prefix response lines'
|
250
255
|
it_behaves_like 'with line numbers'
|
256
|
+
it_behaves_like 'filtered parameters'
|
251
257
|
end
|
252
258
|
end
|
253
259
|
|
@@ -260,12 +266,13 @@ describe HttpLog do
|
|
260
266
|
it_behaves_like 'benchmark logging disabled'
|
261
267
|
it_behaves_like 'with prefix response lines'
|
262
268
|
it_behaves_like 'with line numbers'
|
269
|
+
it_behaves_like 'filtered parameters'
|
263
270
|
end
|
264
271
|
end
|
265
272
|
|
266
273
|
context 'POST multi-part requests (file upload)' do
|
267
274
|
let(:upload) { Tempfile.new('http-log') }
|
268
|
-
let(:params) { { 'foo' =>
|
275
|
+
let(:params) { { 'foo' => secret, 'file' => upload } }
|
269
276
|
|
270
277
|
if adapter_class.method_defined? :send_multipart_post_request
|
271
278
|
before { adapter.send_multipart_post_request }
|
@@ -275,6 +282,7 @@ describe HttpLog do
|
|
275
282
|
it_behaves_like 'benchmark logging disabled'
|
276
283
|
it_behaves_like 'with prefix response lines'
|
277
284
|
it_behaves_like 'with line numbers'
|
285
|
+
it_behaves_like 'filtered parameters'
|
278
286
|
end
|
279
287
|
end
|
280
288
|
end
|
@@ -292,6 +300,7 @@ describe HttpLog do
|
|
292
300
|
it { expect(json['response_code']).to eq(200) }
|
293
301
|
it { expect(json['response_body']).to eq(html) }
|
294
302
|
it { expect(json['benchmark']).to be_a(Numeric) }
|
303
|
+
it_behaves_like 'filtered parameters'
|
295
304
|
|
296
305
|
context 'and compact config' do
|
297
306
|
let(:compact_log) { true }
|
@@ -12,8 +12,15 @@ RSpec.shared_examples 'logs expected response' do
|
|
12
12
|
it { is_expected.to include("Response:#{adapter.expected_response_body}") }
|
13
13
|
end
|
14
14
|
|
15
|
-
RSpec.shared_examples 'logs data' do
|
16
|
-
|
15
|
+
RSpec.shared_examples 'logs data' do
|
16
|
+
# Some adapters (YOU, Faraday!) re-order the keys for no bloody
|
17
|
+
# reason whatsover. So we need to check them individually. And some
|
18
|
+
# (guess who?) use non-standard URL encoding for spaces...
|
19
|
+
it do
|
20
|
+
data.split('&').each do |param|
|
21
|
+
is_expected.to match(Regexp.new(param.gsub(' ', '( |%20|\\\+)')))
|
22
|
+
end
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
26
|
RSpec.shared_examples 'logs status' do |status|
|
@@ -61,3 +68,12 @@ RSpec.shared_examples 'with connection logging disabled' do
|
|
61
68
|
let(:log_connect) { false }
|
62
69
|
it { is_expected.to_not include('Connecting:') }
|
63
70
|
end
|
71
|
+
|
72
|
+
RSpec.shared_examples 'filtered parameters' do
|
73
|
+
let(:filter_parameters) { %w(foo) }
|
74
|
+
|
75
|
+
it 'masks the filtered value' do
|
76
|
+
# is_expected.to include('foo=[FILTERED]&').or exclude('foo')
|
77
|
+
is_expected.to_not include('secret')
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httplog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thilo Rusche
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ethon
|
@@ -241,9 +241,9 @@ files:
|
|
241
241
|
- MIT-LICENSE
|
242
242
|
- README.md
|
243
243
|
- Rakefile
|
244
|
-
- gemfiles/http2.gemfile
|
245
244
|
- gemfiles/http3.gemfile
|
246
245
|
- gemfiles/http4.gemfile
|
246
|
+
- gemfiles/http5.gemfile
|
247
247
|
- gemfiles/rack1.gemfile
|
248
248
|
- gemfiles/rack2.gemfile
|
249
249
|
- httplog.gemspec
|
@@ -302,8 +302,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
302
|
- !ruby/object:Gem::Version
|
303
303
|
version: '0'
|
304
304
|
requirements: []
|
305
|
-
|
306
|
-
rubygems_version: 2.6.13
|
305
|
+
rubygems_version: 3.0.3
|
307
306
|
signing_key:
|
308
307
|
specification_version: 4
|
309
308
|
summary: Log outgoing HTTP requests.
|