Permalink
Browse files

add FollowRedirects middleware

  • Loading branch information...
1 parent 0464e52 commit 16869efe75801152efe0f903b955c066605763d2 @mislav committed Mar 28, 2011
Showing with 79 additions and 1 deletion.
  1. +3 −1 lib/faraday_stack.rb
  2. +43 −0 lib/faraday_stack/follow_redirects.rb
  3. +33 −0 test/follow_redirects_test.rb
View
4 lib/faraday_stack.rb
@@ -11,7 +11,8 @@ module FaradayStack
:ResponseXML => 'response_xml',
:ResponseHTML => 'response_html',
:Instrumentation => 'instrumentation',
- :Caching => 'caching'
+ :Caching => 'caching',
+ :FollowRedirects => 'follow_redirects'
# THE ÜBER STACK
def self.default_connection
@@ -32,6 +33,7 @@ def self.build(url = nil, options = {})
builder.use ResponseJSON, :content_type => 'application/json'
builder.use ResponseXML, :content_type => /[+\/]xml$/
builder.use ResponseHTML, :content_type => 'text/html'
+ builder.use FollowRedirects
builder.response :raise_error
builder.adapter Faraday.default_adapter
end
View
43 lib/faraday_stack/follow_redirects.rb
@@ -0,0 +1,43 @@
+module FaradayStack
+ class RedirectLimitReached < Faraday::Error::ClientError
+ attr_reader :response
+
+ def initialize(response)
+ super "too many redirects; last one to: #{response['location']}"
+ @response = response
+ end
+ end
+
+ class FollowRedirects < Faraday::Middleware
+ # TODO: 307
+ REDIRECTS = [301, 302, 303]
+ # default value for max redirects followed
+ FOLLOW_LIMIT = 3
+
+ def initialize(app, options = {})
+ super(app)
+ @options = options
+ @follow_limit = options[:limit] || FOLLOW_LIMIT
+ end
+
+ def call(env)
+ process_response(@app.call(env), @follow_limit)
+ end
+
+ def process_response(response, follows)
+ response.on_complete do |env|
+ if redirect? response
+ raise RedirectLimitReached, response if follows.zero?
+ env[:url] += response['location']
+ env[:method] = :get
+ response = process_response(@app.call(env), follows - 1)
+ end
+ end
+ response
+ end
+
+ def redirect?(response)
+ REDIRECTS.include? response.status
+ end
+ end
+end
View
33 test/follow_redirects_test.rb
@@ -0,0 +1,33 @@
+require 'test_helper'
+require 'forwardable'
+
+class FollowRedirectsTest < Test::Unit::TestCase
+ def setup
+ @conn = Faraday.new do |b|
+ b.use FaradayStack::FollowRedirects
+ b.adapter :test do |stub|
+ stub.get('/') { [301, {'Location' => '/found'}, ''] }
+ stub.post('/create') { [302, {'Location' => '/'}, ''] }
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
+ stub.get('/loop') { [302, {'Location' => '/loop'}, ''] }
+ end
+ end
+ end
+
+ extend Forwardable
+ def_delegators :@conn, :get, :post
+
+ def test_redirected
+ assert_equal 'fin', get('/').body
+ end
+
+ def test_redirected_twice
+ assert_equal 'fin', post('/create').body
+ end
+
+ def test_redirect_limit
+ assert_raises FaradayStack::RedirectLimitReached do
+ get('/loop')
+ end
+ end
+end

0 comments on commit 16869ef

Please sign in to comment.