api_hammer 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea5469a646316cf076f0fb0016ac81b661c864f4
4
- data.tar.gz: 45c3e691c8692b974496e8ffd40fb213bedf8f41
3
+ metadata.gz: c2f9e2e65c6bd39813bce85257d2ff06f3a9296c
4
+ data.tar.gz: dd5ba2a6902c635d761edf351399820ace975bfc
5
5
  SHA512:
6
- metadata.gz: e953cde20b88e2ee2bc2804a5c030b55abad006a90fe9f7794970da303db467116833fe069f4059a155489e31cde8373f57759f82df58a384b8b0ef035a4f2af
7
- data.tar.gz: 534622ea02a5d88b6ea43e4d6f4f110c15394c4b1a612f310af3841598c6aef14e30a50501b0eb596d463b2c878ce4ce3c4b209179b5966687e0ebcce6d080ff
6
+ metadata.gz: 22059c86a14b39b299ca220fe0465ebcd0fd2d220832a3c49152f02c82b40aca902032c9fd1649cb2052046ac8836e234d7052dd454211feb4d6249fbedbcd57
7
+ data.tar.gz: 907c407c523d113eb6ceb0c21bcb32357dd4bb26c71fd08d3b27e8d0dd721473f4d1a6bf62d87e216e1c504f850a82f3c81e441b23486652cfe07697f365f520
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 0.4.2
2
+ - bugfix encoding in faraday request logger
3
+
1
4
  # 0.4.1
2
5
  - bugfix
3
6
 
@@ -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.body,
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,
@@ -1,3 +1,3 @@
1
1
  module ApiHammer
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -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.1
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-02 00:00:00.000000000 Z
11
+ date: 2014-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack