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