<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>benchmarks/profile.rb</filename>
    </added>
    <added>
      <filename>examples/twitter.rb</filename>
    </added>
    <added>
      <filename>lib/typhoeus/response.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -11,4 +11,7 @@ task :install do
   rm_rf &quot;*.gem&quot;
   puts `gem build typhoeus.gemspec`
   puts `sudo gem install typhoeus-#{Typhoeus::VERSION}.gem`
-end
\ No newline at end of file
+end
+
+desc &quot;Run all the tests&quot;
+task :default =&gt; :spec</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -10,24 +10,26 @@ calls = 20
   include Typhoeus
 end
 
+Typhoeus.init_easy_objects
+
 benchmark do |t|    
-  t.report(&quot;httpmachine&quot;) do
+  t.report(&quot;net::http&quot;) do
     responses = []
     
-    calls.times do
-      responses &lt;&lt; @klass.get(&quot;http://127.0.0.1:3000&quot;)
+    calls.times do |i|
+      responses &lt;&lt; open(&quot;http://127.0.0.1:3000/#{i}&quot;).read
     end
     
-    responses.each {|r| raise unless r.response_body == &quot;whatever&quot;}
+    responses.each {|r| raise unless r == &quot;whatever&quot;}    
   end
-
-  t.report(&quot;net::http&quot;) do
+  
+  t.report(&quot;typhoeus&quot;) do
     responses = []
     
-    calls.times do
-      responses &lt;&lt; open(&quot;http://127.0.0.1:3000&quot;).read
+    calls.times do |i|
+      responses &lt;&lt; @klass.get(&quot;http://127.0.0.1:3000/#{i}&quot;)
     end
     
-    responses.each {|r| raise unless r == &quot;whatever&quot;}    
+    responses.each {|r| raise unless r.body == &quot;whatever&quot;}
   end
 end</diff>
      <filename>benchmarks/vs_nethttp.rb</filename>
    </modified>
    <modified>
      <diff>@@ -76,23 +76,6 @@ static VALUE easy_perform(VALUE self) {
 	return Qnil;
 }
 
-static VALUE easy_reset(VALUE self) {
-	CurlEasy *curl_easy;
-	Data_Get_Struct(self, CurlEasy, curl_easy);
-
-	curl_easy_reset(curl_easy-&gt;curl);
-
-	if (curl_easy-&gt;request_chunk != NULL) {
-		free(curl_easy-&gt;request_chunk);
-	}
-	
-	if (curl_easy-&gt;headers != NULL) {
-		curl_slist_free_all(curl_easy-&gt;headers);
-	}
-
-	return Qnil;	
-}
-
 static size_t write_data_handler(char *stream, size_t size, size_t nmemb, VALUE val) {
 	rb_funcall(val, idAppend, 1, rb_str_new(stream, size * nmemb));
 	return size * nmemb;
@@ -114,6 +97,37 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data) {
 	return realsize; 
 }
 
+static void set_response_handlers(VALUE easy, CURL *curl) {
+	rb_iv_set(easy, &quot;@response_body&quot;, rb_str_new2(&quot;&quot;));
+	rb_iv_set(easy, &quot;@response_header&quot;, rb_str_new2(&quot;&quot;));
+	
+  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&amp;write_data_handler);
+  curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_iv_get(easy, &quot;@response_body&quot;));	
+  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&amp;write_data_handler);
+  curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_iv_get(easy, &quot;@response_header&quot;));
+	
+	return NULL;
+}
+
+static VALUE easy_reset(VALUE self) {
+	CurlEasy *curl_easy;
+	Data_Get_Struct(self, CurlEasy, curl_easy);
+
+	curl_easy_reset(curl_easy-&gt;curl);
+
+	if (curl_easy-&gt;request_chunk != NULL) {
+		free(curl_easy-&gt;request_chunk);
+	}
+	
+	if (curl_easy-&gt;headers != NULL) {
+		curl_slist_free_all(curl_easy-&gt;headers);
+	}
+
+	set_response_handlers(self, curl_easy-&gt;curl);
+
+	return Qnil;	
+}
+
 static VALUE easy_add_header(VALUE self, VALUE header) {
 	CurlEasy *curl_easy;
 	Data_Get_Struct(self, CurlEasy, curl_easy);
@@ -154,6 +168,10 @@ static VALUE easy_escape(VALUE self, VALUE data, VALUE length) {
 	return rb_str_new2(curl_easy_escape(curl_easy-&gt;curl, StringValuePtr(data), NUM2INT(length)));
 }
 
+static VALUE version(VALUE self) {
+	return rb_str_new2(curl_version());
+}
+
 static VALUE new(int argc, VALUE *argv, VALUE klass) {
 	CURL *curl = curl_easy_init();
 	CurlEasy *curl_easy = ALLOC(CurlEasy);
@@ -161,14 +179,8 @@ static VALUE new(int argc, VALUE *argv, VALUE klass) {
 	curl_easy-&gt;headers = NULL;
 	curl_easy-&gt;request_chunk = NULL;
 	VALUE easy = Data_Wrap_Struct(cTyphoeusEasy, 0, dealloc, curl_easy);
-	
-	rb_iv_set(easy, &quot;@response_body&quot;, rb_str_new2(&quot;&quot;));
-	rb_iv_set(easy, &quot;@response_header&quot;, rb_str_new2(&quot;&quot;));
-	
-  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&amp;write_data_handler);
-  curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_iv_get(easy, &quot;@response_body&quot;));	
-  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&amp;write_data_handler);
-  curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_iv_get(easy, &quot;@response_header&quot;));
+
+	set_response_handlers(easy, curl);
 
 	rb_obj_call_init(easy, argc, argv);
 
