faraday-stack 0.1.0 → 0.1.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.
data/README.md CHANGED
@@ -38,7 +38,9 @@ Awesome example:
38
38
  * raises exceptions on 4xx, 5xx responses
39
39
  * follows redirects
40
40
 
41
- Optional features:
41
+ To see how the default stack is built, see "[faraday_stack.rb][source]".
42
+
43
+ ### Optional features:
42
44
 
43
45
  * encode POST/PUT bodies as JSON:
44
46
 
@@ -55,7 +57,14 @@ Optional features:
55
57
  :namespace => 'faraday', :expires_in => 3600
56
58
  end
57
59
 
58
- To see how the default stack is built, see "[faraday_stack.rb][source]".
60
+ * mount [Rack::Cache][] through `RackCompatible` middleware for HTTP caching of responses
61
+
62
+ conn.builder.insert_after FaradayStack::FollowRedirects, FaradayStack::RackCompatible,
63
+ Rack::Cache::Context,
64
+ :metastore => "file:/var/cache/rack/meta",
65
+ :entitystore => "file:/var/cache/rack/body"
66
+
59
67
 
60
68
  [faraday]: https://github.com/technoweenie/faraday
61
69
  [source]: https://github.com/mislav/faraday-stack/blob/master/lib/faraday_stack.rb
70
+ [rack::cache]: http://rtomayko.github.com/rack-cache/
data/lib/faraday_stack.rb CHANGED
@@ -28,13 +28,22 @@ module FaradayStack
28
28
  end
29
29
 
30
30
  def self.build(url = nil, options = {})
31
- Faraday::Connection.new(url, options) do |builder|
31
+ klass = nil
32
+ if url.is_a?(Hash) then options = url.dup
33
+ elsif url.is_a?(Class) then klass = url
34
+ else options = options.merge(:url => url)
35
+ end
36
+
37
+ klass ||= options.delete(:class) || Faraday::Connection
38
+
39
+ klass.new(options) do |builder|
32
40
  builder.request :url_encoded
33
41
  builder.request :json
34
42
  yield builder if block_given?
35
43
  builder.use ResponseXML, :content_type => /[+\/]xml$/
36
44
  builder.use ResponseHTML, :content_type => 'text/html'
37
- builder.use ResponseJSON, :content_type => 'application/json'
45
+ builder.use ResponseJSON, :content_type => /(application|text)\/json/
46
+ builder.use ResponseJSON::MimeTypeFix, :content_type => /text\/(plain|javascript)/
38
47
  builder.use FollowRedirects
39
48
  builder.response :raise_error
40
49
  builder.adapter Faraday.default_adapter
@@ -1,18 +1,20 @@
1
1
  require 'addressable/uri'
2
2
 
3
- # fix `normalized_query` by sorting query key-value pairs
4
- # (rejected: https://github.com/sporkmonger/addressable/issues/28)
5
- class Addressable::URI
6
- class << self
7
- alias old_normalize_component normalize_component
3
+ # feature-detect the bug
4
+ unless Addressable::URI.parse('/?a=1&b=2') === '/?b=2&a=1'
5
+ # fix `normalized_query` by sorting query key-value pairs
6
+ # (rejected: https://github.com/sporkmonger/addressable/issues/28)
7
+ class Addressable::URI
8
+ alias normalized_query_without_ordering_fix normalized_query
8
9
 
9
- def normalize_component(component, character_class = CharacterClasses::RESERVED + CharacterClasses::UNRESERVED)
10
- normalized = old_normalize_component(component, character_class)
11
- if character_class == Addressable::URI::CharacterClasses::QUERY
12
- pairs = normalized.split('&').sort_by { |pair| pair[0, pair.index('=') || pair.length] }
13
- normalized = pairs.join('&')
10
+ def normalized_query
11
+ fresh = @normalized_query.nil?
12
+ query = normalized_query_without_ordering_fix
13
+ if query && fresh
14
+ @normalized_query = query.split('&', -1).sort_by {|q| q[0..(q.index('=')||-1)] }.join('&')
15
+ else
16
+ query
14
17
  end
15
- normalized
16
18
  end
17
19
  end
18
20
  end
@@ -24,14 +24,11 @@ module FaradayStack
24
24
  end
25
25
 
26
26
  def cache_key(env)
27
- url = env[:url]
28
- if params_to_strip.any?
29
- url = url.dup
27
+ url = env[:url].dup
28
+ if url.query && params_to_strip.any?
30
29
  url.query_values = url.query_values.reject { |k,| params_to_strip.include? k }
31
- url.normalize!
32
- else
33
- url = url.normalize
34
30
  end
31
+ url.normalize!
35
32
  url.request_uri
36
33
  end
37
34
 
