<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/httparty/request.rb</filename>
    </added>
    <added>
      <filename>spec/httparty/request_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -8,18 +8,23 @@ require 'active_support'
 directory = File.dirname(__FILE__)
 $:.unshift(directory) unless $:.include?(directory) || $:.include?(File.expand_path(directory))
 
+require 'httparty/request'
+
 module HTTParty
   class UnsupportedFormat &lt; StandardError; end
   class RedirectionTooDeep &lt; StandardError; end
+
+  AllowedFormats = {:xml =&gt; 'text/xml', :json =&gt; 'application/json'}
   
   def self.included(base)
     base.extend ClassMethods
   end
   
-  AllowedFormats = {:xml =&gt; 'text/xml', :json =&gt; 'application/json'}
-  SupportedHTTPMethods = [Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete]
-  
   module ClassMethods    
+    def default_options
+      @@default_options ||= {}
+    end
+
     #
     # Set an http proxy
     #
@@ -28,43 +33,42 @@ module HTTParty
     #	  http_proxy http://myProxy, 1080
     # ....
     def http_proxy(addr=nil, port = nil)
-	   @http_proxyaddr = addr
-	   @http_proxyport = port
+      default_options[:http_proxyaddr] = addr
+      default_options[:http_proxyport] = port
     end
 
-    def base_uri(base_uri=nil)
-      return @base_uri unless base_uri
-      @base_uri = normalize_base_uri(base_uri)
+    def base_uri(uri=nil)
+      return default_options[:base_uri] unless uri
+      default_options[:base_uri] = normalize_base_uri(uri)
     end
-    
+
     # Warning: This is not thread safe most likely and
     # only works if you use one set of credentials. I
     # leave it because it is convenient on some occasions.
     def basic_auth(u, p)
-      @auth = {:username =&gt; u, :password =&gt; p}
+      default_options[:basic_auth] = {:username =&gt; u, :password =&gt; p}
     end
     
     # Updates the default query string parameters
     # that should be appended to each request.
     def default_params(h={})
       raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
-      @default_params ||= {}
-      return @default_params if h.blank?
-      @default_params.merge!(h)
+      default_options[:default_params] ||= {}
+      default_options[:default_params].merge!(h)
     end
 
     def headers(h={})
       raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
-      @headers ||= {}
-      return @headers if h.blank?
-      @headers.merge!(h)
+      default_options[:headers] ||= {}
+      default_options[:headers].merge!(h)
     end
     
     def format(f)
       raise UnsupportedFormat, &quot;Must be one of: #{AllowedFormats.keys.join(', ')}&quot; unless AllowedFormats.key?(f)
-      @format = f
+      default_options[:format] = f
     end
     
+    
     # TODO: spec out this
     def get(path, options={})
       send_request Net::HTTP::Get, path, options
@@ -84,72 +88,11 @@ module HTTParty
     def delete(path, options={})
       send_request Net::HTTP::Delete, path, options
     end
-    
+
     private