@@ -190,4 +202,5 @@ void init_typhoeus_easy() {
 	rb_define_private_method(klass, &quot;easy_set_headers&quot;, easy_set_headers, 0);
 	rb_define_private_method(klass, &quot;easy_add_header&quot;, easy_add_header, 1);
 	rb_define_private_method(klass, &quot;easy_escape&quot;, easy_escape, 2);
+	rb_define_private_method(klass, &quot;version&quot;, version, 0);
 }
\ No newline at end of file</diff>
      <filename>ext/typhoeus/typhoeus_easy.c</filename>
    </modified>
    <modified>
      <diff>@@ -9,10 +9,34 @@ require 'typhoeus/filter'
 require 'typhoeus/remote_method'
 require 'typhoeus/remote'
 require 'typhoeus/remote_proxy_object'
+require 'typhoeus/response'
 
 module Typhoeus
   VERSION = &quot;0.0.6&quot;
   
+  def self.easy_object_pool
+    @easy_objects ||= []
+  end
+  
+  def self.init_easy_object_pool
+    20.times do
+      easy_object_pool &lt;&lt; Typhoeus::Easy.new
+    end
+  end
+  
+  def self.release_easy_object(easy)
+    easy.reset
+    easy_object_pool &lt;&lt; easy
+  end
+  
+  def self.get_easy_object
+    if easy_object_pool.empty?
+      Typhoeus::Easy.new
+    else
+      easy_object_pool.pop
+    end
+  end
+  
   def self.add_easy_request(easy_object)
     Thread.current[:curl_multi] ||= Typhoeus::Multi.new
     Thread.current[:curl_multi].add(easy_object)</diff>
      <filename>lib/typhoeus.rb</filename>
    </modified>
    <modified>
      <diff>@@ -171,6 +171,9 @@ module Typhoeus
     end
     
     def reset
+      @response_code = 0
+      @response_header = &quot;&quot;
+      @response_body = &quot;&quot;
       easy_reset()
     end
     
@@ -185,5 +188,9 @@ module Typhoeus
     def get_info_double(option)
       easy_getinfo_double(option)
     end
+    
+    def curl_version
+      version
+    end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/typhoeus/easy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,13 +23,14 @@ module Typhoeus
     end
     
     def remote_proxy_object(url, method, options)
-      easy = Typhoeus::Easy.new
+      easy = Typhoeus.get_easy_object
       
       easy.url                   = url
       easy.method                = method
       easy.headers[&quot;User-Agent&quot;] = (options[:user_agent] || Typhoeus::USER_AGENT)
       easy.params                = options[:params] if options[:params]
       easy.request_body          = options[:body] if options[:body]
+      easy.timeout               = options[:timeout] if options[:timeout]
       
       easy
       </diff>
      <filename>lib/typhoeus/remote.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,13 +21,16 @@ module Typhoeus
         
         unless @proxied_object
           Typhoeus.perform_easy_requests
+          response = Response.new(@easy.response_code, @easy.response_header, @easy.response_body, @easy.total_time_taken)
           if @easy.response_code &gt;= 200 &amp;&amp; @easy.response_code &lt; 300
