httplog 1.1.1 → 1.2.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 +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +39 -35
- data/Guardfile +1 -1
- data/README.md +18 -2
- data/lib/httplog/adapters/ethon.rb +13 -12
- data/lib/httplog/adapters/excon.rb +27 -37
- data/lib/httplog/adapters/http.rb +18 -19
- data/lib/httplog/adapters/httpclient.rb +14 -15
- data/lib/httplog/adapters/net_http.rb +13 -16
- data/lib/httplog/adapters/patron.rb +13 -15
- data/lib/httplog/configuration.rb +3 -1
- data/lib/httplog/http_log.rb +85 -21
- data/lib/httplog/version.rb +1 -1
- data/spec/lib/http_log_spec.rb +190 -211
- data/spec/support/shared_examples.rb +63 -0
- data/spec/support/test.pdf +198 -0
- data/spec/support/test_server.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 559dce6d4408a4c64b11a0a80860f373cca08218
|
4
|
+
data.tar.gz: 631b221d50a319c8ab94fabccf910d8ba1ea8d17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45a9cb8d87165ce54676c5946e56af35c306a19e02a9cf2f17018ac4fd03e8a2993506eae1eb71db3a5b38a3bbbea9f072b96f3c3dfb1ccd75b19ec7d516918a
|
7
|
+
data.tar.gz: c1bbaf8818fd4454223b28ba62e41538d255b02354623777891a445cf584da77e15dec6e34c912f6399d172a555a10633def08e4343eccc2b40b8b339140d8de
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 1.2.0 - 2018-12-31
|
2
|
+
|
3
|
+
* [#65](https://github.com/trusche/httplog/pull/65) Added JSON as an optional output format
|
4
|
+
* Ruby 2.2 no longer supported
|
5
|
+
|
6
|
+
## 1.1.1 - 2018-06-30
|
7
|
+
|
8
|
+
* [#60](https://github.com/trusche/httplog/issues/60) Fixed a bug in color configuration settings
|
9
|
+
|
1
10
|
## 1.1.0 - 2018-06-22
|
2
11
|
|
3
12
|
* [#59](https://github.com/trusche/httplog/issues/59) Switched colorization library to MIT licensed [rainbow](https://github.com/sickill/rainbow).
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
httplog (1.
|
4
|
+
httplog (1.2.0)
|
5
5
|
rack (>= 1.0)
|
6
6
|
rainbow (>= 2.0.0)
|
7
7
|
|
@@ -13,18 +13,18 @@ GEM
|
|
13
13
|
coderay (1.1.2)
|
14
14
|
daemons (1.2.6)
|
15
15
|
diff-lcs (1.3)
|
16
|
-
docile (1.1
|
17
|
-
domain_name (0.5.
|
16
|
+
docile (1.3.1)
|
17
|
+
domain_name (0.5.20180417)
|
18
18
|
unf (>= 0.0.5, < 1.0.0)
|
19
19
|
ethon (0.11.0)
|
20
20
|
ffi (>= 1.3.0)
|
21
|
-
eventmachine (1.2.
|
22
|
-
excon (0.
|
23
|
-
faraday (0.
|
21
|
+
eventmachine (1.2.7)
|
22
|
+
excon (0.62.0)
|
23
|
+
faraday (0.15.4)
|
24
24
|
multipart-post (>= 1.2, < 3)
|
25
|
-
ffi (1.9.
|
25
|
+
ffi (1.9.25)
|
26
26
|
formatador (0.2.5)
|
27
|
-
guard (2.
|
27
|
+
guard (2.15.0)
|
28
28
|
formatador (>= 0.2.4)
|
29
29
|
listen (>= 2.7, < 4.0)
|
30
30
|
lumberjack (>= 1.0.12, < 2.0)
|
@@ -38,16 +38,17 @@ GEM
|
|
38
38
|
guard (~> 2.1)
|
39
39
|
guard-compat (~> 1.1)
|
40
40
|
rspec (>= 2.99.0, < 4.0)
|
41
|
-
http (3.
|
41
|
+
http (3.3.0)
|
42
42
|
addressable (~> 2.3)
|
43
43
|
http-cookie (~> 1.0)
|
44
|
-
http-form_data (
|
44
|
+
http-form_data (~> 2.0)
|
45
45
|
http_parser.rb (~> 0.6.0)
|
46
46
|
http-cookie (1.0.3)
|
47
47
|
domain_name (~> 0.5)
|
48
|
-
http-form_data (2.
|
48
|
+
http-form_data (2.1.1)
|
49
49
|
http_parser.rb (0.6.0)
|
50
|
-
httparty (0.16.
|
50
|
+
httparty (0.16.3)
|
51
|
+
mime-types (~> 3.0)
|
51
52
|
multi_xml (>= 0.5.2)
|
52
53
|
httpclient (2.8.3)
|
53
54
|
json (2.1.0)
|
@@ -55,42 +56,45 @@ GEM
|
|
55
56
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
56
57
|
rb-inotify (~> 0.9, >= 0.9.7)
|
57
58
|
ruby_dep (~> 1.2)
|
58
|
-
lumberjack (1.0.
|
59
|
-
method_source (0.9.
|
59
|
+
lumberjack (1.0.13)
|
60
|
+
method_source (0.9.2)
|
61
|
+
mime-types (3.2.2)
|
62
|
+
mime-types-data (~> 3.2015)
|
63
|
+
mime-types-data (3.2018.0812)
|
60
64
|
multi_xml (0.6.0)
|
61
65
|
multipart-post (2.0.0)
|
62
66
|
nenv (0.3.0)
|
63
67
|
notiffany (0.1.1)
|
64
68
|
nenv (~> 0.1)
|
65
69
|
shellany (~> 0.0)
|
66
|
-
patron (0.
|
67
|
-
pry (0.
|
70
|
+
patron (0.13.1)
|
71
|
+
pry (0.12.2)
|
68
72
|
coderay (~> 1.1.0)
|
69
73
|
method_source (~> 0.9.0)
|
70
|
-
public_suffix (3.0.
|
71
|
-
rack (2.0.
|
74
|
+
public_suffix (3.0.3)
|
75
|
+
rack (2.0.6)
|
72
76
|
rainbow (3.0.0)
|
73
|
-
rake (12.3.
|
74
|
-
rb-fsevent (0.10.
|
77
|
+
rake (12.3.2)
|
78
|
+
rb-fsevent (0.10.3)
|
75
79
|
rb-inotify (0.9.10)
|
76
80
|
ffi (>= 0.5.0, < 2)
|
77
|
-
rspec (3.
|
78
|
-
rspec-core (~> 3.
|
79
|
-
rspec-expectations (~> 3.
|
80
|
-
rspec-mocks (~> 3.
|
81
|
-
rspec-core (3.
|
82
|
-
rspec-support (~> 3.
|
83
|
-
rspec-expectations (3.
|
81
|
+
rspec (3.8.0)
|
82
|
+
rspec-core (~> 3.8.0)
|
83
|
+
rspec-expectations (~> 3.8.0)
|
84
|
+
rspec-mocks (~> 3.8.0)
|
85
|
+
rspec-core (3.8.0)
|
86
|
+
rspec-support (~> 3.8.0)
|
87
|
+
rspec-expectations (3.8.2)
|
84
88
|
diff-lcs (>= 1.2.0, < 2.0)
|
85
|
-
rspec-support (~> 3.
|
86
|
-
rspec-mocks (3.
|
89
|
+
rspec-support (~> 3.8.0)
|
90
|
+
rspec-mocks (3.8.0)
|
87
91
|
diff-lcs (>= 1.2.0, < 2.0)
|
88
|
-
rspec-support (~> 3.
|
89
|
-
rspec-support (3.
|
92
|
+
rspec-support (~> 3.8.0)
|
93
|
+
rspec-support (3.8.0)
|
90
94
|
ruby_dep (1.5.0)
|
91
95
|
shellany (0.0.1)
|
92
|
-
simplecov (0.
|
93
|
-
docile (~> 1.1
|
96
|
+
simplecov (0.16.1)
|
97
|
+
docile (~> 1.1)
|
94
98
|
json (>= 1.8, < 3)
|
95
99
|
simplecov-html (~> 0.10.0)
|
96
100
|
simplecov-html (0.10.2)
|
@@ -98,7 +102,7 @@ GEM
|
|
98
102
|
daemons (~> 1.0, >= 1.0.9)
|
99
103
|
eventmachine (~> 1.0, >= 1.0.4)
|
100
104
|
rack (>= 1, < 3)
|
101
|
-
thor (0.20.
|
105
|
+
thor (0.20.3)
|
102
106
|
unf (0.1.4)
|
103
107
|
unf_ext
|
104
108
|
unf_ext (0.0.7.5)
|
@@ -123,4 +127,4 @@ DEPENDENCIES
|
|
123
127
|
thin (~> 1.7)
|
124
128
|
|
125
129
|
BUNDLED WITH
|
126
|
-
1.
|
130
|
+
1.17.1
|
data/Guardfile
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# A sample Guardfile
|
4
4
|
# More info at https://github.com/guard/guard#readme
|
5
5
|
|
6
|
-
guard 'rspec',
|
6
|
+
guard 'rspec', cmd: 'bundle exec rspec' do
|
7
7
|
watch(%r{^spec/.+_spec\.rb$})
|
8
8
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
9
9
|
watch('spec/spec_helper.rb') { 'spec' }
|
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.3.
|
9
9
|
|
10
10
|
This gem works with the following ruby modules and libraries:
|
11
11
|
|
@@ -72,11 +72,14 @@ HttpLog.configure do |config|
|
|
72
72
|
# ...or log all request as a single line by setting this to `true`
|
73
73
|
config.compact_log = false
|
74
74
|
|
75
|
+
# You can also log in JSON format
|
76
|
+
config.json_log = false
|
77
|
+
|
75
78
|
# Prettify the output - see below
|
76
79
|
config.color = false
|
77
80
|
|
78
81
|
# Limit logging based on URL patterns
|
79
|
-
config.url_whitelist_pattern =
|
82
|
+
config.url_whitelist_pattern = nil
|
80
83
|
config.url_blacklist_pattern = nil
|
81
84
|
end
|
82
85
|
```
|
@@ -114,6 +117,10 @@ For more color options please refer to the [rainbow documentation](https://githu
|
|
114
117
|
|
115
118
|
If the log is too noisy for you, but you don't want to completely disable it either, set the `compact_log` option to `true`. This will log each request in a single line with method, request URI, response status and time, but no data or headers. No need to disable any other options individually.
|
116
119
|
|
120
|
+
### JSON logging
|
121
|
+
|
122
|
+
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
|
+
|
117
124
|
### Example
|
118
125
|
|
119
126
|
With the default configuration, the log output might look like this:
|
@@ -136,6 +143,14 @@ With `compact_log` enabled, the same request might look like this:
|
|
136
143
|
|
137
144
|
[httplog] GET http://localhost:9292/index.html completed with status code 200 in 0.00057 seconds
|
138
145
|
|
146
|
+
With `json_log` enabled:
|
147
|
+
|
148
|
+
[httplog] {"method":"GET","url":"localhost:80","request_body":null, "request_headers":{"foo":"bar"}, "response_code":200,"response_body":"<html>\n <head>\n <title>Test Page</title>\n </head>\n <body>\n <h1>This is the test page.</h1>\n </body>\n </html>","response_headers":{"foo":"bar"},"benchmark":0.00057}
|
149
|
+
|
150
|
+
And with `json_log` *and* `compact_log` enabled:
|
151
|
+
|
152
|
+
[httplog] {"method":"GET","url":"localhost:80","response_code":200,"benchmark":0.00057}
|
153
|
+
|
139
154
|
### Known Issues
|
140
155
|
|
141
156
|
Following are some known quirks and issues with particular libraries. If you know a workaround or have
|
@@ -200,3 +215,4 @@ Thanks to these fine folks for contributing pull requests:
|
|
200
215
|
* [Ilya Bondarenko](https://github.com/sedx)
|
201
216
|
* [Kostas Zacharakis](https://github.com/kzacharakis)
|
202
217
|
* [Yuri Smirnov](https://github.com/tycooon)
|
218
|
+
* [Manuel Bustillo Alonso](https://github.com/bustikiller)
|
@@ -8,13 +8,7 @@ if defined?(Ethon)
|
|
8
8
|
module Http
|
9
9
|
alias orig_http_request http_request
|
10
10
|
def http_request(url, action_name, options = {})
|
11
|
-
@
|
12
|
-
if HttpLog.url_approved?(url)
|
13
|
-
HttpLog.log_request(action_name, url)
|
14
|
-
HttpLog.log_headers(options[:headers])
|
15
|
-
HttpLog.log_data(options[:body]) # if action_name == :post
|
16
|
-
end
|
17
|
-
|
11
|
+
@http_log = options.merge(method: action_name) # remember this for compact logging
|
18
12
|
orig_http_request(url, action_name, options)
|
19
13
|
end
|
20
14
|
end
|
@@ -36,11 +30,18 @@ if defined?(Ethon)
|
|
36
30
|
# an array; probably overlooked it. Anyway, let's do it ourselves:
|
37
31
|
headers = response_headers.split(/\r?\n/)[1..-1]
|
38
32
|
|
39
|
-
HttpLog.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
HttpLog.call(
|
34
|
+
method: @http_log[:method],
|
35
|
+
url: @url,
|
36
|
+
request_body: @http_log[:body],
|
37
|
+
request_headers: @http_log[:headers],
|
38
|
+
response_code: @return_code,
|
39
|
+
response_body: response_body,
|
40
|
+
response_headers: headers.map{ |header| header.split(/:\s/) }.to_h,
|
41
|
+
benchmark: bm,
|
42
|
+
encoding: encoding,
|
43
|
+
content_type: content_type
|
44
|
+
)
|
44
45
|
return_code
|
45
46
|
end
|
46
47
|
end
|
@@ -2,20 +2,26 @@
|
|
2
2
|
|
3
3
|
if defined?(Excon)
|
4
4
|
module Excon
|
5
|
+
module HttpLogHelper
|
6
|
+
def _httplog_url(datum)
|
7
|
+
@httplog_url ||= "#{datum[:scheme]}://#{datum[:host]}:#{datum[:port]}#{datum[:path]}#{datum[:query]}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
class Socket
|
12
|
+
include Excon::HttpLogHelper
|
6
13
|
alias orig_connect connect
|
7
14
|
def connect
|
8
15
|
host = @data[:proxy] ? @data[:proxy][:host] : @data[:host]
|
9
16
|
port = @data[:proxy] ? @data[:proxy][:port] : @data[:port]
|
10
|
-
HttpLog.log_connection(host, port)
|
17
|
+
HttpLog.log_connection(host, port) if ::HttpLog.url_approved?(_httplog_url(@data))
|
11
18
|
orig_connect
|
12
19
|
end
|
13
20
|
end
|
14
21
|
|
15
22
|
class Connection
|
16
|
-
|
17
|
-
|
18
|
-
end
|
23
|
+
include Excon::HttpLogHelper
|
24
|
+
attr_reader :bm
|
19
25
|
|
20
26
|
alias orig_request request
|
21
27
|
def request(params, &block)
|
@@ -24,41 +30,25 @@ if defined?(Excon)
|
|
24
30
|
result = orig_request(params, &block)
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
url = _httplog_url(@data)
|
34
|
+
return result unless HttpLog.url_approved?(url)
|
35
|
+
|
36
|
+
headers = result[:headers] || {}
|
37
|
+
|
38
|
+
HttpLog.call(
|
39
|
+
method: params[:method],
|
40
|
+
url: url,
|
41
|
+
request_body: @data[:body],
|
42
|
+
request_headers: @data[:headers] || {},
|
43
|
+
response_code: result[:status],
|
44
|
+
response_body: result[:body],
|
45
|
+
response_headers: headers,
|
46
|
+
benchmark: bm,
|
47
|
+
encoding: headers['Content-Encoding'],
|
48
|
+
content_type: headers['Content-Type']
|
49
|
+
)
|
35
50
|
result
|
36
51
|
end
|
37
|
-
|
38
|
-
alias orig_request_call request_call
|
39
|
-
def request_call(datum)
|
40
|
-
url = _httplog_url(datum)
|
41
|
-
|
42
|
-
if HttpLog.url_approved?(url)
|
43
|
-
HttpLog.log_request(datum[:method], _httplog_url(datum))
|
44
|
-
HttpLog.log_headers(datum[:headers])
|
45
|
-
HttpLog.log_data(datum[:body]) # if datum[:method] == :post
|
46
|
-
end
|
47
|
-
orig_request_call(datum)
|
48
|
-
end
|
49
|
-
|
50
|
-
alias orig_response response
|
51
|
-
def response(datum = {})
|
52
|
-
return orig_response(datum) unless HttpLog.url_approved?(_httplog_url(datum))
|
53
|
-
|
54
|
-
datum = orig_response(datum)
|
55
|
-
response = datum[:response]
|
56
|
-
headers = response[:headers] || {}
|
57
|
-
HttpLog.log_status(response[:status])
|
58
|
-
HttpLog.log_headers(headers)
|
59
|
-
HttpLog.log_body(response[:body], headers['Content-Encoding'], headers['Content-Type'])
|
60
|
-
datum
|
61
|
-
end
|
62
52
|
end
|
63
53
|
end
|
64
54
|
end
|
@@ -8,11 +8,7 @@ if defined?(::HTTP::Client) && defined?(::HTTP::Connection)
|
|
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
|
-
|
13
|
-
if log_enabled
|
14
|
-
HttpLog.log_request(req.verb, req.uri)
|
15
|
-
HttpLog.log_headers(req.headers.to_h)
|
11
|
+
if HttpLog.url_approved?(req.uri)
|
16
12
|
|
17
13
|
body = if defined?(::HTTP::Request::Body)
|
18
14
|
req.body.respond_to?(:source) ? req.body.source : req.body.instance_variable_get(:@body)
|
@@ -20,21 +16,24 @@ if defined?(::HTTP::Client) && defined?(::HTTP::Connection)
|
|
20
16
|
req.body
|
21
17
|
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
19
|
+
bm = Benchmark.realtime do
|
20
|
+
@response = send(orig_request_method, req, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
HttpLog.call(
|
24
|
+
method: req.verb,
|
25
|
+
url: req.uri,
|
26
|
+
request_body: body,
|
27
|
+
request_headers: req.headers,
|
28
|
+
response_code: @response.code,
|
29
|
+
response_body: @response.body,
|
30
|
+
response_headers: @response.headers,
|
31
|
+
benchmark: bm,
|
32
|
+
encoding: @response.headers['Content-Encoding'],
|
33
|
+
content_type: @response.headers['Content-Type']
|
34
|
+
)
|
30
35
|
|
31
|
-
|
32
|
-
headers = @response.headers
|
33
|
-
HttpLog.log_compact(req.verb, req.uri, @response.code, bm)
|
34
|
-
HttpLog.log_status(@response.code)
|
35
|
-
HttpLog.log_benchmark(bm)
|
36
|
-
HttpLog.log_headers(@response.headers.to_h)
|
37
|
-
HttpLog.log_body(@response.body, headers['Content-Encoding'], headers['Content-Type'])
|
36
|
+
body.rewind if body.respond_to?(:rewind)
|
38
37
|
end
|
39
38
|
|
40
39
|
@response
|
@@ -7,14 +7,6 @@ if defined?(::HTTPClient)
|
|
7
7
|
alias orig_do_get_block do_get_block
|
8
8
|
|
9
9
|
def do_get_block(req, proxy, conn, &block)
|
10
|
-
log_enabled = HttpLog.url_approved?(req.header.request_uri)
|
11
|
-
|
12
|
-
if log_enabled
|
13
|
-
HttpLog.log_request(req.header.request_method, req.header.request_uri)
|
14
|
-
HttpLog.log_headers(req.headers)
|
15
|
-
HttpLog.log_data(req.body)
|
16
|
-
end
|
17
|
-
|
18
10
|
retryable_response = nil
|
19
11
|
bm = Benchmark.realtime do
|
20
12
|
begin
|
@@ -24,14 +16,21 @@ if defined?(::HTTPClient)
|
|
24
16
|
end
|
25
17
|
end
|
26
18
|
|
27
|
-
if
|
19
|
+
if HttpLog.url_approved?(req.header.request_uri)
|
28
20
|
res = conn.pop
|
29
|
-
|
30
|
-
HttpLog.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
|
22
|
+
HttpLog.call(
|
23
|
+
method: req.header.request_method,
|
24
|
+
url: req.header.request_uri,
|
25
|
+
request_body: req.body,
|
26
|
+
request_headers: req.headers,
|
27
|
+
response_code: res.status_code,
|
28
|
+
response_body: res.body,
|
29
|
+
response_headers: res.headers,
|
30
|
+
benchmark: bm,
|
31
|
+
encoding: res.headers['Content-Encoding'],
|
32
|
+
content_type: res.headers['Content-Type']
|
33
|
+
)
|
35
34
|
conn.push(res)
|
36
35
|
end
|
37
36
|
|