Permalink
Browse files

Keep cookies through a redirection

  • Loading branch information...
1 parent 3d406fb commit de5837289909f671e190388e52631b3b03621210 Micah Cooper committed with mrmicahcooper Apr 27, 2012
Showing with 46 additions and 0 deletions.
  1. +23 −0 lib/faraday_middleware/response/follow_redirects.rb
  2. +23 −0 spec/follow_redirects_spec.rb
@@ -50,6 +50,9 @@ class FollowRedirects < Faraday::Middleware
# standards_compliant - A Boolean indicating whether to respect
# the HTTP spec when following 302
# (default: false)
+ # cookie - Use either an array of strings
+ # (e.g. ['cookie1', 'cookie2']) to choose kept cookies
+ # or :all to keep all cookies.
def initialize(app, options = {})
super(app)
@options = options
@@ -84,6 +87,7 @@ def perform_with_redirection(env, follows)
def update_env(env, request_body, response)
env[:url] += response['location']
+ env[:request_headers][:cookies] = keep_cookies(env) if @options[:cookies]
if transform_into_get?(response)
env[:method] = :get
@@ -106,6 +110,25 @@ def follow_limit
@options.fetch(:limit, FOLLOW_LIMIT)
end
+ def keep_cookies(env)
+ cookies = @options.fetch(:cookies, [])
+ response_cookies = env[:response_headers][:cookies]
+ cookies == :all ? response_cookies : selected_request_cookies(response_cookies)
+ end
+
+ def selected_request_cookies(cookies)
+ selected_cookies(cookies)[0...-1]
+ end
+
+ def selected_cookies(cookies)
+ "".tap do |cookie_string|
+ @options[:cookies].each do |cookie|
+ string = /#{cookie}=?[^;]*/.match(cookies)[0] + ';'
+ cookie_string << string
+ end
+ end
+ end
+
def standards_compliant?
@options.fetch(:standards_compliant, false)
end
@@ -130,6 +130,29 @@
expect { conn.get('/') }.to raise_error(FaradayMiddleware::RedirectLimitReached)
end
+ context 'when cookies option' do
+
+ let(:cookies) { 'cookie1=abcdefg; cookie2=1234567; cookie3=awesome' }
+
+ context "is :all" do
+ it "puts all cookies from the response into the next request"do
+ conn = connection(cookies: :all) do |stub|
+ stub.get('/') { [301, {'Location' => '/found', 'Cookies' => cookies }, ''] }
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, ''] }
+ end.get('/').env[:request_headers][:cookies].should == cookies
+ end
+ end
+
+ context "is an array of cookie names" do
+ it "puts selected cookies from the response into the next request"do
+ conn = connection(cookies: ['cookie2']) do |stub|
+ stub.get('/') { [301, {'Location' => '/found', 'Cookies' => cookies }, ''] }
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, ''] }
+ end.get('/').env[:request_headers][:cookies].should == 'cookie2=1234567'
+ end
+ end
+ end
+
context 'for an HTTP 301 response' do
it_should_behave_like 'a successful redirection', 301
it_should_behave_like 'a forced GET redirection', 301

0 comments on commit de58372

Please sign in to comment.