public
Rubygem
Description: Makes http fun! Also, makes consuming restful web services dead easy.
Homepage:
Clone URL: git://github.com/jnunemaker/httparty.git
Click here to lend your support to: httparty and make a donation at www.pledgie.com !
Add the ability to automatically follow redirects and to turn it off.
evri (author)
Fri Sep 19 16:31:06 -0700 2008
jnunemaker (committer)
Fri Oct 24 21:34:33 -0700 2008
commit  ae7ce3097731a034e7b9ddae2b30d3916efa3a5c
tree    6c16d50dad43cc43ad8538a352da5b0bf2682f29
parent  f90c40914a3dec04face3a160eb5bdb6b2226ad6
...
10
11
12
13
 
14
15
 
 
16
17
18
...
107
108
109
 
 
 
110
111
112
...
130
131
132
 
 
 
133
134
135
...
10
11
12
 
13
14
15
16
17
18
19
20
...
109
110
111
112
113
114
115
116
117
...
135
136
137
138
139
140
141
142
143
0
@@ -10,9 +10,11 @@ $:.unshift(File.dirname(__FILE__)) unless
0
 
0
 dir = File.expand_path(File.join(File.dirname(__FILE__), 'httparty'))
0
 require dir + '/core_ext'
0
-  
0
+
0
 module HTTParty
0
   class UnsupportedFormat < StandardError; end
0
+
0
+  class RedirectionTooDeep < StandardError; end
0
   
0
   def self.included(base)
0
     base.extend ClassMethods
0
@@ -107,6 +109,9 @@ module HTTParty
0
       #   basic_auth  => :username and :password to use as basic http authentication (overrides @auth class instance variable)
0
       # Raises exception Net::XXX (http error code) if an http error occured
0
       def send_request(method, path, options={}) #:nodoc:
0
+        options = {:limit => 5}.merge(options)
0
+        options[:limit] = 0 if options.delete(:no_follow)
0
+        raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
0
         raise ArgumentError, 'only get, post, put and delete methods are supported' unless %w[get post put delete].include?(method.to_s)
0
         raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
0
         raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
0
@@ -130,6 +135,9 @@ module HTTParty
0
         case response
0
         when Net::HTTPSuccess
0
           parse_response(response.body)
0
+        when Net::HTTPRedirection
0
+          options[:limit] -= 1
0
+          send_request(method, response['location'], options)
0
         else
0
           response.instance_eval { class << self; attr_accessor :body_parsed; end }
0
           begin; response.body_parsed = parse_response(response.body); rescue; end
...
138
139
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
142
143
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
0
@@ -138,5 +138,78 @@ describe HTTParty do
0
       response.stub!(:body).and_return("")
0
       Foo.send(:send_request, 'get', 'bar').should be_nil
0
     end
0
+
0
+    describe "that respond with redirects" do
0
+      def setup_http
0
+        @http = Net::HTTP.new('localhost', 80)
0
+        Foo.stub!(:http).and_return(@http)
0
+        @redirect = Net::HTTPFound.new("1.1", 302, "")
0
+        @redirect.stub!(:[]).with('location').and_return('/foo')
0
+        @ok = Net::HTTPOK.new("1.1", 200, "Content for you")
0
+        @ok.stub!(:body).and_return({"foo" => "bar"}.to_xml)
0
+        @http.should_receive(:request).and_return(@redirect, @ok)
0
+        Foo.headers.clear
0
+        Foo.format :xml
0
+      end
0
+
0
+      it "should handle redirects for GET transparently" do
0
+        setup_http
0
+        Foo.get('/foo/').should == {"hash" => {"foo" => "bar"}}
0
+      end
0
+
0
+      it "should handle redirects for POST transparently" do
0
+        setup_http
0
+        Foo.post('/foo/', {:foo => :bar}).should == {"hash" => {"foo" => "bar"}}
0
+      end
0
+
0
+      it "should handle redirects for DELETE transparently" do
0
+        setup_http
0
+        Foo.delete('/foo/').should == {"hash" => {"foo" => "bar"}}
0
+      end
0
+
0
+      it "should handle redirects for PUT transparently" do
0
+        setup_http
0
+        Foo.put('/foo/').should == {"hash" => {"foo" => "bar"}}
0
+      end
0
+
0
+      it "should prevent infinite loops" do
0
+        http = Net::HTTP.new('localhost', 80)
0
+        Foo.stub!(:http).and_return(http)
0
+        redirect = Net::HTTPFound.new("1.1", "302", "Look, over there!")
0
+        redirect.stub!(:[]).with('location').and_return('/foo')
0
+        http.stub!(:request).and_return(redirect)
0
+
0
+        lambda do
0
+          Foo.send(:send_request, 'get', '/foo')
0
+        end.should raise_error(HTTParty::RedirectionTooDeep)
0
+      end
0
+
0
+      describe "with explicit override of automatic redirect handling" do
0
+
0
+        it "should fail with redirected GET" do
0
+          lambda do
0
+            Foo.get('/foo', :no_follow => true)
0
+          end.should raise_error(HTTParty::RedirectionTooDeep)
0
+        end
0
+
0
+        it "should fail with redirected POST" do
0
+          lambda do
0
+            Foo.post('/foo', :no_follow => true)
0
+          end.should raise_error(HTTParty::RedirectionTooDeep)
0
+        end
0
+
0
+        it "should fail with redirected DELETE" do
0
+          lambda do
0
+            Foo.delete('/foo', :no_follow => true)
0
+          end
0
+        end
0
+
0
+        it "should fail with redirected PUT" do
0
+          lambda do
0
+            Foo.put('/foo', :no_follow => true)
0
+          end
0
+        end
0
+      end
0
+    end
0
   end
0
 end
0
\ No newline at end of file

Comments