-      def http(uri) #:nodoc:
-        http = Net::HTTP.new(uri.host, uri.port, @http_proxyaddr, @http_proxyport)
-        http.use_ssl = (uri.port == 443)
-        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
-        http
-      end
-      
-      # FIXME: this method is doing way to much and needs to be split up
-      # options can be any or all of:
-      #   query       =&gt; hash of keys/values or a query string (foo=bar&amp;baz=poo)
-      #   body        =&gt; hash of keys/values or a query string (foo=bar&amp;baz=poo)
-      #   headers     =&gt; hash of headers to send request with
-      #   basic_auth  =&gt; :username and :password to use as basic http authentication (overrides @auth class instance variable)
-      # Raises exception Net::XXX (http error code) if an http error occured
-      def send_request(klass, path, options={}) #:nodoc:
-        options = {:limit =&gt; 5}.merge(options)
-        options[:limit] = 0 if options.delete(:no_follow)
-        
-        raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i &lt;= 0
-        raise ArgumentError, 'only get, post, put and delete methods are supported' unless SupportedHTTPMethods.include?(klass)
-        raise ArgumentError, ':headers must be a hash' if options[:headers] &amp;&amp; !options[:headers].is_a?(Hash)
-        raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] &amp;&amp; !options[:basic_auth].is_a?(Hash)
-        
-        path           = URI.parse(path)
-        uri            = path.relative? ? URI.parse(&quot;#{base_uri}#{path}&quot;) : path
-        existing_query = uri.query ? &quot;#{uri.query}&amp;&quot; : ''
-        uri.query      = if options[:query].blank?
-          existing_query + default_params.to_query
-        else
-          existing_query + (options[:query].is_a?(Hash) ? default_params.merge(options[:query]).to_query : options[:query])
-        end
-        
-        request        = klass.new(uri.request_uri)
-        request.body   = options[:body].is_a?(Hash) ? options[:body].to_query : options[:body] unless options[:body].blank?
-        basic_auth     = options.delete(:basic_auth) || @auth
-        request.initialize_http_header headers.merge(options[:headers] || {})
-        request.basic_auth(basic_auth[:username], basic_auth[:password]) if basic_auth
-        response       = http(uri).request(request)
-        @format      ||= format_from_mimetype(response['content-type'])
-        
-        case response
-        when Net::HTTPSuccess
-          parse_response(response.body)
-        when Net::HTTPRedirection
-          options[:limit] -= 1
-          send_request(klass, response['location'], options)
-        else
-          response.instance_eval { class &lt;&lt; self; attr_accessor :body_parsed; end }
-          begin; response.body_parsed = parse_response(response.body); rescue; end
-          response.error! # raises  exception corresponding to http error Net::XXX
-        end
 
-      end
-      
-      def parse_response(body) #:nodoc:
-        return nil if body.nil? or body.empty?
-        case @format
-        when :xml
-          Hash.from_xml(body)
-        when :json
-          ActiveSupport::JSON.decode(body)
-        else
-          body
-        end
+      def send_request(http_method, path, options)
+        Request.send_request(http_method, path, default_options.merge(options))
       end
     
       # Makes it so uri is sure to parse stuff like google.com with the http
@@ -159,11 +102,5 @@ module HTTParty
         url.gsub!(/^https?:\/\//i, '')
         &quot;http#{'s' if use_ssl}://#{url}&quot;
       end
-      
-      # Uses the HTTP Content-Type header to determine the format of the response
-      # It compares the MIME type returned to the types stored in the AllowedFormats hash
-      def format_from_mimetype(mimetype) #:nodoc:
-        AllowedFormats.each { |k, v| return k if mimetype.include?(v) }
-      end
   end
 end</diff>
      <filename>lib/httparty.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,10 @@ end
 describe HTTParty do
   
   describe &quot;base uri&quot; do
+    before do
+      Foo.base_uri('api.foo.com/v1')
+    end
+
     it &quot;should have reader&quot; do
       Foo.base_uri.should == 'http://api.foo.com/v1'
     end
@@ -65,19 +69,19 @@ describe HTTParty do
   describe &quot;basic http authentication&quot; do
     it &quot;should work&quot; do
       Foo.basic_auth 'foobar', 'secret'
-      Foo.instance_variable_get(&quot;@auth&quot;).should == {:username =&gt; 'foobar', :password =&gt; 'secret'}
+      Foo.default_options[:basic_auth].should == {:username =&gt; 'foobar', :password =&gt; 'secret'}
     end
   end
   
   describe &quot;format&quot; do
     it &quot;should allow xml&quot; do
       Foo.format :xml
-      Foo.instance_variable_get(&quot;@format&quot;).should == :xml
+      Foo.default_options[:format].should == :xml
     end
     
     it &quot;should allow json&quot; do
       Foo.format :json
-      Foo.instance_variable_get(&quot;@format&quot;).should == :json
+      Foo.default_options[:format].should == :json
     end
     
     it 'should not allow funky format' do
@@ -87,30 +91,6 @@ describe HTTParty do
     end
   end
   
-  describe 'http' do
-    it &quot;should use ssl for port 443&quot; do
-      FooWithHttps.send(:http, URI.parse('https://api.foo.com/v1:443')).use_ssl?.should == true
-    end
-    
-    it 'should not use ssl for port 80' do
-      Foo.send(:http, URI.parse('http://foobar.com')).use_ssl?.should == false
-    end
-  end
-  
-  describe 'parsing responses' do
-    it 'should handle xml automatically' do
-      xml = %q[&lt;books&gt;&lt;book&gt;&lt;id&gt;1234&lt;/id&gt;&lt;name&gt;Foo Bar!&lt;/name&gt;&lt;/book&gt;&lt;/books&gt;]
-      Foo.format :xml
-      Foo.send(:parse_response, xml).should == {'books' =&gt; {'book' =&gt; {'id' =&gt; '1234', 'name' =&gt; 'Foo Bar!'}}}
-    end
-    
-    it 'should handle json automatically' do
-      json = %q[{&quot;books&quot;: {&quot;book&quot;: {&quot;name&quot;: &quot;Foo Bar!&quot;, &quot;id&quot;: &quot;1234&quot;}}}]
-      Foo.format :json
-      Foo.send(:parse_response, json).should == {'books' =&gt; {'book' =&gt; {'id' =&gt; '1234', 'name' =&gt; 'Foo Bar!'}}}
-    end
-  end
-  
   describe &quot;sending requests&quot; do
     it &quot;should not work with request method other than get, post, put, delete&quot; do
       lambda do
@@ -126,96 +106,35 @@ describe HTTParty do
     
     it 'should require that :basic_auth is a hash if present' do
       lambda do
-        Foo.send(:send_request, 'get', '/foo', :basic_auth =&gt; 'string')
+        Foo.get('/foo', :basic_auth =&gt; 'string')
       end.should raise_error(ArgumentError)
     end
+  end
 
-    it &quot;should not attempt to parse empty responses&quot; do
-      http = Net::HTTP.new('localhost', 80)
-      Foo.stub!(:http).and_return(http)
-      response = Net::HTTPNoContent.new(&quot;1.1&quot;, 204, &quot;No content for you&quot;)
-      response.stub!(:body).and_return(nil)
-      http.stub!(:request).and_return(response)
-
-      Foo.headers.clear # clear out bogus settings from other specs
-      Foo.format :xml
-      Foo.get('/bar').should be_nil
+  describe &quot;with explicit override of automatic redirect handling&quot; do
 
-      response.stub!(:body).and_return(&quot;&quot;)
-      Foo.get('bar').should be_nil
+    it &quot;should fail with redirected GET&quot; do
+      lambda do
+        Foo.get('/foo', :no_follow =&gt; true)
+      end.should raise_error(HTTParty::RedirectionTooDeep)
     end
 
-    describe &quot;that respond with redirects&quot; do
-      def setup_http
-        @http = Net::HTTP.new('localhost', 80)
-        Foo.stub!(:http).and_return(@http)
-        @redirect = Net::HTTPFound.new(&quot;1.1&quot;, 302, &quot;&quot;)
-        @redirect.stub!(:[]).with('location').and_return('/foo')
-        @ok = Net::HTTPOK.new(&quot;1.1&quot;, 200, &quot;Content for you&quot;)
-        @ok.stub!(:body).and_return({&quot;foo&quot; =&gt; &quot;bar&quot;}.to_xml)
-        @http.should_receive(:request).and_return(@redirect, @ok)
-        Foo.headers.clear
-        Foo.format :xml
-      end
-
-      it &quot;should handle redirects for GET transparently&quot; do
-        setup_http
-        Foo.get('/foo/').should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
-      end
-
-      it &quot;should handle redirects for POST transparently&quot; do
-        setup_http
-        Foo.post('/foo/', {:foo =&gt; :bar}).should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
-      end
-
-      it &quot;should handle redirects for DELETE transparently&quot; do
-        setup_http
-        Foo.delete('/foo/').should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
-      end
-
-      it &quot;should handle redirects for PUT transparently&quot; do
-        setup_http
-        Foo.put('/foo/').should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
-      end
-
-      it &quot;should prevent infinite loops&quot; do
-        http = Net::HTTP.new('localhost', 80)
-        Foo.stub!(:http).and_return(http)
-        redirect = Net::HTTPFound.new(&quot;1.1&quot;, &quot;302&quot;, &quot;Look, over there!&quot;)
-        redirect.stub!(:[]).with('location').and_return('/foo')
-        http.stub!(:request).and_return(redirect)
-
-        lambda do
-          Foo.get('/foo')
-        end.should raise_error(HTTParty::RedirectionTooDeep)
-      end
-
-      describe &quot;with explicit override of automatic redirect handling&quot; do
-
-        it &quot;should fail with redirected GET&quot; do
-          lambda do
-            Foo.get('/foo', :no_follow =&gt; true)
-          end.should raise_error(HTTParty::RedirectionTooDeep)
-        end
-
-        it &quot;should fail with redirected POST&quot; do
-          lambda do
-            Foo.post('/foo', :no_follow =&gt; true)
-          end.should raise_error(HTTParty::RedirectionTooDeep)
-        end
+    it &quot;should fail with redirected POST&quot; do
+      lambda do
+        Foo.post('/foo', :no_follow =&gt; true)
+      end.should raise_error(HTTParty::RedirectionTooDeep)
+    end
 
-        it &quot;should fail with redirected DELETE&quot; do
-          lambda do
-            Foo.delete('/foo', :no_follow =&gt; true)
-          end
-        end
+    it &quot;should fail with redirected DELETE&quot; do
+      lambda do
+        Foo.delete('/foo', :no_follow =&gt; true)
+      end.should raise_error(HTTParty::RedirectionTooDeep)
+    end
 
-        it &quot;should fail with redirected PUT&quot; do
-          lambda do
-            Foo.put('/foo', :no_follow =&gt; true)
-          end
-        end
-      end
+    it &quot;should fail with redirected PUT&quot; do
+      lambda do
+        Foo.put('/foo', :no_follow =&gt; true)
+      end.should raise_error(HTTParty::RedirectionTooDeep)
     end
   end
 end</diff>
      <filename>spec/httparty_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a2fd09256fb5b4558838c32b19f158024d065fb0</id>
    </parent>
  </parents>
  <author>
    <name>Rein Henrichs</name>
    <email>reinh@reinh.com</email>
  </author>
  <url>http://github.com/jnunemaker/httparty/commit/7bdca06bd4d9a41765e83c30da9744521e2eb455</url>
  <id>7bdca06bd4d9a41765e83c30da9744521e2eb455</id>
  <committed-date>2008-11-08T10:59:57-08:00</committed-date>
  <authored-date>2008-11-08T10:59:57-08:00</authored-date>
  <message>Moving send_request and friends into HTTParty::Request</message>
  <tree>ce6c5263dcc2b3143c6604a5339ed824bc539709</tree>
  <committer>
    <name>Rein Henrichs</name>
    <email>reinh@reinh.com</email>
  </committer>
</commit>
