faraday-stack 0.1.0 → 0.1.2

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