-            @proxied_object = @success.nil? ? @easy : @success.call(@easy)
+            Typhoeus.release_easy_object(@easy)
+            @proxied_object = @success.nil? ? response : @success.call(response)
+            
             if @cache &amp;&amp; @cache_key
               @cache.set(@cache_key, @proxied_object, @timeout)
             end
           else
-            @proxied_object = @failure.nil? ? @easy : @failure.call(@easy)
+            @proxied_object = @failure.nil? ? response : @failure.call(response)
           end
          @clear_memoized_store_proc.call
        end</diff>
      <filename>lib/typhoeus/remote_proxy_object.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ require 'sinatra'
 get '/**' do
   puts request.inspect
   puts &quot;**#{request.body.read}**&quot;
-  sleep 1
+  sleep 3
   &quot;hello world&quot;
 end
 </diff>
      <filename>spec/servers/app.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@ class DelayFixtureServer  &lt; EventMachine::Connection
  
   def process_http_request
     EventMachine.stop if ENV[&quot;PATH_INFO&quot;] == &quot;/die&quot;
-    puts &quot;got a request&quot;
+    puts &quot;got a request #{ENV['PATH_INFO']}&quot;
     resp = EventMachine::DelegatedHttpResponse.new( self )
     
     # Block which fulfills the request
@@ -56,7 +56,7 @@ end
 
 port = (ARGV[0] || 3000).to_i
 
-DelayFixtureServer.response_delay   = 0.1
+DelayFixtureServer.response_delay   = 0.5
 DelayFixtureServer.response_number = 0
 #DelayFixtureServer.response_fixture = File.read(File.dirname(__FILE__) + &quot;/../fixtures/result_set.xml&quot;)
 </diff>
      <filename>spec/servers/delay_fixture_server.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,6 @@ describe Typhoeus::RemoteProxyObject do
     @easy = Typhoeus::Easy.new
     @easy.method = :get
     @easy.url    = &quot;http://localhost:3001&quot;
-    @klass = Class.new do
-      def self.clear_memoized_proxy_objects
-      end
-    end
   end
       
   before(:all) do
@@ -20,51 +16,52 @@ describe Typhoeus::RemoteProxyObject do
   end
   
   it &quot;should take a caller and call the clear_memoized_proxy_objects&quot; do
-    @klass.should_receive(:clear_memoized_proxy_objects)
-    easy = Typhoeus::RemoteProxyObject.new(@klass, @easy)
-    easy.response_code.should == 200
+    clear_proxy = lambda {}
+    clear_proxy.should_receive(:call)
+    response = Typhoeus::RemoteProxyObject.new(clear_proxy, @easy)
+    response.code.should == 200
   end
 
   it &quot;should take an easy object and return the body when requested&quot; do
-    easy = Typhoeus::RemoteProxyObject.new(@klass, @easy)
+    response = Typhoeus::RemoteProxyObject.new(lambda {}, @easy)
     @easy.response_code.should == 0
-    easy.response_code.should == 200
+    response.code.should == 200
   end
   
   it &quot;should perform requests only on the first access&quot; do
-    easy = Typhoeus::RemoteProxyObject.new(@klass, @easy)
-    easy.response_code.should == 200
+    response = Typhoeus::RemoteProxyObject.new(lambda {}, @easy)
+    response.code.should == 200
     Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
-    easy.response_code.should == 200
+    response.code.should == 200
   end
   
   it &quot;should call the on_success method with an easy object and proxy to the result of on_success&quot; do
     klass = Class.new do
-      def initialize(e)
-        @easy = e
+      def initialize(r)
+        @response = r
       end
       
       def blah
-        @easy.response_code
+        @response.code
       end
     end
     
-    k = Typhoeus::RemoteProxyObject.new(@klass, @easy, :on_success =&gt; lambda {|e| klass.new(e)})
+    k = Typhoeus::RemoteProxyObject.new(lambda {}, @easy, :on_success =&gt; lambda {|e| klass.new(e)})
     k.blah.should == 200
   end
   
   it &quot;should call the on_failure method with an easy object and proxy to the result of on_failure&quot; do
     klass = Class.new do
-      def initialize(e)
-        @easy = e
+      def initialize(r)
+        @response = r
       end
       
       def blah
-        @easy.response_code
+        @response.code
       end
     end
     @easy.url = &quot;http://localhost:3002&quot; #bad port
