user, password and user-defined headers should survive a redirect . Fixes #29

This commit is contained in:
Julien Kirch 2010-05-18 20:00:09 +02:00
parent 77f35b6b7d
commit 1c29e3bc1c
7 changed files with 31 additions and 20 deletions

View File

@ -118,11 +118,11 @@ Response.return! can be called to invoke the default response's behavior.
# RFC : "If the 301 (or 302) status code is received in response to a request other than GET or HEAD,
# the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
# since this might change the conditions under which the request was issued."
RestClient.get('http://my-rest-service.com/resource'){ |response, &block|
RestClient.get('http://my-rest-service.com/resource'){ |response, request, &block|
if [301, 302].include? response.code
response.follow_redirection &block
response.follow_redirection(request) &block
else
response.return! &block
response.return!(request) &block
end
}

View File

@ -1,6 +1,7 @@
# 1.5.2
# 1.6.0
- forgot to include rest-client.rb in the gem
- user, password and user-defined headers should survive a redirect
# 1.5.1

View File

@ -36,19 +36,19 @@ module RestClient
# Return the default behavior corresponding to the response code:
# the response itself for code in 200..206, redirection for 301 and 302 in get and head cases, redirection for 303 and an exception in other cases
def return! &block
def return! request, & block
if (200..206).include? code
self
elsif [301, 302].include? code
unless [:get, :head].include? args[:method]
raise Exceptions::EXCEPTIONS_MAP[code], self
else
follow_redirection(&block)
follow_redirection(request, & block)
end
elsif code == 303
args[:method] = :get
args.delete :payload
follow_redirection(&block)
follow_redirection(request, & block)
elsif Exceptions::EXCEPTIONS_MAP[code]
raise Exceptions::EXCEPTIONS_MAP[code], self
else
@ -65,18 +65,21 @@ module RestClient
end
# Follow a redirection
def follow_redirection &block
def follow_redirection request, & block
url = headers[:location]
if url !~ /^http/
url = URI.parse(args[:url]).merge(url).to_s
end
args[:url] = url
Request.execute args, &block
args[:password] = request.password
args[:user] = request.user
args[:headers] = request.headers
Request.execute args, & block
end
def AbstractResponse.beautify_headers(headers)
headers.inject({}) do |out, (key, value)|
out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
out[key.gsub(/-/, '_').downcase.to_sym] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
out
end
end

View File

@ -188,9 +188,9 @@ module RestClient
end
if block_given?
block.call response, &block
block.call(response, self, &block)
else
response.return!(&block)
response.return!(self, &block)
end
end

View File

@ -276,7 +276,7 @@ describe RestClient::Request do
describe "block usage" do
it "returns what asked to" do
res = mock('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
@request.process_result(res){|response| "foo"}.should == "foo"
@request.process_result(res){|response, request| "foo"}.should == "foo"
end
end

View File

@ -79,20 +79,20 @@ describe RestClient::Resource do
describe 'block' do
it 'can use block when creating the resource' do
stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
resource = RestClient::Resource.new('www.example.com'){|response| 'foo'}
resource = RestClient::Resource.new('www.example.com'){|response, request| 'foo'}
resource.get.should == 'foo'
end
it 'can use block when executing the resource' do
stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
resource = RestClient::Resource.new('www.example.com')
resource.get{|response| 'foo'}.should == 'foo'
resource.get{|response, request| 'foo'}.should == 'foo'
end
it 'execution block override resource block' do
stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
resource = RestClient::Resource.new('www.example.com'){|response| 'foo'}
resource.get{|response| 'bar'}.should == 'bar'
resource = RestClient::Resource.new('www.example.com'){|response, request| 'foo'}
resource.get{|response, request| 'bar'}.should == 'bar'
end
end

View File

@ -6,6 +6,7 @@ include WebMock
describe RestClient::Response do
before do
@net_http_res = mock('net http response', :to_hash => {"Status" => ["200 OK"]}, :code => 200)
@request = mock('http request', :user => nil, :password => nil)
@response = RestClient::Response.create('abc', @net_http_res, {})
end
@ -59,7 +60,7 @@ describe RestClient::Response do
(200..206).each do |code|
net_http_res = mock('net http response', :code => '200')
response = RestClient::Response.create('abc', net_http_res, {})
response.return!
response.return! @request
end
end
@ -83,16 +84,22 @@ describe RestClient::Response do
RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should == 'Foo'
end
it "follows a redirection and keep the parameters" do
stub_request(:get, 'http://foo:bar@some/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
stub_request(:get, 'http://foo:bar@new/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => 'Foo')
RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :user => 'foo', :password => 'bar', :headers => {:accept => :json}).body.should == 'Foo'
end
it "doesn't follow a redirection when the request is a post" do
net_http_res = mock('net http response', :code => 301)
response = RestClient::Response.create('abc', net_http_res, {:method => :post})
lambda { response.return!}.should raise_error(RestClient::MovedPermanently)
lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
end
it "doesn't follow a redirection when the request is a put" do
net_http_res = mock('net http response', :code => 301)
response = RestClient::Response.create('abc', net_http_res, {:method => :put})
lambda { response.return!}.should raise_error(RestClient::MovedPermanently)
lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
end
it "follows a redirection when the request is a post and result is a 303" do