api_hammer 0.4.1 → 0.4.2
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/faraday/request_logger.rb +65 -1
- data/lib/api_hammer/version.rb +1 -1
- data/test/faraday_request_logger_test.rb +52 -0
- 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: c2f9e2e65c6bd39813bce85257d2ff06f3a9296c
|
|
4
|
+
data.tar.gz: dd5ba2a6902c635d761edf351399820ace975bfc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22059c86a14b39b299ca220fe0465ebcd0fd2d220832a3c49152f02c82b40aca902032c9fd1649cb2052046ac8836e234d7052dd454211feb4d6249fbedbcd57
|
|
7
|
+
data.tar.gz: 907c407c523d113eb6ceb0c21bcb32357dd4bb26c71fd08d3b27e8d0dd721473f4d1a6bf62d87e216e1c504f850a82f3c81e441b23486652cfe07697f365f520
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,7 @@ require 'faraday'
|
|
|
2
2
|
require 'rack'
|
|
3
3
|
require 'term/ansicolor'
|
|
4
4
|
require 'json'
|
|
5
|
+
require 'strscan'
|
|
5
6
|
|
|
6
7
|
if Faraday.respond_to?(:register_middleware)
|
|
7
8
|
Faraday.register_middleware(:request, :api_hammer_request_logger => proc { ApiHammer::Faraday::RequestLogger })
|
|
@@ -28,6 +29,69 @@ module ApiHammer
|
|
|
28
29
|
@options = options
|
|
29
30
|
end
|
|
30
31
|
|
|
32
|
+
# deal with the vagaries of getting the response body in a form which JSON
|
|
33
|
+
# gem will not cry about dumping
|
|
34
|
+
def response_body(response_env)
|
|
35
|
+
# first try to change the string's encoding per the Content-Type header
|
|
36
|
+
content_type = response_env.response_headers['Content-Type']
|
|
37
|
+
response_body = response_env.body.dup
|
|
38
|
+
unless response_body.valid_encoding?
|
|
39
|
+
# I think this always comes in as ASCII-8BIT anyway so may never get here. hopefully.
|
|
40
|
+
response_body.force_encoding('ASCII-8BIT')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if content_type
|
|
44
|
+
# TODO refactor this parsing somewhere better?
|
|
45
|
+
parsed = false
|
|
46
|
+
attributes = Hash.new { |h,k| h[k] = [] }
|
|
47
|
+
catch(:unparseable) do
|
|
48
|
+
uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
|
49
|
+
scanner = StringScanner.new(content_type)
|
|
50
|
+
scanner.scan(/.*;\s*/) || throw(:unparseable)
|
|
51
|
+
while match = scanner.scan(/(\w+)=("?)([^"]*)("?)\s*(,?)\s*/)
|
|
52
|
+
key = scanner[1]
|
|
53
|
+
quote1 = scanner[2]
|
|
54
|
+
value = scanner[3]
|
|
55
|
+
quote2 = scanner[4]
|
|
56
|
+
comma_follows = !scanner[5].empty?
|
|
57
|
+
throw(:unparseable) unless quote1 == quote2
|
|
58
|
+
throw(:unparseable) if !comma_follows && !scanner.eos?
|
|
59
|
+
attributes[uri_parser.unescape(key)] << uri_parser.unescape(value)
|
|
60
|
+
end
|
|
61
|
+
throw(:unparseable) unless scanner.eos?
|
|
62
|
+
parsed = true
|
|
63
|
+
end
|
|
64
|
+
if parsed
|
|
65
|
+
charset = attributes['charset'].first
|
|
66
|
+
if Encoding.list.any? { |enc| enc.to_s.downcase == charset.downcase }
|
|
67
|
+
if response_body.dup.force_encoding(charset).valid_encoding?
|
|
68
|
+
response_body.force_encoding(charset)
|
|
69
|
+
else
|
|
70
|
+
# I guess just ignore the specified encoding if the result is not valid. fall back to
|
|
71
|
+
# something else below.
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
begin
|
|
77
|
+
JSON.dump([response_body])
|
|
78
|
+
rescue Encoding::UndefinedConversionError
|
|
79
|
+
# if updating by content-type didn't do it, try UTF8 since JSON wants that - but only
|
|
80
|
+
# if it seems to be valid utf8.
|
|
81
|
+
# don't try utf8 if the response content-type indicated something else.
|
|
82
|
+
try_utf8 = !(parsed && attributes['charset'].any?)
|
|
83
|
+
if try_utf8 && response_body.dup.force_encoding('UTF-8').valid_encoding?
|
|
84
|
+
response_body.force_encoding('UTF-8')
|
|
85
|
+
else
|
|
86
|
+
# I'm not sure if there is a way in this situation to get JSON gem to dump the
|
|
87
|
+
# string correctly. fall back to an array of codepoints I guess? this is a weird
|
|
88
|
+
# solution but the best I've got for now.
|
|
89
|
+
response_body = response_body.codepoints.to_a
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
response_body
|
|
93
|
+
end
|
|
94
|
+
|
|
31
95
|
def call(request_env)
|
|
32
96
|
began_at = Time.now
|
|
33
97
|
|
|
@@ -60,7 +124,7 @@ module ApiHammer
|
|
|
60
124
|
'response' => {
|
|
61
125
|
'status' => response_env.status,
|
|
62
126
|
'headers' => response_env.response_headers,
|
|
63
|
-
'body' => response_env
|
|
127
|
+
'body' => response_body(response_env),
|
|
64
128
|
}.reject{|k,v| v.nil? },
|
|
65
129
|
'processing' => {
|
|
66
130
|
'began_at' => began_at.utc.to_i,
|
data/lib/api_hammer/version.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
4
|
require 'helper'
|
|
3
5
|
require 'logger'
|
|
@@ -41,4 +43,54 @@ describe ApiHammer::RequestLogger do
|
|
|
41
43
|
conn.get '/'
|
|
42
44
|
assert_match(/200/, logio.string)
|
|
43
45
|
end
|
|
46
|
+
|
|
47
|
+
describe 'response body encoding' do
|
|
48
|
+
it 'deals with encoding specified properly by the content type' do
|
|
49
|
+
app = proc do |env|
|
|
50
|
+
[200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
|
|
51
|
+
end
|
|
52
|
+
conn = Faraday.new do |f|
|
|
53
|
+
f.request :api_hammer_request_logger, logger
|
|
54
|
+
f.use Faraday::Adapter::Rack, app
|
|
55
|
+
end
|
|
56
|
+
conn.get '/'
|
|
57
|
+
assert_match(/Jalapeños/, logio.string)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'deals with encoding not specified by the content type' do
|
|
61
|
+
app = proc do |env|
|
|
62
|
+
[200, {}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
|
|
63
|
+
end
|
|
64
|
+
conn = Faraday.new do |f|
|
|
65
|
+
f.request :api_hammer_request_logger, logger
|
|
66
|
+
f.use Faraday::Adapter::Rack, app
|
|
67
|
+
end
|
|
68
|
+
conn.get '/'
|
|
69
|
+
assert_match(/Jalapeños/, logio.string)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'falls back to array of codepoints when encoding is improperly specified by the content type' do
|
|
73
|
+
app = proc do |env|
|
|
74
|
+
[200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["xx" + [195].pack("C*")]]
|
|
75
|
+
end
|
|
76
|
+
conn = Faraday.new do |f|
|
|
77
|
+
f.request :api_hammer_request_logger, logger
|
|
78
|
+
f.use Faraday::Adapter::Rack, app
|
|
79
|
+
end
|
|
80
|
+
conn.get '/'
|
|
81
|
+
assert_match('[120,120,195]', logio.string)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'falls back to array of codepoints when encoding is not specified and not valid utf8' do
|
|
85
|
+
app = proc do |env|
|
|
86
|
+
[200, {}, ["xx" + [195].pack("C*")]]
|
|
87
|
+
end
|
|
88
|
+
conn = Faraday.new do |f|
|
|
89
|
+
f.request :api_hammer_request_logger, logger
|
|
90
|
+
f.use Faraday::Adapter::Rack, app
|
|
91
|
+
end
|
|
92
|
+
conn.get '/'
|
|
93
|
+
assert_match('[120,120,195]', logio.string)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
44
96
|
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.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ethan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-07-
|
|
11
|
+
date: 2014-07-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|