-    k = Typhoeus::RemoteProxyObject.new(@klass, @easy, :on_failure =&gt; lambda {|e| klass.new(e)})
+    k = Typhoeus::RemoteProxyObject.new(lambda {}, @easy, :on_failure =&gt; lambda {|e| klass.new(e)})
     k.blah.should == 0
   end
 end
\ No newline at end of file</diff>
      <filename>spec/typhoeus/remote_proxy_object_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,45 +18,45 @@ describe Typhoeus do
   describe &quot;get&quot; do
     it &quot;should add a get method&quot; do
       easy = @klass.get(&quot;http://localhost:3001/posts.xml&quot;)
-      easy.response_code.should == 200
-      easy.response_body.should include(&quot;REQUEST_METHOD=GET&quot;)
-      easy.response_body.should include(&quot;REQUEST_URI=/posts.xml&quot;)
+      easy.code.should == 200
+      easy.body.should include(&quot;REQUEST_METHOD=GET&quot;)
+      easy.body.should include(&quot;REQUEST_URI=/posts.xml&quot;)
     end
 
     it &quot;should take passed in params and add them to the query string&quot; do
       easy = @klass.get(&quot;http://localhost:3001&quot;, {:params =&gt; {:foo =&gt; :bar}})
-      easy.response_body.should include(&quot;QUERY_STRING=foo=bar&quot;)
+      easy.body.should include(&quot;QUERY_STRING=foo=bar&quot;)
     end
   end # get
   
   describe &quot;post&quot; do
     it &quot;should add a post method&quot; do
       easy = @klass.post(&quot;http://localhost:3001/posts.xml&quot;, {:params =&gt; {:post =&gt; {:author =&gt; &quot;paul&quot;, :title =&gt; &quot;a title&quot;, :body =&gt; &quot;a body&quot;}}})
-      easy.response_code.should == 200
-      easy.response_body.should include(&quot;post%5Bbody%5D=a+body&quot;)
-      easy.response_body.should include(&quot;post%5Bauthor%5D=paul&quot;)
-      easy.response_body.should include(&quot;post%5Btitle%5D=a+title&quot;)
-      easy.response_body.should include(&quot;REQUEST_METHOD=POST&quot;)
+      easy.code.should == 200
+      easy.body.should include(&quot;post%5Bbody%5D=a+body&quot;)
+      easy.body.should include(&quot;post%5Bauthor%5D=paul&quot;)
+      easy.body.should include(&quot;post%5Btitle%5D=a+title&quot;)
+      easy.body.should include(&quot;REQUEST_METHOD=POST&quot;)
     end
 
     it &quot;should add a body&quot; do
       easy = @klass.post(&quot;http://localhost:3001/posts.xml&quot;, {:body =&gt; &quot;this is a request body&quot;})
-      easy.response_code.should == 200
-      easy.response_body.should include(&quot;this is a request body&quot;)
-      easy.response_body.should include(&quot;REQUEST_METHOD=POST&quot;)
+      easy.code.should == 200
+      easy.body.should include(&quot;this is a request body&quot;)
+      easy.body.should include(&quot;REQUEST_METHOD=POST&quot;)
     end
   end # post
   
   it &quot;should add a put method&quot; do
     easy = @klass.put(&quot;http://localhost:3001/posts/3.xml&quot;)
-    easy.response_code.should == 200
-    easy.response_body.should include(&quot;REQUEST_METHOD=PUT&quot;)
+    easy.code.should == 200
+    easy.body.should include(&quot;REQUEST_METHOD=PUT&quot;)
   end
   
   it &quot;should add a delete method&quot; do
     easy = @klass.delete(&quot;http://localhost:3001/posts/3.xml&quot;)
-    easy.response_code.should == 200
-    easy.response_body.should include(&quot;REQUEST_METHOD=DELETE&quot;)
+    easy.code.should == 200
+    easy.body.should include(&quot;REQUEST_METHOD=DELETE&quot;)
   end
   
   describe &quot;#define_remote_method&quot; do
@@ -211,7 +211,7 @@ describe Typhoeus do
     describe &quot;on_success&quot; do
       it &quot;should take :on_success as an argument&quot; do
         @klass.instance_eval do
-          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :on_success =&gt; lambda {|e| e.response_code.should == 200; :foo}
+          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :on_success =&gt; lambda {|e| e.code.should == 200; :foo}
         end
         
         @klass.do_stuff.should == :foo
@@ -219,7 +219,7 @@ describe Typhoeus do
       
       it &quot;should use default_on_success if no on_success provided&quot; do
         @klass.instance_eval do
-          remote_defaults :on_success =&gt; lambda {|e| e.response_code.should == 200; :foo}
+          remote_defaults :on_success =&gt; lambda {|e| e.code.should == 200; :foo}
           define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;
         end
         
@@ -229,7 +229,7 @@ describe Typhoeus do
       it &quot;should override default_on_success if on_success is provided&quot; do
         @klass.instance_eval do
           remote_defaults :on_success =&gt; lambda {|e| :foo}
-          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :on_success =&gt; lambda {|e| e.response_code.should == 200; :bar}
+          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :on_success =&gt; lambda {|e| e.code.should == 200; :bar}
         end
         
         @klass.do_stuff.should == :bar
@@ -239,7 +239,7 @@ describe Typhoeus do
     describe &quot;on_failure&quot; do
       it &quot;should take :on_failure as an argument&quot; do
         @klass.instance_eval do
-          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:9999&quot;, :on_failure =&gt; lambda {|e| e.response_code.should == 0; :foo}
+          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:9999&quot;, :on_failure =&gt; lambda {|e| e.code.should == 0; :foo}
         end
         
         @klass.do_stuff.should == :foo
@@ -247,7 +247,7 @@ describe Typhoeus do
       
       it &quot;should use default_on_failure if no on_success provided&quot; do
         @klass.instance_eval do
-          remote_defaults :on_failure =&gt; lambda {|e| e.response_code.should == 0; :bar}
+          remote_defaults :on_failure =&gt; lambda {|e| e.code.should == 0; :bar}
           define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:9999&quot;
         end
         
@@ -257,7 +257,7 @@ describe Typhoeus do
       it &quot;should override default_on_failure if no method is provided&quot; do
         @klass.instance_eval do
           remote_defaults :on_failure =&gt; lambda {|e| :foo}
-          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:9999&quot;, :on_failure =&gt; lambda {|e| e.response_code.should == 0; :bar}
+          define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:9999&quot;, :on_failure =&gt; lambda {|e| e.code.should == 0; :bar}
         end
         
         @klass.do_stuff.should == :bar
@@ -270,7 +270,7 @@ describe Typhoeus do
           define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :params =&gt; {:foo =&gt; :bar}
         end
 
-        @klass.do_stuff.response_body.should include(&quot;QUERY_STRING=foo=bar&quot;)
+        @klass.do_stuff.body.should include(&quot;QUERY_STRING=foo=bar&quot;)
       end
       
       it &quot;should add :params from remote method definition with params passed in when called&quot; do
@@ -278,7 +278,7 @@ describe Typhoeus do
           define_remote_method :do_stuff, :base_uri =&gt; &quot;http://localhost:3001&quot;, :params =&gt; {:foo =&gt; :bar}
         end
 
-        @klass.do_stuff(:params =&gt; {:asdf =&gt; :jkl}).response_body.should include(&quot;QUERY_STRING=asdf=jkl&amp;foo=bar&quot;)
+        @klass.do_stuff(:params =&gt; {:asdf =&gt; :jkl}).body.should include(&quot;QUERY_STRING=foo=bar&amp;asdf=jkl&quot;)
       end
     end
     </diff>
      <filename>spec/typhoeus/remote_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>spec/typhoeus/http_machine_spec.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>60a23f380e949a099b3a03a54505d598c0579668</id>
    </parent>
  </parents>
  <author>
    <name>Paul Dix</name>
    <email>paul@pauldix.net</email>
  </author>
  <url>http://github.com/pauldix/typhoeus/commit/1a60706ae912fba95958608fd684d046dc77dd51</url>
  <id>1a60706ae912fba95958608fd684d046dc77dd51</id>
  <committed-date>2009-05-07T09:36:10-07:00</committed-date>
  <authored-date>2009-05-07T09:36:10-07:00</authored-date>
  <message>sweet zombie jesus, this is a huge commit. Got too caught up hacking new ideas while at the conf. Main change is the addition of a response object and the easy object pool</message>
  <tree>37eed6c0ab284943ec8b7a7e04238bde788fde8e</tree>
  <committer>
    <name>Paul Dix</name>
    <email>paul@pauldix.net</email>
  </committer>
</commit>
