jeffersongirao_faraday-stack 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Über Stack
2
+
3
+ [Faraday][] is an HTTP client lib that provides a common interface over many adapters (such as Net::HTTP) and embraces the concept of Rack middleware when processing the request/response cycle.
4
+
5
+ *“Faraday Stack”* is an add-on library that implements several middleware (such as JSON and XML parsers) and helps you build an awesome stack that covers most of your API-consuming needs.
6
+
7
+ Boring example:
8
+
9
+ require 'faraday_stack'
10
+
11
+ response = FaradayStack.get 'http://google.com'
12
+
13
+ response.headers['content-type'] #=> "text/html; charset=UTF-8"
14
+ response.headers['location'] #=> "http://www.google.com/"
15
+ puts response.body
16
+
17
+ Awesome example:
18
+
19
+ conn = FaradayStack.build 'http://github.com/api/v2'
20
+
21
+ # JSON resource
22
+ resp = conn.get 'json/repos/show/mislav/faraday-stack'
23
+ resp.body
24
+ #=> {"repository"=>{"language"=>"Ruby", "fork"=>false, ...}}
25
+
26
+ # XML resource
27
+ resp = conn.get 'xml/repos/show/mislav/faraday-stack'
28
+ resp.body.class
29
+ #=> Nokogiri::XML::Document
30
+
31
+ # 404
32
+ conn.get 'zomg/wrong/url'
33
+ #=> raises Faraday::Error::ResourceNotFound
34
+
35
+ ## Features
36
+
37
+ * parses JSON, XML & HTML
38
+ * raises exceptions on 4xx, 5xx responses
39
+ * follows redirects
40
+
41
+ To see how the default stack is built, see "[faraday_stack.rb][source]".
42
+
43
+ ### Optional features:
44
+
45
+ * encode POST/PUT bodies as JSON:
46
+
47
+ conn.post(path, payload, :content_type => 'application/json')
48
+
49
+ * add `Instrumentation` middleware to instrument requests with ActiveSupport
50
+
51
+ conn.builder.insert_after Faraday::Response::RaiseError, FaradayStack::Instrumentation
52
+
53
+ * add `Caching` middleware to have GET responses cached
54
+
55
+ conn.builder.insert_before FaradayStack::ResponseJSON, FaradayStack::Caching do
56
+ ActiveSupport::Cache::FileStore.new 'tmp/cache',
57
+ :namespace => 'faraday', :expires_in => 3600
58
+ end
59
+
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
+
67
+
68
+ [faraday]: https://github.com/technoweenie/faraday
69
+ [source]: https://github.com/mislav/faraday-stack/blob/master/lib/faraday_stack.rb
70
+ [rack::cache]: http://rtomayko.github.com/rack-cache/
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/*_test.rb'
9
+ test.verbose = true
10
+ end
@@ -0,0 +1 @@
1
+ require 'faraday_stack'
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require 'faraday'
3
+ require 'forwardable'
4
+ require 'faraday_stack/addressable_patch'
5
+
6
+ module FaradayStack
7
+ extend Faraday::AutoloadHelper
8
+
9
+ autoload_all 'faraday_stack',
10
+ :ResponseMiddleware => 'response_middleware',
11
+ :ResponseJSON => 'response_json',
12
+ :ResponseXML => 'response_xml',
13
+ :ResponseHTML => 'response_html',
14
+ :Instrumentation => 'instrumentation',
15
+ :Caching => 'caching',
16
+ :FollowRedirects => 'follow_redirects',
17
+ :RackCompatible => 'rack_compatible'
18
+
19
+ # THE ÜBER STACK
20
+ def self.default_connection
21
+ @default_connection ||= self.build
22
+ end
23
+
24
+ class << self
25
+ extend Forwardable
26
+ attr_writer :default_connection
27
+ def_delegators :default_connection, :get, :post, :put, :head, :delete
28
+ end
29
+
30
+ def self.build(url = nil, options = {})
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|
40
+ builder.request :url_encoded
41
+ builder.request :json
42
+ yield builder if block_given?
43
+ builder.use ResponseXML, :content_type => /[+\/]xml$/
44
+ builder.use ResponseHTML, :content_type => 'text/html'
45
+ builder.use ResponseJSON, :content_type => /[+\/]json$/
46
+ builder.use ResponseJSON::MimeTypeFix, :content_type => /text\/(plain|javascript)/
47
+ builder.use FollowRedirects
48
+ builder.response :raise_error
49
+ builder.adapter Faraday.default_adapter
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,20 @@
1
+ require 'addressable/uri'
2
+
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
9
+
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
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ module FaradayStack
2
+ class Caching < Faraday::Middleware
3
+ attr_reader :cache
4
+
5
+ def initialize(app, cache = nil, options = {})
6
+ super(app)
7
+ @cache = cache || Proc.new.call
8
+ @options = options
9
+ end
10
+
11
+ def call(env)
12
+ if :get == env[:method]
13
+ if env[:parallel_manager]
14
+ # callback mode
15
+ cache_on_complete(env)
16
+ else
17
+ # synchronous mode
18
+ response = cache.fetch(cache_key(env)) { @app.call(env) }
19
+ finalize_response(response, env)
20
+ end
21
+ else
22
+ @app.call(env)
23
+ end
24
+ end
25
+
26
+ def cache_key(env)
27
+ url = env[:url].dup
28
+ if url.query && params_to_strip.any?
29
+ url.query_values = url.query_values.reject { |k,| params_to_strip.include? k }
30
+ end
31
+ url.normalize!
32
+ url.request_uri
33
+ end
34
+
35
+ def params_to_strip
36
+ @params_to_strip ||= Array(@options[:strip_params]).map { |p| p.to_s }
37
+ end
38
+
39
+ def cache_on_complete(env)
40
+ key = cache_key(env)
41
+ if cached_response = cache.read(key)
42
+ finalize_response(cached_response, env)
43
+ else
44
+ response = @app.call(env)
45
+ response.on_complete { cache.write(key, response) }
46
+ end
47
+ end
48
+
49
+ def finalize_response(response, env)
50
+ response = env[:response] = response.dup if response.frozen?
51
+ response.apply_request env unless response.env[:method]
52
+ response
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,42 @@
1
+ module FaradayStack
2
+ class RedirectLimitReached < Faraday::Error::ClientError
3
+ attr_reader :response
4
+
5
+ def initialize(response)
6
+ super "too many redirects; last one to: #{response['location']}"
7
+ @response = response
8
+ end
9
+ end
10
+
11
+ class FollowRedirects < Faraday::Middleware
12
+ REDIRECTS = [301, 302, 303, 307]
13
+ # default value for max redirects followed
14
+ FOLLOW_LIMIT = 3
15
+
16
+ def initialize(app, options = {})
17
+ super(app)
18
+ @options = options
19
+ @follow_limit = options[:limit] || FOLLOW_LIMIT
20
+ end
21
+
22
+ def call(env)
23
+ process_response(@app.call(env), @follow_limit)
24
+ end
25
+
26
+ def process_response(response, follows)
27
+ response.on_complete do |env|
28
+ if redirect? response
29
+ raise RedirectLimitReached, response if follows.zero?
30
+ env[:url] += response['location']
31
+ env[:method] = :get
32
+ response = process_response(@app.call(env), follows - 1)
33
+ end
34
+ end
35
+ response
36
+ end
37
+
38
+ def redirect?(response)
39
+ REDIRECTS.include? response.status
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module FaradayStack
2
+ # Measures request time only in synchronous request mode.
3
+ # Sample subscriber:
4
+ #
5
+ # ActiveSupport::Notifications.subscribe('request.faraday') do |name, start_time, end_time, _, env|
6
+ # url = env[:url]
7
+ # http_method = env[:method].to_s.upcase
8
+ # duration = end_time - start_time
9
+ # $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration]
10
+ # end
11
+ class Instrumentation < Faraday::Middleware
12
+ dependency 'active_support/notifications'
13
+
14
+ def initialize(app, options = {})
15
+ super(app)
16
+ @options = options
17
+ @name = options[:name] || 'request.faraday'
18
+ end
19
+
20
+ def call(env)
21
+ ActiveSupport::Notifications.instrument(@name, env) do
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,76 @@
1
+ require 'stringio'
2
+
3
+ module FaradayStack
4
+ # Wraps a handler originally written for Rack to make it compatible with Faraday.
5
+ #
6
+ # Experimental. Only handles changes in request headers.
7
+ class RackCompatible
8
+ def initialize(app, rack_handler, *args)
9
+ # tiny middleware that decomposes a Faraday::Response to standard Rack
10
+ # array: [status, headers, body]
11
+ compatible_app = lambda do |env|
12
+ restore_env(env)
13
+ response = app.call(env)
14
+ [response.status, response.headers, Array(response.body)]
15
+ end
16
+ @rack = rack_handler.new(compatible_app, *args)
17
+ end
18
+
19
+ def call(env)
20
+ prepare_env(env)
21
+ rack_response = @rack.call(env)
22
+ finalize_response(env, rack_response)
23
+ end
24
+
25
+ NonPrefixedHeaders = %w[CONTENT_LENGTH CONTENT_TYPE]
26
+
27
+ # faraday to rack-compatible
28
+ def prepare_env(env)
29
+ env[:request_headers].each do |name, value|
30
+ name = name.upcase.tr('-', '_')
31
+ name = "HTTP_#{name}" unless NonPrefixedHeaders.include? name
32
+ env[name] = value
33
+ end
34
+
35
+ url = env[:url]
36
+ env['rack.url_scheme'] = url.scheme
37
+ env['PATH_INFO'] = url.path
38
+ env['SERVER_PORT'] = url.inferred_port
39
+ env['QUERY_STRING'] = url.query
40
+ env['REQUEST_METHOD'] = env[:method].to_s.upcase
41
+
42
+ env['rack.errors'] ||= StringIO.new
43
+
44
+ env
45
+ end
46
+
47
+ # rack to faraday-compatible
48
+ def restore_env(env)
49
+ headers = env[:request_headers]
50
+ headers.clear
51
+
52
+ env.each do |name, value|
53
+ next unless String === name
54
+ if NonPrefixedHeaders.include? name or name.index('HTTP_') == 0
55
+ name = name.sub(/^HTTP_/, '').downcase.tr('_', '-')
56
+ headers[name] = value
57
+ end
58
+ end
59
+
60
+ env[:method] = env['REQUEST_METHOD'].downcase.to_sym
61
+ env
62
+ end
63
+
64
+ def finalize_response(env, rack_response)
65
+ status, headers, body = rack_response
66
+ body = body.inject('') { |str, part| str << part }
67
+ headers = Faraday::Utils::Headers.new(headers) unless Faraday::Utils::Headers === headers
68
+
69
+ response_env = { :status => status, :body => body, :response_headers => headers }
70
+
71
+ env[:response] ||= Faraday::Response.new({})
72
+ env[:response].env.update(response_env)
73
+ env[:response]
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,12 @@
1
+ module FaradayStack
2
+ class ResponseHTML < ResponseMiddleware
3
+ dependency do
4
+ require 'nokogiri'
5
+ Nokogiri::HTML
6
+ end
7
+
8
+ define_parser do |body|
9
+ Nokogiri::HTML body
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ module FaradayStack
2
+ class ResponseJSON < ResponseMiddleware
3
+ adapter_name = nil
4
+
5
+ # loads the JSON decoder either from yajl-ruby or activesupport
6
+ dependency do
7
+ require 'yajl'
8
+ adapter_name = Yajl::Parser.name
9
+ end
10
+
11
+ dependency do
12
+ require 'active_support/json/decoding'
13
+ adapter_name = ActiveSupport::JSON.name
14
+ end unless loaded?
15
+
16
+ # defines a parser block depending on which adapter has loaded
17
+ case adapter_name
18
+ when 'Yajl::Parser'
19
+ define_parser do |body|
20
+ Yajl::Parser.parse(body)
21
+ end
22
+ when 'ActiveSupport::JSON'
23
+ define_parser do |body|
24
+ unless body.nil? or body.empty?
25
+ result = ActiveSupport::JSON.decode(body)
26
+ raise ActiveSupport::JSON.backend::ParseError if String === result
27
+ result
28
+ end
29
+ end
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
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ module FaradayStack
2
+ # A base class for middleware that parses responses
3
+ class ResponseMiddleware < Faraday::Response::Middleware
4
+ CONTENT_TYPE = 'Content-Type'.freeze
5
+
6
+ class << self
7
+ attr_accessor :parser
8
+ end
9
+
10
+ # Stores a block that receives the body and should return a parsed result
11
+ def self.define_parser(&block)
12
+ @parser = block
13
+ end
14
+
15
+ def self.inherited(subclass)
16
+ super
17
+ subclass.load_error = self.load_error
18
+ subclass.parser = self.parser
19
+ end
20
+
21
+ def initialize(app = nil, options = {})
22
+ super(app)
23
+ @options = options
24
+ @content_types = Array(options[:content_type])
25
+ end
26
+
27
+ # Override this to modify the environment after the response has finished.
28
+ def on_complete(env)
29
+ if process_response_type?(response_type(env)) and parse_response?(env)
30
+ env[:body] = parse(env[:body])
31
+ end
32
+ end
33
+
34
+ # Parses the response body and returns the result.
35
+ # Instead of overriding this method, consider using `define_parser`
36
+ def parse(body)
37
+ if self.class.parser
38
+ begin
39
+ self.class.parser.call(body)
40
+ rescue
41
+ raise Faraday::Error::ParsingError, $!
42
+ end
43
+ else
44
+ body
45
+ end
46
+ end
47
+
48
+ def response_type(env)
49
+ type = env[:response_headers][CONTENT_TYPE].to_s
50
+ type = type.split(';', 2).first if type.index(';')
51
+ type
52
+ end
53
+
54
+ def process_response_type?(type)
55
+ @content_types.empty? or @content_types.any? { |pattern|
56
+ Regexp === pattern ? type =~ pattern : type == pattern
57
+ }
58
+ end
59
+
60
+ def parse_response?(env)
61
+ env[:body].respond_to? :to_str
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ module FaradayStack
2
+ class ResponseXML < ResponseMiddleware
3
+ dependency do
4
+ require 'nokogiri'
5
+ Nokogiri::XML
6
+ end
7
+
8
+ define_parser do |body|
9
+ Nokogiri::XML body
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+ require 'forwardable'
3
+ require 'fileutils'
4
+ require 'rack/cache'
5
+
6
+ class CachingTest < Test::Unit::TestCase
7
+ class TestCache < Hash
8
+ def read(key)
9
+ if cached = self[key]
10
+ Marshal.load(cached)
11
+ end
12
+ end
13
+
14
+ def write(key, data)
15
+ self[key] = Marshal.dump(data)
16
+ end
17
+
18
+ def fetch(key)
19
+ read(key) || yield.tap { |data| write(key, data) }
20
+ end
21
+ end
22
+
23
+ def setup
24
+ @cache = TestCache.new
25
+
26
+ request_count = 0
27
+ response = lambda { |env|
28
+ [200, {'Content-Type' => 'text/plain'}, "request:#{request_count+=1}"]
29
+ }
30
+
31
+ @conn = Faraday.new do |b|
32
+ b.use FaradayStack::Caching, @cache
33
+ b.adapter :test do |stub|
34
+ stub.get('/', &response)
35
+ stub.get('/?foo=bar', &response)
36
+ stub.post('/', &response)
37
+ stub.get('/other', &response)
38
+ end
39
+ end
40
+ end
41
+
42
+ extend Forwardable
43
+ def_delegators :@conn, :get, :post
44
+
45
+ def test_cache_get
46
+ assert_equal 'request:1', get('/').body
47
+ assert_equal 'request:1', get('/').body
48
+ assert_equal 'request:2', get('/other').body
49
+ assert_equal 'request:2', get('/other').body
50
+ end
51
+
52
+ def test_response_has_request_params
53
+ get('/') # make cache
54
+ response = get('/')
55
+ assert_equal :get, response.env[:method]
56
+ assert_equal '/', response.env[:url].to_s
57
+ end
58
+
59
+ def test_cache_query_params
60
+ assert_equal 'request:1', get('/').body
61
+ assert_equal 'request:2', get('/?foo=bar').body
62
+ assert_equal 'request:2', get('/?foo=bar').body
63
+ assert_equal 'request:1', get('/').body
64
+ end
65
+
66
+ def test_doesnt_cache_post
67
+ assert_equal 'request:1', post('/').body
68
+ assert_equal 'request:2', post('/').body
69
+ assert_equal 'request:3', post('/').body
70
+ end
71
+ end
72
+
73
+ # RackCompatible + Rack::Cache
74
+ class HttpCachingTest < Test::Unit::TestCase
75
+ include FileUtils
76
+
77
+ CACHE_DIR = File.expand_path('../cache', __FILE__)
78
+
79
+ def setup
80
+ rm_r CACHE_DIR if File.exists? CACHE_DIR
81
+
82
+ request_count = 0
83
+ response = lambda { |env|
84
+ [200, { 'Content-Type' => 'text/plain',
85
+ 'Cache-Control' => 'public, max-age=900',
86
+ },
87
+ "request:#{request_count+=1}"]
88
+ }
89
+
90
+ @conn = Faraday.new do |b|
91
+ b.use FaradayStack::RackCompatible, Rack::Cache::Context,
92
+ :metastore => "file:#{CACHE_DIR}/rack/meta",
93
+ :entitystore => "file:#{CACHE_DIR}/rack/body",
94
+ :verbose => true
95
+
96
+ b.adapter :test do |stub|
97
+ stub.get('/', &response)
98
+ stub.post('/', &response)
99
+ end
100
+ end
101
+ end
102
+
103
+ extend Forwardable
104
+ def_delegators :@conn, :get, :post
105
+
106
+ def test_cache_get
107
+ assert_equal 'request:1', get('/', :user_agent => 'test').body
108
+ response = get('/', :user_agent => 'test')
109
+ assert_equal 'request:1', response.body
110
+ assert_equal 'text/plain', response['content-type']
111
+
112
+ assert_equal 'request:2', post('/').body
113
+ end
114
+
115
+ def test_doesnt_cache_post
116
+ assert_equal 'request:1', get('/').body
117
+ assert_equal 'request:2', post('/').body
118
+ assert_equal 'request:3', post('/').body
119
+ end
120
+ 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
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+ require 'forwardable'
3
+
4
+ class FollowRedirectsTest < Test::Unit::TestCase
5
+ def setup
6
+ @conn = Faraday.new do |b|
7
+ b.use FaradayStack::FollowRedirects
8
+ b.adapter :test do |stub|
9
+ stub.get('/') { [301, {'Location' => '/found'}, ''] }
10
+ stub.post('/create') { [302, {'Location' => '/'}, ''] }
11
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
12
+ stub.get('/loop') { [302, {'Location' => '/loop'}, ''] }
13
+ stub.get('/temp') { [307, {'Location' => '/found'}, ''] }
14
+ end
15
+ end
16
+ end
17
+
18
+ extend Forwardable
19
+ def_delegators :@conn, :get, :post
20
+
21
+ def test_redirected
22
+ assert_equal 'fin', get('/').body
23
+ end
24
+
25
+ def test_redirected_twice
26
+ assert_equal 'fin', post('/create').body
27
+ end
28
+
29
+ def test_redirected_by_temp
30
+ assert_equal 'fin', get('/temp').body
31
+ end
32
+
33
+ def test_redirect_limit
34
+ assert_raises FaradayStack::RedirectLimitReached do
35
+ get('/loop')
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,93 @@
1
+ require 'test_helper'
2
+
3
+ class ResponseMiddlewareTest < Test::Unit::TestCase
4
+ def setup
5
+ @json_handler = FaradayStack::ResponseJSON
6
+ @conn = Faraday.new do |b|
7
+ b.use @json_handler
8
+ b.adapter :test do |stub|
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')"] }
12
+ stub.get('blank') { [200, {'Content-Type' => 'application/json'}, ''] }
13
+ stub.get('nil') { [200, {'Content-Type' => 'application/json'}, nil] }
14
+ stub.get('bad_json') { [200, {'Content-Type' => 'application/json'}, '<body></body>']}
15
+ stub.get('non_json') { [200, {'Content-Type' => 'text/html'}, '<body></body>']}
16
+ end
17
+ end
18
+ end
19
+
20
+ def process_only(*types)
21
+ @conn.builder.swap @json_handler, @json_handler, :content_type => types
22
+ end
23
+
24
+ def with_mime_type_fix(*types)
25
+ @conn.builder.insert_after @json_handler, FaradayStack::ResponseJSON::MimeTypeFix, :content_type => types
26
+ end
27
+
28
+ def test_uses_json_to_parse_json_content
29
+ response = @conn.get('json')
30
+ assert response.success?
31
+ assert_equal [1,2,3], response.body
32
+ end
33
+
34
+ def test_uses_json_to_parse_json_content_conditional
35
+ process_only('application/json')
36
+ response = @conn.get('json')
37
+ assert response.success?
38
+ assert_equal [1,2,3], response.body
39
+ end
40
+
41
+ def test_uses_json_to_parse_json_content_conditional_with_regexp
42
+ process_only(%r{/(x-)?json$})
43
+ response = @conn.get('json')
44
+ assert response.success?
45
+ assert_equal [1,2,3], response.body
46
+ end
47
+
48
+ def test_uses_json_to_skip_blank_content
49
+ response = @conn.get('blank')
50
+ assert response.success?
51
+ assert_nil response.body
52
+ end
53
+
54
+ def test_uses_json_to_skip_nil_content
55
+ response = @conn.get('nil')
56
+ assert response.success?
57
+ assert_nil response.body
58
+ end
59
+
60
+ def test_uses_json_to_raise_Faraday_Error_Parsing_with_no_json_content
61
+ assert_raises Faraday::Error::ParsingError do
62
+ @conn.get('bad_json')
63
+ end
64
+ end
65
+
66
+ def test_non_json_response
67
+ assert_raises Faraday::Error::ParsingError do
68
+ @conn.get('non_json')
69
+ end
70
+ end
71
+
72
+ def test_non_json_response_conditional
73
+ process_only('application/json')
74
+ response = @conn.get('non_json')
75
+ assert_equal 'text/html', response.headers['Content-Type']
76
+ assert_equal '<body></body>', response.body
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
93
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require 'faraday_stack'
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jeffersongirao_faraday-stack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mislav Marohnić
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-15 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: &2157616900 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0.6'
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: '0.8'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: *2157616900
28
+ description:
29
+ email: mislav.marohnic@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Rakefile
35
+ - lib/faraday-stack.rb
36
+ - lib/faraday_stack/addressable_patch.rb
37
+ - lib/faraday_stack/caching.rb
38
+ - lib/faraday_stack/follow_redirects.rb
39
+ - lib/faraday_stack/instrumentation.rb
40
+ - lib/faraday_stack/rack_compatible.rb
41
+ - lib/faraday_stack/response_html.rb
42
+ - lib/faraday_stack/response_json.rb
43
+ - lib/faraday_stack/response_middleware.rb
44
+ - lib/faraday_stack/response_xml.rb
45
+ - lib/faraday_stack.rb
46
+ - test/caching_test.rb
47
+ - test/factory_test.rb
48
+ - test/follow_redirects_test.rb
49
+ - test/response_middleware_test.rb
50
+ - test/test_helper.rb
51
+ - README.md
52
+ homepage: https://github.com/jeffersongirao/faraday-stack
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ segments:
65
+ - 0
66
+ hash: -1051454488374554944
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ segments:
74
+ - 0
75
+ hash: -1051454488374554944
76
+ requirements: []
77
+ rubyforge_project: jeffersongirao_faraday-stack
78
+ rubygems_version: 1.8.10
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: A Temp fork of faraday-stack
82
+ test_files: []