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