api_hammer 0.7.1 → 0.8.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/CHANGELOG.md +3 -0
- data/lib/api_hammer/request_logger.rb +23 -23
- data/lib/api_hammer/version.rb +1 -1
- data/test/check_required_params_test.rb +7 -7
- data/test/halt_test.rb +1 -1
- data/test/request_logger_test.rb +13 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac61ce80519fdf3583b64584b95987a4c19c1f70
|
4
|
+
data.tar.gz: 3b9b20ab3729e8c9a473747f54652da7cc947284
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3cac57cc7ac0e03057b8b5bb5b2c10cc96af35e1df16ff635476ce332bd3855f5a7c13aab42051e29543b7f734615984f99bbbe0d7327bed55eeee7aefb56e3
|
7
|
+
data.tar.gz: ed7d082a200f2b6c4cab977afb1c32cb02dc997b65c0f5369197cac176f53dd1f13c6adc3ab408b94fd47f5948a8dc18eae1e88eb21f1854d67c7b6a3088d624
|
data/CHANGELOG.md
CHANGED
@@ -15,6 +15,8 @@ module ApiHammer
|
|
15
15
|
class RequestLogger < Rack::CommonLogger
|
16
16
|
include Term::ANSIColor
|
17
17
|
|
18
|
+
LARGE_BODY_SIZE = 4096
|
19
|
+
|
18
20
|
def call(env)
|
19
21
|
began_at = Time.now
|
20
22
|
|
@@ -97,31 +99,29 @@ module ApiHammer
|
|
97
99
|
'activesupport_tagged_logging_tags' => log_tags,
|
98
100
|
}.merge(env['request_logger.info'] || {}).merge(Thread.current['request_logger.info'] || {}).reject { |k,v| v.nil? },
|
99
101
|
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
response_body_string = response_body.to_enum.to_a.join('')
|
103
|
+
body_info = [['request', request_body, request.content_type], ['response', response_body_string, response.content_type]]
|
104
|
+
body_info.map do |(role, body, content_type)|
|
105
|
+
if (400..599).include?(status.to_i) || body.size < LARGE_BODY_SIZE
|
106
|
+
# log bodies if they are not large, or if there was an error (either client or server)
|
107
|
+
data[role]['body'] = body
|
108
|
+
else
|
109
|
+
# otherwise, log id and uuid fields
|
110
|
+
media_type = ::Rack::Request.new({'CONTENT_TYPE' => content_type}).media_type
|
111
|
+
body_object = begin
|
112
|
+
if media_type == 'application/json'
|
113
|
+
JSON.parse(body) rescue nil
|
114
|
+
elsif media_type == 'application/x-www-form-urlencoded'
|
115
|
+
CGI.parse(body).map { |k, vs| {k => vs.last} }.inject({}, &:update)
|
116
|
+
end
|
107
117
|
end
|
118
|
+
if body_object.is_a?(Hash)
|
119
|
+
sep = /(?:\b|\W|_)/
|
120
|
+
body_ids = body_object.reject { |key, value| !(key =~ /#{sep}([ug]u)?id#{sep}/ && value.is_a?(String)) }
|
121
|
+
end
|
122
|
+
|
123
|
+
data[role]['body_ids'] = body_ids if body_ids && body_ids.any?
|
108
124
|
end
|
109
|
-
if body_object.is_a?(Hash)
|
110
|
-
sep = /(?:\b|\W|_)/
|
111
|
-
body_object.reject { |key, value| !(key =~ /#{sep}([ug]u)?id#{sep}/ && value.is_a?(String)) }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
response_body_string = response_body.to_enum.to_a.join('')
|
115
|
-
if (400..599).include?(status.to_i)
|
116
|
-
# only log bodies if there was an error (either client or server)
|
117
|
-
data['request']['body'] = request_body
|
118
|
-
data['response']['body'] = response_body_string
|
119
|
-
else
|
120
|
-
# otherwise, log id and uuid fields
|
121
|
-
request_body_ids = ids_from_body.call(request_body, request.content_type)
|
122
|
-
data['request']['body_ids'] = request_body_ids if request_body_ids && request_body_ids.any?
|
123
|
-
response_body_ids = ids_from_body.call(response_body_string, response.content_type)
|
124
|
-
data['response']['body_ids'] = response_body_ids if response_body_ids && response_body_ids.any?
|
125
125
|
end
|
126
126
|
Thread.current['request_logger.info'] = nil
|
127
127
|
json_data = JSON.dump(data)
|
data/lib/api_hammer/version.rb
CHANGED
@@ -25,43 +25,43 @@ describe 'ApiHammer::Rails#check_required_params' do
|
|
25
25
|
it 'is missing id' do
|
26
26
|
c = controller_with_params(:person => {:name => 'hammer', :height => '3'}, :lucky_numbers => ['2'])
|
27
27
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
28
|
-
assert_equal({'errors' => {'id' => ['is required but was not provided']}}, err.body)
|
28
|
+
assert_equal({'error_message' => 'id is required but was not provided', 'errors' => {'id' => ['id is required but was not provided']}}, err.body)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'is missing person' do
|
32
32
|
c = controller_with_params(:id => '99', :lucky_numbers => ['2'])
|
33
33
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
34
|
-
assert_equal({'errors' => {'person' => ['is required but was not provided']}}, err.body)
|
34
|
+
assert_equal({'error_message' => 'person is required but was not provided', 'errors' => {'person' => ['person is required but was not provided']}}, err.body)
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'is has the wrong type for person' do
|
38
38
|
c = controller_with_params(:id => '99', :person => ['hammer', '3'], :lucky_numbers => ['2'])
|
39
39
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
40
|
-
assert_equal({'errors' => {'person' => ['must be a Hash']}}, err.body)
|
40
|
+
assert_equal({'error_message' => 'person must be a Hash', 'errors' => {'person' => ['person must be a Hash']}}, err.body)
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'is missing person#name' do
|
44
44
|
c = controller_with_params(:id => '99', :person => {:height => '3'}, :lucky_numbers => ['2'])
|
45
45
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
46
|
-
assert_equal({'errors' => {'person#name' => ['is required but was not provided']}}, err.body)
|
46
|
+
assert_equal({'error_message' => 'person#name is required but was not provided', 'errors' => {'person#name' => ['person#name is required but was not provided']}}, err.body)
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'is missing lucky_numbers' do
|
50
50
|
c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'})
|
51
51
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
52
|
-
assert_equal({'errors' => {'lucky_numbers' => ['is required but was not provided']}}, err.body)
|
52
|
+
assert_equal({'error_message' => 'lucky_numbers is required but was not provided', 'errors' => {'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'has the wrong type for lucky_numbers' do
|
56
56
|
c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'}, :lucky_numbers => '2')
|
57
57
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
58
|
-
assert_equal({'errors' => {'lucky_numbers' => ['must be a Array']}}, err.body)
|
58
|
+
assert_equal({'error_message' => 'lucky_numbers must be a Array', 'errors' => {'lucky_numbers' => ['lucky_numbers must be a Array']}}, err.body)
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'has multiple problems' do
|
62
62
|
c = controller_with_params({})
|
63
63
|
err = assert_raises(ApiHammer::Halt) { c.check_required_params(checks) }
|
64
|
-
assert_equal({'errors' => {'id' => ['is required but was not provided'], 'person' => ['is required but was not provided'], 'lucky_numbers' => ['is required but was not provided']}}, err.body)
|
64
|
+
assert_equal({'error_message' => 'id is required but was not provided. person is required but was not provided. lucky_numbers is required but was not provided.', 'errors' => {'id' => ['id is required but was not provided'], 'person' => ['person is required but was not provided'], 'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
data/test/halt_test.rb
CHANGED
@@ -50,7 +50,7 @@ describe 'ApiHammer::Rails#halt' do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
haltex = assert_raises(ApiHammer::Halt) { FakeController.new.find_or_halt(model, {:id => 'anid'}) }
|
53
|
-
assert_equal({'errors' => {'record' => ['Unknown record! id: anid']}}, haltex.body)
|
53
|
+
assert_equal({'error_message' => 'Unknown record! id: anid', 'errors' => {'record' => ['Unknown record! id: anid']}}, haltex.body)
|
54
54
|
assert_equal(404, haltex.render_options[:status])
|
55
55
|
end
|
56
56
|
end
|
data/test/request_logger_test.rb
CHANGED
@@ -22,23 +22,30 @@ describe ApiHammer::RequestLogger do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'logs id and uuid (json)' do
|
25
|
-
body = %
|
25
|
+
body = %Q({"uuid": "theuuid", "foo_uuid": "thefoouuid", "id": "theid", "id_for_x": "theidforx", "bar.id": "thebarid", "baz-guid": "bazzz", "bigthing": "#{' ' * 4096}"})
|
26
26
|
app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }, logger)
|
27
27
|
app.call(Rack::MockRequest.env_for('/')).last.close
|
28
28
|
assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'logs id and uuid (form encoded)' do
|
32
|
-
body = %
|
32
|
+
body = %Q(uuid=theuuid&foo_uuid=thefoouuid&id=theid&id_for_x=theidforx&bar.id=thebarid&baz-guid=bazzz&bigthing=#{' ' * 4096})
|
33
33
|
app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/x-www-form-urlencoded; charset=UTF8'}, [body]] }, logger)
|
34
34
|
app.call(Rack::MockRequest.env_for('/')).last.close
|
35
35
|
assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
|
36
36
|
end
|
37
37
|
|
38
|
-
it 'logs request
|
39
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [
|
38
|
+
it 'logs not-too-big request response bodies' do
|
39
|
+
app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, ['the_response_body']] }, logger)
|
40
40
|
app.call(Rack::MockRequest.env_for('/', :input => 'the_request_body')).last.close
|
41
|
-
assert_match(/"request":\{.*"body":"the_request_body
|
42
|
-
assert_match(/"response":\{.*"body":"the_response_body
|
41
|
+
assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
|
42
|
+
assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'logs request and response body on error (even if big)' do
|
46
|
+
app = ApiHammer::RequestLogger.new(proc { |env| [400, {}, ["the_response_body #{' ' * 4096}"]] }, logger)
|
47
|
+
app.call(Rack::MockRequest.env_for('/', :input => "the_request_body #{' ' * 4096}")).last.close
|
48
|
+
assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
|
49
|
+
assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
|
43
50
|
end
|
44
51
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_hammer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|