@@ -28,5 +28,23 @@ module FaradayStack
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ # writes the correct MIME-type if the payload looks like JSON
33
+ class MimeTypeFix < ResponseMiddleware
34
+ def on_complete(env)
35
+ if process_response_type?(response_type(env)) and looks_like_json?(env)
36
+ old_type = env[:response_headers][CONTENT_TYPE]
37
+ new_type = 'application/json'
38
+ new_type << ';' << old_type.split(';', 2).last if old_type.index(';')
39
+ env[:response_headers][CONTENT_TYPE] = new_type
40
+ end
41
+ end
42
+
43
+ BRACKETS = %w- [ { -
44
+
45
+ def looks_like_json?(env)
46
+ parse_response?(env) and BRACKETS.include? env[:body][0,1]
47
+ end
48
+ end
31
49
  end
32
50
  end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+ require 'forwardable'
3
+
4
+ class FactoryTest < Test::Unit::TestCase
5
+ extend Forwardable
6
+ def_delegator FaradayStack, :build
7
+
8
+ class CustomConnection < Faraday::Connection
9
+ end
10
+
11
+ def test_default_connection
12
+ assert_instance_of Faraday::Connection, FaradayStack.default_connection
13
+ end
14
+
15
+ def test_build_subclass
16
+ assert_instance_of CustomConnection, build(CustomConnection)
17
+ end
18
+
19
+ def test_build_url
20
+ conn = FaradayStack.build('http://example.com')
21
+ assert_equal 'example.com', conn.host
22
+ end
23
+
24
+ def test_build_url_in_options
25
+ conn = FaradayStack.build(:url => 'http://example.com')
26
+ assert_equal 'example.com', conn.host
27
+ end
28
+ end
@@ -7,6 +7,8 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
7
7
  b.use @json_handler
8
8
  b.adapter :test do |stub|
9
9
  stub.get('json') { [200, {'Content-Type' => 'application/json; charset=utf-8'}, "[1,2,3]"] }
10
+ stub.get('bad_mime') { [200, {'Content-Type' => 'text/javascript; charset=utf-8'}, "[1,2,3]"] }
11
+ stub.get('js') { [200, {'Content-Type' => 'text/javascript'}, "alert('hello')"] }
10
12
  stub.get('blank') { [200, {'Content-Type' => 'application/json'}, ''] }
11
13
  stub.get('nil') { [200, {'Content-Type' => 'application/json'}, nil] }
12
14
  stub.get('bad_json') { [200, {'Content-Type' => 'application/json'}, '<body></body>']}
@@ -19,6 +21,10 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
19
21
  @conn.builder.swap @json_handler, @json_handler, :content_type => types
20
22
  end
21
23
 
24
+ def with_mime_type_fix(*types)
25
+ @conn.builder.insert_after @json_handler, FaradayStack::ResponseJSON::MimeTypeFix, :content_type => types
26
+ end
27
+
22
28
  def test_uses_json_to_parse_json_content
23
29
  response = @conn.get('json')
24
30
  assert response.success?
@@ -69,4 +75,19 @@ class ResponseMiddlewareTest < Test::Unit::TestCase
69
75
  assert_equal 'text/html', response.headers['Content-Type']
70
76
  assert_equal '<body></body>', response.body
71
77
  end
78
+
79
+ def test_mime_type_fix
80
+ process_only('application/json')
81
+ with_mime_type_fix
82
+ response = @conn.get('bad_mime')
83
+ assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
84
+ assert_equal [1,2,3], response.body
85
+ end
86
+
87
+ def test_mime_type_fix_conditional
88
+ process_only('application/json')
89
+ with_mime_type_fix
90
+ response = @conn.get('js')
91
+ assert_equal 'text/javascript', response.headers['Content-Type']
92
+ end
72
93
  end
metadata CHANGED
@@ -1,34 +1,45 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: faraday-stack
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 2
9
+ version: 0.1.2
6
10
  platform: ruby
7
- authors:
8
- - Mislav Marohnić
11
+ authors:
12
+ - "Mislav Marohni\xC4\x87"
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2011-04-01 00:00:00.000000000 +02:00
16
+
17
+ date: 2011-06-13 00:00:00 +02:00
13
18
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
16
21
  name: faraday
17
- requirement: &2164745380 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
18
24
  none: false
19
- requirements:
25
+ requirements:
20
26
  - - ~>
21
- - !ruby/object:Gem::Version
22
- version: '0.6'
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 6
31
+ version: "0.6"
23
32
  type: :runtime
24
- prerelease: false
25
- version_requirements: *2164745380
33
+ version_requirements: *id001
26
34
  description:
27
35
  email: mislav.marohnic@gmail.com
28
36
  executables: []
37
+
29
38
  extensions: []
39
+
30
40
  extra_rdoc_files: []
31
- files:
41
+
42
+ files:
32
43
  - lib/faraday-stack.rb
33
44
  - lib/faraday_stack/addressable_patch.rb
34
45
  - lib/faraday_stack/caching.rb
@@ -41,33 +52,42 @@ files:
41
52
  - lib/faraday_stack/response_xml.rb
42
53
  - lib/faraday_stack.rb
43
54
  - test/caching_test.rb
55
+ - test/factory_test.rb
44
56
  - test/follow_redirects_test.rb
45
57
  - test/response_middleware_test.rb
46
58
  - test/test_helper.rb
47
59
  - README.md
48
- has_rdoc: false
60
+ has_rdoc: true
49
61
  homepage: https://github.com/mislav/faraday-stack
50
62
  licenses: []
63
+
51
64
  post_install_message:
52
65
  rdoc_options: []
53
- require_paths:
66
+
67
+ require_paths:
54
68
  - lib
55
- required_ruby_version: !ruby/object:Gem::Requirement
69
+ required_ruby_version: !ruby/object:Gem::Requirement
56
70
  none: false
57
- requirements:
58
- - - ! '>='
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
- required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
78
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
67
85
  requirements: []
86
+
68
87
  rubyforge_project:
69
- rubygems_version: 1.5.3
88
+ rubygems_version: 1.3.7
70
89
  signing_key:
71
90
  specification_version: 3
72
91
  summary: Great Faraday stack for consuming all kinds of APIs
73
92
  test_files: []
93
+