1
0
Fork 0
mirror of https://github.com/jnunemaker/httparty synced 2023-03-27 23:23:07 -04:00

Fix RedirectionTooDeep raise before making request

Closes gh-28
This commit is contained in:
Sandro Turriate 2010-01-29 16:57:35 -05:00
parent fc73d77877
commit 9b978214e0
3 changed files with 62 additions and 21 deletions

View file

@ -127,6 +127,29 @@ module HTTParty
end
end
# Declare whether or not to follow redirects. When true, an
# {HTTParty::RedirectionTooDeep} error will raise upon encountering a
# redirect. You can then gain access to the response object via
# HTTParty::RedirectionTooDeep#response.
#
# @see HTTParty::ResponseError#response
#
# @example
# class Foo
# include HTTParty
# base_uri 'http://google.com'
# no_follow true
# end
#
# begin
# Foo.get('/')
# rescue HTTParty::RedirectionTooDeep => e
# puts e.response.body
# end
def no_follow(value = false)
default_options[:no_follow] = value
end
# Allows setting a PEM file to be used
#
# class Foo

View file

@ -13,13 +13,13 @@ module HTTParty
SupportedURISchemes = [URI::HTTP, URI::HTTPS]
attr_accessor :http_method, :path, :options
attr_accessor :http_method, :path, :options, :last_response
def initialize(http_method, path, o={})
self.http_method = http_method
self.path = path
self.options = {
:limit => o.delete(:no_follow) ? 0 : 5,
:limit => o.delete(:no_follow) ? 1 : 5,
:default_params => {},
:parser => Parser
}.merge(o)
@ -56,7 +56,8 @@ module HTTParty
def perform
validate
setup_raw_request
handle_response(get_response)
get_response
handle_response
end
private
@ -113,9 +114,8 @@ module HTTParty
end
def get_response
response = perform_actual_request
options[:format] ||= format_from_mimetype(response['content-type'])
response
self.last_response = perform_actual_request
options[:format] ||= format_from_mimetype(last_response['content-type'])
end
def query_string(uri)
@ -133,26 +133,26 @@ module HTTParty
end
# Raises exception Net::XXX (http error code) if an http error occured
def handle_response(response)
case response
def handle_response
case last_response
when Net::HTTPMultipleChoice, # 300
Net::HTTPMovedPermanently, # 301
Net::HTTPFound, # 302
Net::HTTPSeeOther, # 303
Net::HTTPUseProxy, # 305
Net::HTTPTemporaryRedirect
if response.key?('location')
if last_response.key?('location')
options[:limit] -= 1
self.path = response['location']
self.path = last_response['location']
@redirect = true
self.http_method = Net::HTTP::Get
capture_cookies(response)
capture_cookies(last_response)
perform
else
response
last_response
end
else
Response.new(parse_response(response.body), response.body, response.code, response.message, response.to_hash)
Response.new(parse_response(last_response.body), last_response.body, last_response.code, last_response.message, last_response.to_hash)
end
end
@ -179,7 +179,7 @@ module HTTParty
end
def validate
raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
raise ArgumentError, 'only get, post, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)

View file

@ -304,42 +304,60 @@ describe HTTParty do
end
end
describe "#no_follow" do
it "sets no_follow to false by default" do
@klass.no_follow
@klass.default_options[:no_follow].should be_false
end
it "sets the no_follow option to true" do
@klass.no_follow true
@klass.default_options[:no_follow].should be_true
end
end
describe "with explicit override of automatic redirect handling" do
before do
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml, :no_follow => true)
@redirect = stub_response 'first redirect', 302
@redirect['location'] = 'http://foo.com/bar'
HTTParty::Request.stub(:new => @request)
end
it "should fail with redirected GET" do
lambda do
@klass.get('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
@error = @klass.get('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
it "should fail with redirected POST" do
lambda do
@klass.post('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
it "should fail with redirected DELETE" do
lambda do
@klass.delete('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
it "should fail with redirected PUT" do
lambda do
@klass.put('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
it "should fail with redirected HEAD" do
lambda do
@klass.head('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
it "should fail with redirected OPTIONS" do
lambda do
@klass.options('/foo', :no_follow => true)
end.should raise_error(HTTParty::RedirectionTooDeep)
end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
end
end