<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>VERSION</filename>
    </added>
    <added>
      <filename>features/supports_timeout_option.feature</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -6,7 +6,7 @@ Makes http fun again!
 
 Releases are tagged on github and also released as gems on github and rubyforge. Master is pushed to whenever I add a patch or a new feature. To build from master, you can clone the code, generate the updated gemspec, build the gem and install.
 
-* rake build_gemspec
+* rake gemspec
 * gem build httparty.gemspec
 * gem install the gem that was built
 </diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -1,48 +1,70 @@
-ProjectName = 'httparty'
-WebsitePath = &quot;jnunemaker@rubyforge.org:/var/www/gforge-projects/#{ProjectName}&quot;
-
-require 'rubygems'
-require 'rake'
-require 'echoe'
-require 'spec/rake/spectask'
-require &quot;lib/#{ProjectName}/version&quot;
-require 'cucumber/rake/task'
-
-Echoe.new(ProjectName, HTTParty::Version) do |p|
-  p.description     = &quot;Makes http fun! Also, makes consuming restful web services dead easy.&quot;
-  p.install_message = &quot;When you HTTParty, you must party hard!&quot;
-  p.url             = &quot;http://#{ProjectName}.rubyforge.org&quot;
-  p.author          = &quot;John Nunemaker&quot;
-  p.email           = &quot;nunemaker@gmail.com&quot;
-  p.extra_deps      = [['crack', '&gt;= 0.1.1']]
-  p.need_tar_gz     = false
-  p.docs_host       = WebsitePath
-end
-
-desc 'Upload website files to rubyforge'
-task :website do
-  sh %{rsync -av website/ #{WebsitePath}}
-  Rake::Task['website_docs'].invoke
-end
-
-task :website_docs do
-  Rake::Task['redocs'].invoke
-  sh %{rsync -av doc/ #{WebsitePath}/docs}
-end
-
-desc 'Preps the gem for a new release'
-task :prepare do
-  %w[manifest build_gemspec].each do |task|
-    Rake::Task[task].invoke
-  end
-end
-
-Rake::Task[:default].prerequisites.clear
-task :default =&gt; :spec
-Spec::Rake::SpecTask.new do |t|
-  t.spec_files = FileList[&quot;spec/**/*_spec.rb&quot;]
-end
-
-Cucumber::Rake::Task.new(:features) do |t|
-  t.cucumber_opts = &quot;--format pretty&quot; 
-end
+require 'rubygems'
+require 'rake'
+
+begin
+  require 'jeweler'
+  Jeweler::Tasks.new do |gem|
+  gem.name = &quot;httparty&quot;
+  gem.summary = %Q{Makes http fun! Also, makes consuming restful web services dead easy.}
+  gem.description = %Q{Makes http fun! Also, makes consuming restful web services dead easy.}
+  gem.email = &quot;nunemaker@gmail.com&quot;
+  gem.homepage = &quot;http://httparty.rubyforge.org&quot;
+  gem.authors = [&quot;John Nunemaker&quot;]
+  gem.add_dependency 'crack', '&gt;= 0.1.1'
+  gem.add_development_dependency &quot;rspec&quot;, &quot;1.2.8&quot;
+  gem.post_install_message = &quot;When you HTTParty, you must party hard!&quot;
+  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+  end
+  Jeweler::RubyforgeTasks.new do |rubyforge|
+  rubyforge.doc_task = &quot;rdoc&quot;
+  end
+rescue LoadError
+  puts &quot;Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler&quot;
+end
+
+require 'spec/rake/spectask'
+Spec::Rake::SpecTask.new(:spec) do |spec|
+spec.libs &lt;&lt; 'lib' &lt;&lt; 'spec'
+spec.spec_files = FileList['spec/**/*_spec.rb']
+spec.spec_opts = ['--options', 'spec/spec.opts']
+end
+
+Spec::Rake::SpecTask.new(:rcov) do |spec|
+spec.libs &lt;&lt; 'lib' &lt;&lt; 'spec'
+spec.pattern = 'spec/**/*_spec.rb'
+spec.rcov = true
+end
+
+task :spec =&gt; :check_dependencies
+
+begin
+  require 'cucumber/rake/task'
+  Cucumber::Rake::Task.new(:features)
+  
+  task :features =&gt; :check_dependencies
+rescue LoadError
+  task :features do
+  abort &quot;Cucumber is not available. In order to run features, you must: sudo gem install cucumber&quot;
+  end
+end
+
+task :default =&gt; [:spec, :features]
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+if File.exist?('VERSION')
+  version = File.read('VERSION')
+else
+  version = &quot;&quot;
+end
+
+rdoc.rdoc_dir = 'rdoc'
+rdoc.title = &quot;httparty #{version}&quot;
+rdoc.rdoc_files.include('README*')
+rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+desc 'Upload website files to rubyforge'
+task :website do
+sh %{rsync -av website/ jnunemaker@rubyforge.org:/var/www/gforge-projects/httparty}
+end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -37,7 +37,7 @@ OptionParser.new do |o|
        &quot;--data [BODY]&quot;,
        &quot;Data to put in request body (prefix with '@' for file)&quot;) do |d|
     if d =~ /^@/
-      opts[:data] = open(d).read
+      opts[:data] = open(d[1..-1]).read
     else
       opts[:data] = d
     end</diff>
      <filename>bin/httparty</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@ Before do
   @host_and_port = &quot;0.0.0.0:#{port}&quot;
   @server = Mongrel::HttpServer.new(&quot;0.0.0.0&quot;, port)
   @server.run
+  @request_options = {}
 end
 
 After do</diff>
      <filename>features/steps/env.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ Then /it should return a response with a (\d+) response code/ do |code|
   @response_from_httparty.code.should eql(code.to_i)
 end
 
-Then /it should raise an HTTParty::RedirectionTooDeep exception/ do
+Then /it should raise (?:an|a) ([\w:]+) exception/ do |exception|
   @exception_from_httparty.should_not be_nil
-  @exception_from_httparty.class.should eql(HTTParty::RedirectionTooDeep)
+  @exception_from_httparty.class.name.should eql(exception)
 end</diff>
      <filename>features/steps/httparty_response_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,11 @@
+When /^I set my HTTParty timeout option to (\d+)$/ do |timeout|
+  @request_options[:timeout] = timeout.to_i
+end
+
 When /I call HTTParty#get with '(.*)'$/ do |url|
   begin
-    @response_from_httparty = HTTParty.get(&quot;http://#{@host_and_port}#{url}&quot;)
-  rescue HTTParty::RedirectionTooDeep =&gt; e
+    @response_from_httparty = HTTParty.get(&quot;http://#{@host_and_port}#{url}&quot;, @request_options)
+  rescue HTTParty::RedirectionTooDeep, Timeout::Error =&gt; e
     @exception_from_httparty = e
   end
 end</diff>
      <filename>features/steps/httparty_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 def basic_mongrel_handler
   Class.new(Mongrel::HttpHandler) do
-    attr_writer :content_type, :response_body, :response_code
+    attr_writer :content_type, :response_body, :response_code, :preprocessor
 
     def initialize
       @content_type = &quot;text/html&quot;
@@ -10,6 +10,7 @@ def basic_mongrel_handler
     end
 
     def process(request, response)
+      instance_eval &amp;@preprocessor if @preprocessor
       reply_with(response, @response_code, @response_body)
     end
 </diff>
      <filename>features/steps/mongrel_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,6 +12,11 @@ Given /that service is accessed at the path '(.*)'/ do |path|
   @server.register(path, @handler)
 end
 
+Given /^that service takes (\d+) seconds to generate a response$/ do |time|
+  preprocessor = lambda { sleep time.to_i }
+  @handler.preprocessor = preprocessor
+end
+
 Given /the response from the service has a Content-Type of '(.*)'/ do |content_type|
   @handler.content_type = content_type
 end</diff>
      <filename>features/steps/remote_service_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,26 +1,95 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE
+# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
 # -*- encoding: utf-8 -*-
 
 Gem::Specification.new do |s|
   s.name = %q{httparty}
-  s.version = &quot;0.4.4&quot;
+  s.version = &quot;0.4.5&quot;
 
-  s.required_rubygems_version = Gem::Requirement.new(&quot;&gt;= 1.2&quot;) if s.respond_to? :required_rubygems_version=
+  s.required_rubygems_version = Gem::Requirement.new(&quot;&gt;= 0&quot;) if s.respond_to? :required_rubygems_version=
   s.authors = [&quot;John Nunemaker&quot;]
-  s.date = %q{2009-07-19}
+  s.date = %q{2009-09-12}
   s.default_executable = %q{httparty}
   s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
   s.email = %q{nunemaker@gmail.com}
   s.executables = [&quot;httparty&quot;]
-  s.extra_rdoc_files = [&quot;bin/httparty&quot;, &quot;lib/httparty/cookie_hash.rb&quot;, &quot;lib/httparty/core_extensions.rb&quot;, &quot;lib/httparty/exceptions.rb&quot;, &quot;lib/httparty/module_inheritable_attributes.rb&quot;, &quot;lib/httparty/request.rb&quot;, &quot;lib/httparty/response.rb&quot;, &quot;lib/httparty/version.rb&quot;, &quot;lib/httparty.rb&quot;, &quot;README.rdoc&quot;]
-  s.files = [&quot;bin/httparty&quot;, &quot;cucumber.yml&quot;, &quot;examples/aaws.rb&quot;, &quot;examples/basic.rb&quot;, &quot;examples/delicious.rb&quot;, &quot;examples/google.rb&quot;, &quot;examples/rubyurl.rb&quot;, &quot;examples/twitter.rb&quot;, &quot;examples/whoismyrep.rb&quot;, &quot;features/basic_authentication.feature&quot;, &quot;features/command_line.feature&quot;, &quot;features/deals_with_http_error_codes.feature&quot;, &quot;features/handles_multiple_formats.feature&quot;, &quot;features/steps/env.rb&quot;, &quot;features/steps/httparty_response_steps.rb&quot;, &quot;features/steps/httparty_steps.rb&quot;, &quot;features/steps/mongrel_helper.rb&quot;, &quot;features/steps/remote_service_steps.rb&quot;, &quot;features/supports_redirection.feature&quot;, &quot;History&quot;, &quot;httparty.gemspec&quot;, &quot;lib/httparty/cookie_hash.rb&quot;, &quot;lib/httparty/core_extensions.rb&quot;, &quot;lib/httparty/exceptions.rb&quot;, &quot;lib/httparty/module_inheritable_attributes.rb&quot;, &quot;lib/httparty/request.rb&quot;, &quot;lib/httparty/response.rb&quot;, &quot;lib/httparty/version.rb&quot;, &quot;lib/httparty.rb&quot;, &quot;Manifest&quot;, &quot;MIT-LICENSE&quot;, &quot;Rakefile&quot;, &quot;README.rdoc&quot;, &quot;spec/fixtures/delicious.xml&quot;, &quot;spec/fixtures/empty.xml&quot;, &quot;spec/fixtures/google.html&quot;, &quot;spec/fixtures/twitter.json&quot;, &quot;spec/fixtures/twitter.xml&quot;, &quot;spec/fixtures/undefined_method_add_node_for_nil.xml&quot;, &quot;spec/httparty/cookie_hash_spec.rb&quot;, &quot;spec/httparty/request_spec.rb&quot;, &quot;spec/httparty/response_spec.rb&quot;, &quot;spec/httparty_spec.rb&quot;, &quot;spec/spec.opts&quot;, &quot;spec/spec_helper.rb&quot;, &quot;website/css/common.css&quot;, &quot;website/index.html&quot;]
+  s.extra_rdoc_files = [
+    &quot;README.rdoc&quot;
+  ]
+  s.files = [
+    &quot;.gitignore&quot;,
+     &quot;History&quot;,
+     &quot;MIT-LICENSE&quot;,
+     &quot;Manifest&quot;,
+     &quot;README.rdoc&quot;,
+     &quot;Rakefile&quot;,
+     &quot;VERSION&quot;,
+     &quot;bin/httparty&quot;,
+     &quot;cucumber.yml&quot;,
+     &quot;examples/aaws.rb&quot;,
+     &quot;examples/basic.rb&quot;,
+     &quot;examples/delicious.rb&quot;,
+     &quot;examples/google.rb&quot;,
+     &quot;examples/rubyurl.rb&quot;,
+     &quot;examples/twitter.rb&quot;,
+     &quot;examples/whoismyrep.rb&quot;,
+     &quot;features/basic_authentication.feature&quot;,
+     &quot;features/command_line.feature&quot;,
+     &quot;features/deals_with_http_error_codes.feature&quot;,
+     &quot;features/handles_multiple_formats.feature&quot;,
+     &quot;features/steps/env.rb&quot;,
+     &quot;features/steps/httparty_response_steps.rb&quot;,
+     &quot;features/steps/httparty_steps.rb&quot;,
+     &quot;features/steps/mongrel_helper.rb&quot;,
+     &quot;features/steps/remote_service_steps.rb&quot;,
+     &quot;features/supports_redirection.feature&quot;,
+     &quot;features/supports_timeout_option.feature&quot;,
+     &quot;httparty.gemspec&quot;,
+     &quot;lib/httparty.rb&quot;,
+     &quot;lib/httparty/cookie_hash.rb&quot;,
+     &quot;lib/httparty/core_extensions.rb&quot;,
+     &quot;lib/httparty/exceptions.rb&quot;,
+     &quot;lib/httparty/module_inheritable_attributes.rb&quot;,
+     &quot;lib/httparty/request.rb&quot;,
+     &quot;lib/httparty/response.rb&quot;,
+     &quot;lib/httparty/version.rb&quot;,
+     &quot;spec/fixtures/delicious.xml&quot;,
+     &quot;spec/fixtures/empty.xml&quot;,
+     &quot;spec/fixtures/google.html&quot;,
+     &quot;spec/fixtures/twitter.json&quot;,
+     &quot;spec/fixtures/twitter.xml&quot;,
+     &quot;spec/fixtures/undefined_method_add_node_for_nil.xml&quot;,
+     &quot;spec/httparty/cookie_hash_spec.rb&quot;,
+     &quot;spec/httparty/request_spec.rb&quot;,
+     &quot;spec/httparty/response_spec.rb&quot;,
+     &quot;spec/httparty_spec.rb&quot;,
+     &quot;spec/spec.opts&quot;,
+     &quot;spec/spec_helper.rb&quot;,
+     &quot;website/css/common.css&quot;,
+     &quot;website/index.html&quot;
+  ]
   s.has_rdoc = true
   s.homepage = %q{http://httparty.rubyforge.org}
   s.post_install_message = %q{When you HTTParty, you must party hard!}
-  s.rdoc_options = [&quot;--line-numbers&quot;, &quot;--inline-source&quot;, &quot;--title&quot;, &quot;Httparty&quot;, &quot;--main&quot;, &quot;README.rdoc&quot;]
+  s.rdoc_options = [&quot;--charset=UTF-8&quot;]
   s.require_paths = [&quot;lib&quot;]
-  s.rubyforge_project = %q{httparty}
   s.rubygems_version = %q{1.3.1}
   s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
+  s.test_files = [
+    &quot;spec/httparty/cookie_hash_spec.rb&quot;,
+     &quot;spec/httparty/request_spec.rb&quot;,
+     &quot;spec/httparty/response_spec.rb&quot;,
+     &quot;spec/httparty_spec.rb&quot;,
+     &quot;spec/spec_helper.rb&quot;,
+     &quot;examples/aaws.rb&quot;,
+     &quot;examples/basic.rb&quot;,
+     &quot;examples/delicious.rb&quot;,
+     &quot;examples/google.rb&quot;,
+     &quot;examples/rubyurl.rb&quot;,
+     &quot;examples/twitter.rb&quot;,
+     &quot;examples/whoismyrep.rb&quot;
+  ]
 
   if s.respond_to? :specification_version then
     current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -28,13 +97,13 @@ Gem::Specification.new do |s|
 
     if Gem::Version.new(Gem::RubyGemsVersion) &gt;= Gem::Version.new('1.2.0') then
       s.add_runtime_dependency(%q&lt;crack&gt;, [&quot;&gt;= 0.1.1&quot;])
-      s.add_development_dependency(%q&lt;echoe&gt;, [&quot;&gt;= 0&quot;])
+      s.add_development_dependency(%q&lt;rspec&gt;, [&quot;= 1.2.8&quot;])
     else
       s.add_dependency(%q&lt;crack&gt;, [&quot;&gt;= 0.1.1&quot;])
-      s.add_dependency(%q&lt;echoe&gt;, [&quot;&gt;= 0&quot;])
+      s.add_dependency(%q&lt;rspec&gt;, [&quot;= 1.2.8&quot;])
     end
   else
     s.add_dependency(%q&lt;crack&gt;, [&quot;&gt;= 0.1.1&quot;])
-    s.add_dependency(%q&lt;echoe&gt;, [&quot;&gt;= 0&quot;])
+    s.add_dependency(%q&lt;rspec&gt;, [&quot;= 1.2.8&quot;])
   end
 end</diff>
      <filename>httparty.gemspec</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,14 @@
-$:.unshift(File.dirname(__FILE__))
-
+require 'pathname'
 require 'net/http'
 require 'net/https'
-require 'httparty/module_inheritable_attributes'
 require 'rubygems'
-gem 'crack'
+gem 'crack', '&gt;= 0.1.1'
 require 'crack'
 
-require 'httparty/cookie_hash'
+dir = Pathname(__FILE__).dirname.expand_path
+
+require dir + 'httparty/module_inheritable_attributes'
+require dir + 'httparty/cookie_hash'
 
 module HTTParty
   
@@ -160,11 +161,9 @@ module HTTParty
       end
 
       def process_cookies(options) #:nodoc:
-        return unless options[:cookies] || default_cookies
-        options[:headers] ||= {}
-        options[:headers][&quot;cookie&quot;] = cookies.merge(options[:cookies] || {}).to_cookie_string
-
-        options.delete(:cookies)
+        return unless options[:cookies] || default_cookies.any?
+        options[:headers] ||= headers.dup
+        options[:headers][&quot;cookie&quot;] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
       end
   end
 
@@ -200,7 +199,7 @@ module HTTParty
   end
 end
 
-require 'httparty/core_extensions'
-require 'httparty/exceptions'
-require 'httparty/request'
-require 'httparty/response'
+require dir + 'httparty/core_extensions'
+require dir + 'httparty/exceptions'
+require dir + 'httparty/request'
+require dir + 'httparty/response'</diff>
      <filename>lib/httparty.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,22 @@
 class HTTParty::CookieHash &lt; Hash #:nodoc:
-  def add_cookies(hash)
-    merge!(hash)
+  
+  CLIENT_COOKIES = %w{path expires domain path secure HTTPOnly}
+  
+  def add_cookies(value)
+    case value
+    when Hash
+      merge!(value)
+    when String
+      value.split('; ').each do |cookie|
+        array = cookie.split('=')
+        self[array[0].to_sym] = array[1]
+      end
+    else
+      raise &quot;add_cookies only takes a Hash or a String&quot;
+    end
   end
 
   def to_cookie_string
-    collect { |k, v| &quot;#{k}=#{v}&quot; }.join(&quot;; &quot;)
+    delete_if { |k, v| CLIENT_COOKIES.include?(k.to_s) }.collect { |k, v| &quot;#{k}=#{v}&quot; }.join(&quot;; &quot;)
   end
 end</diff>
      <filename>lib/httparty/cookie_hash.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,6 @@
-if RUBY_VERSION.to_f == 1.8
-  class BlankSlate #:nodoc:
-    instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ }
-  end
-else
-  class BlankSlate &lt; BasicObject; end
-end
+class BasicObject #:nodoc:
+  instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
+end unless defined?(BasicObject)
  
 # 1.8.6 has mistyping of transitive in if statement
 require &quot;rexml/document&quot;</diff>
      <filename>lib/httparty/core_extensions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -41,10 +41,15 @@ module HTTParty
     end
 
     private
+
       def http
         http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
         http.use_ssl = (uri.port == 443)
         http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+        if options[:timeout] &amp;&amp; options[:timeout].is_a?(Integer)
+          http.open_timeout = options[:timeout]
+          http.read_timeout = options[:timeout]
+        end
         http
       end
 
@@ -98,6 +103,8 @@ module HTTParty
             options[:limit] -= 1
             self.path = response['location']
             @redirect = true
+            self.http_method = Net::HTTP::Get
+            capture_cookies(response)
             perform
           else
             parsed_response = parse_response(response.body)
@@ -118,6 +125,15 @@ module HTTParty
             body
           end
       end
+      
+      def capture_cookies(response)
+        return unless response['Set-Cookie']
+        cookies_hash = HTTParty::CookieHash.new()
+        cookies_hash.add_cookies(options[:headers]['Cookie']) if options[:headers] &amp;&amp; options[:headers]['Cookie']
+        cookies_hash.add_cookies(response['Set-Cookie'])
+        options[:headers] ||= {}
+        options[:headers]['Cookie'] = cookies_hash.to_cookie_string
+      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</diff>
      <filename>lib/httparty/request.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 module HTTParty
-  class Response &lt; BlankSlate #:nodoc:
+  class Response &lt; BasicObject #:nodoc:
     attr_accessor :body, :code, :message, :headers
     attr_reader :delegate
 </diff>
      <filename>lib/httparty/response.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,17 +6,44 @@ describe HTTParty::CookieHash do
   end
 
   describe &quot;#add_cookies&quot; do
-    it &quot;should add new key/value pairs to the hash&quot; do
-      @cookie_hash.add_cookies(:foo =&gt; &quot;bar&quot;)
-      @cookie_hash.add_cookies(:rofl =&gt; &quot;copter&quot;)
-      @cookie_hash.length.should eql(2)
+    
+    describe &quot;with a hash&quot; do
+      it &quot;should add new key/value pairs to the hash&quot; do
+        @cookie_hash.add_cookies(:foo =&gt; &quot;bar&quot;)
+        @cookie_hash.add_cookies(:rofl =&gt; &quot;copter&quot;)
+        @cookie_hash.length.should eql(2)
+      end
+
+      it &quot;should overwrite any existing key&quot; do
+        @cookie_hash.add_cookies(:foo =&gt; &quot;bar&quot;)
+        @cookie_hash.add_cookies(:foo =&gt; &quot;copter&quot;)
+        @cookie_hash.length.should eql(1)
+        @cookie_hash[:foo].should eql(&quot;copter&quot;)
+      end
     end
 
-    it &quot;should overwrite any existing key&quot; do
-      @cookie_hash.add_cookies(:foo =&gt; &quot;bar&quot;)
-      @cookie_hash.add_cookies(:foo =&gt; &quot;copter&quot;)
-      @cookie_hash.length.should eql(1)
-      @cookie_hash[:foo].should eql(&quot;copter&quot;)
+    describe &quot;with a string&quot; do
+      it &quot;should add new key/value pairs to the hash&quot; do
+        @cookie_hash.add_cookies(&quot;first=one; second=two; third&quot;)
+        @cookie_hash[:first].should == 'one'
+        @cookie_hash[:second].should == 'two'
+        @cookie_hash[:third].should == nil
+      end
+      
+      it &quot;should overwrite any existing key&quot; do
+        @cookie_hash[:foo] = 'bar'
+        @cookie_hash.add_cookies(&quot;foo=tar&quot;)
+        @cookie_hash.length.should eql(1)
+        @cookie_hash[:foo].should eql(&quot;tar&quot;)
+      end
+    end
+    
+    describe 'with other class' do
+      it &quot;should error&quot; do
+        lambda {
+          @cookie_hash.add_cookies(Array.new)
+        }.should raise_error
+      end
     end
   end
 
@@ -34,5 +61,11 @@ describe HTTParty::CookieHash do
       @s.should match(/rofl=copter/)
       @s.should match(/^\w+=\w+; \w+=\w+$/)
     end
+    
+    it &quot;should not include client side only cookies&quot; do
+      @cookie_hash.add_cookies(:path =&gt; &quot;/&quot;)
+      @s = @cookie_hash.to_cookie_string
+      @s.should_not match(/path=\//)
+    end
   end
 end</diff>
      <filename>spec/httparty/cookie_hash_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -46,8 +46,26 @@ describe HTTParty::Request do
       @request.send(:setup_raw_request)
       @request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil
     end
+
+    context &quot;when setting timeout&quot; do
+      it &quot;does nothing if the timeout option is a string&quot; do
+        http = mock(&quot;http&quot;, :null_object =&gt; true)
+        http.should_not_receive(:open_timeout=)
+        http.should_not_receive(:read_timeout=)
+        Net::HTTP.stub(:new =&gt; http)
+
+        request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com', {:timeout =&gt; &quot;five seconds&quot;})
+        request.send(:http)
+      end
+
+      it &quot;sets the timeout to 5 seconds&quot; do
+        @request.options[:timeout] = 5
+        @request.send(:http).open_timeout.should == 5
+        @request.send(:http).read_timeout.should == 5
+      end
+    end
   end
-  
+
   describe '#format_from_mimetype' do
     it 'should handle text/xml' do
       [&quot;text/xml&quot;, &quot;text/xml; charset=iso8859-1&quot;].each do |ct|
@@ -176,6 +194,33 @@ describe HTTParty::Request do
         @request.http_method = Net::HTTP::Put
         @request.perform.should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
       end
+      
+      it &quot;should keep track of cookies between redirects&quot; do
+        @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
+        @request.perform
+        @request.options[:headers]['Cookie'].should match(/foo=bar/)
+        @request.options[:headers]['Cookie'].should match(/name=value/)
+      end
+      
+      it 'should update cookies with rediects' do
+        @request.options[:headers] = {'Cookie'=&gt; 'foo=bar;'}
+        @redirect['Set-Cookie'] = 'foo=tar;'
+        @request.perform
+        @request.options[:headers]['Cookie'].should match(/foo=tar/)
+      end
+      
+      it 'should keep cookies between rediects' do
+        @request.options[:headers] = {'Cookie'=&gt; 'keep=me'}
+        @redirect['Set-Cookie'] = 'foo=tar;'
+        @request.perform
+        @request.options[:headers]['Cookie'].should match(/keep=me/)
+      end
+      
+      it 'should make resulting request a get request if it not already' do
+        @request.http_method = Net::HTTP::Delete
+        @request.perform.should == {&quot;hash&quot; =&gt; {&quot;foo&quot; =&gt; &quot;bar&quot;}}
+        @request.http_method.should == Net::HTTP::Get
+      end
     end
 
     describe &quot;infinitely&quot; do</diff>
      <filename>spec/httparty/request_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -51,15 +51,53 @@ describe HTTParty do
   end
   
   describe &quot;headers&quot; do
+    def expect_headers(header={})
+      HTTParty::Request.should_receive(:new) \
+        .with(anything, anything, hash_including({ :headers =&gt; header })) \
+        .and_return(mock(&quot;mock response&quot;, :perform =&gt; nil))
+    end
+
     it &quot;should default to empty hash&quot; do
       @klass.headers.should == {}
     end
-    
+
     it &quot;should be able to be updated&quot; do
       init_headers = {:foo =&gt; 'bar', :baz =&gt; 'spax'}
       @klass.headers init_headers
       @klass.headers.should == init_headers
     end
+
+    it &quot;uses the class headers when sending a request&quot; do
+      expect_headers(:foo =&gt; 'bar')
+      @klass.headers(:foo =&gt; 'bar')
+      @klass.get('')
+    end
+
+    it &quot;overwrites class headers when passing in headers&quot; do
+      expect_headers(:baz =&gt; 'spax')
+      @klass.headers(:foo =&gt; 'bar')
+      @klass.get('', :headers =&gt; {:baz =&gt; 'spax'})
+    end
+
+    context &quot;with cookies&quot; do
+      it 'utilizes the class-level cookies' do
+        expect_headers(:foo =&gt; 'bar', 'cookie' =&gt; 'type=snickerdoodle')
+        @klass.headers(:foo =&gt; 'bar')
+        @klass.cookies(:type =&gt; 'snickerdoodle')
+        @klass.get('')
+      end
+
+      it 'adds cookies to the headers' do
+        expect_headers(:foo =&gt; 'bar', 'cookie' =&gt; 'type=snickerdoodle')
+        @klass.headers(:foo =&gt; 'bar')
+        @klass.get('', :cookies =&gt; {:type =&gt; 'snickerdoodle'})
+      end
+
+      it 'adds optional cookies to the optional headers' do
+        expect_headers(:baz =&gt; 'spax', 'cookie' =&gt; 'type=snickerdoodle')
+        @klass.get('', :cookies =&gt; {:type =&gt; 'snickerdoodle'}, :headers =&gt; {:baz =&gt; 'spax'})
+      end
+    end
   end
 
   describe &quot;cookies&quot; do</diff>
      <filename>spec/httparty_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,2 @@
---format
-  progress
 --colour
+--format specdoc</diff>
      <filename>spec/spec.opts</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,10 @@
-require 'rubygems'
-gem 'rspec', '&gt;= 1.2.8'
-require 'spec'
 require File.join(File.dirname(__FILE__), '..', 'lib', 'httparty')
+gem 'rspec', '1.2.8'
+gem 'fakeweb'
+require 'spec/autorun'
+require 'fakeweb'
+
+FakeWeb.allow_net_connect = false
 
 def file_fixture(filename)
   open(File.join(File.dirname(__FILE__), 'fixtures', &quot;#{filename.to_s}&quot;)).read
@@ -18,4 +21,4 @@ def stub_http_response_with(filename)
   http_request.stub!(:perform_actual_request).and_return(response)
 
   HTTParty::Request.should_receive(:new).and_return(http_request)
-end
\ No newline at end of file
+end</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,32 +1,31 @@
 &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt; 
 &lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt; 
 &lt;head&gt; 
-	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt; 
-	&lt;title&gt;HTTParty by John Nunemaker&lt;/title&gt; 
-	&lt;link rel=&quot;stylesheet&quot; href=&quot;css/common.css&quot; type=&quot;text/css&quot; /&gt; 
+  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt; 
+  &lt;title&gt;HTTParty by John Nunemaker&lt;/title&gt; 
+  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/common.css&quot; type=&quot;text/css&quot; /&gt; 
 &lt;/head&gt; 
 &lt;body&gt; 
  
 &lt;div id=&quot;wrapper&quot;&gt; 
-	&lt;div id=&quot;header&quot;&gt; 
-		&lt;h1&gt;HTTParty&lt;/h1&gt; 
-		&lt;p&gt;Tonight we're gonna HTTParty like it's 1999!&lt;/p&gt; 
-		
-		&lt;ul id=&quot;nav&quot;&gt;
-			&lt;li&gt;&lt;a href=&quot;rdoc/&quot;&gt;Docs&lt;/a&gt;&lt;/li&gt; 
-			&lt;li&gt;&lt;a href=&quot;http://github.com/jnunemaker/httparty&quot;&gt;Github&lt;/a&gt;&lt;/li&gt;
-			&lt;li&gt;&lt;a href=&quot;http://jnunemaker.lighthouseapp.com/projects/14842-httparty/tickets&quot;&gt;Lighthouse&lt;/a&gt;&lt;/li&gt;
-			&lt;li&gt;&lt;a href=&quot;http://rubyforge.org/projects/httparty/&quot;&gt;Rubyforge&lt;/a&gt;&lt;/li&gt; 
-		&lt;/ul&gt; 
-	&lt;/div&gt; 
-	
-	&lt;div id=&quot;content&quot;&gt; 
-		&lt;h2&gt;Install&lt;/h2&gt; 
-		&lt;pre&gt;&lt;code&gt;$ sudo gem install httparty&lt;/code&gt;&lt;/pre&gt; 
-		
-		&lt;h2&gt;Some Quick Examples&lt;/h2&gt;
-		
-		&lt;p&gt;The following is a simple example of wrapping Twitter's API for posting updates.&lt;/p&gt;
+  &lt;div id=&quot;header&quot;&gt; 
+    &lt;h1&gt;HTTParty&lt;/h1&gt; 
+    &lt;p&gt;Tonight we're gonna HTTParty like it's 1999!&lt;/p&gt; 
+    
+    &lt;ul id=&quot;nav&quot;&gt;
+      &lt;li&gt;&lt;a href=&quot;rdoc/&quot;&gt;Docs&lt;/a&gt;&lt;/li&gt; 
+      &lt;li&gt;&lt;a href=&quot;http://github.com/jnunemaker/httparty&quot;&gt;Github&lt;/a&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;a href=&quot;http://rubyforge.org/projects/httparty/&quot;&gt;Rubyforge&lt;/a&gt;&lt;/li&gt; 
+    &lt;/ul&gt; 
+  &lt;/div&gt; 
+  
+  &lt;div id=&quot;content&quot;&gt; 
+    &lt;h2&gt;Install&lt;/h2&gt; 
+    &lt;pre&gt;&lt;code&gt;$ sudo gem install httparty&lt;/code&gt;&lt;/pre&gt; 
+    
+    &lt;h2&gt;Some Quick Examples&lt;/h2&gt;
+    
+    &lt;p&gt;The following is a simple example of wrapping Twitter's API for posting updates.&lt;/p&gt;
 
 &lt;pre&gt;&lt;code&gt;class Twitter
   include HTTParty
@@ -36,9 +35,9 @@ end
 
 Twitter.post('/statuses/update.json', :query =&gt; {:status =&gt; &quot;It's an HTTParty and everyone is invited!&quot;})&lt;/code&gt;&lt;/pre&gt;
 
-		&lt;p&gt;That is really it! The object returned is a ruby hash that is decoded from Twitter's json response. JSON parsing is used because of the .json extension in the path of the request. You can also explicitly set a format (see the examples). &lt;/p&gt;
+    &lt;p&gt;That is really it! The object returned is a ruby hash that is decoded from Twitter's json response. JSON parsing is used because of the .json extension in the path of the request. You can also explicitly set a format (see the examples). &lt;/p&gt;
 
-		&lt;p&gt;That works and all but what if you don't want to embed your username and password in the class? Below is an example to fix that:&lt;/p&gt;
+    &lt;p&gt;That works and all but what if you don't want to embed your username and password in the class? Below is an example to fix that:&lt;/p&gt;
 
 &lt;pre&gt;&lt;code&gt;class Twitter
   include HTTParty
@@ -55,19 +54,19 @@ Twitter.post('/statuses/update.json', :query =&gt; {:status =&gt; &quot;It's an HTTParty an
 end
 
 Twitter.new('username', 'password').post(&quot;It's an HTTParty and everyone is invited!&quot;)&lt;/code&gt;&lt;/pre&gt;
-		
-		&lt;p&gt;&lt;strong&gt;More Examples:&lt;/strong&gt; There are &lt;a href=&quot;http://github.com/jnunemaker/httparty/tree/master/examples/&quot;&gt;several examples in the gem itself&lt;/a&gt;.&lt;/p&gt;
-		
-		&lt;h2&gt;Support&lt;/h2&gt; 
-		&lt;p&gt;Conversations welcome in the &lt;a href=&quot;http://groups.google.com/group/httparty-gem&quot;&gt;google group&lt;/a&gt; and bugs/features over at &lt;a href=&quot;http://jnunemaker.lighthouseapp.com/projects/14842-httparty/overview&quot;&gt;Lightouse&lt;/a&gt;.&lt;/p&gt; 
-		
-		
-	&lt;/div&gt; 
+    
+    &lt;p&gt;&lt;strong&gt;More Examples:&lt;/strong&gt; There are &lt;a href=&quot;http://github.com/jnunemaker/httparty/tree/master/examples/&quot;&gt;several examples in the gem itself&lt;/a&gt;.&lt;/p&gt;
+    
+    &lt;h2&gt;Support&lt;/h2&gt; 
+    &lt;p&gt;Conversations welcome in the &lt;a href=&quot;http://groups.google.com/group/httparty-gem&quot;&gt;google group&lt;/a&gt; and bugs/features over at &lt;a href=&quot;http://github.com/jnunemaker/httparty&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt; 
+    
+    
+  &lt;/div&gt; 
  
-	&lt;div id=&quot;footer&quot;&gt; 
-		&lt;p&gt;Created by &lt;a href=&quot;http://addictedtonew.com/about/&quot;&gt;John Nunemaker&lt;/a&gt; | 
-		  &lt;a href=&quot;http://orderedlist.com/&quot;&gt;Hire Me at Ordered List&lt;/a&gt;&lt;/p&gt; 
-	&lt;/div&gt; 
+  &lt;div id=&quot;footer&quot;&gt; 
+    &lt;p&gt;Created by &lt;a href=&quot;http://addictedtonew.com/about/&quot;&gt;John Nunemaker&lt;/a&gt; | 
+      &lt;a href=&quot;http://orderedlist.com/&quot;&gt;Hire Me at Ordered List&lt;/a&gt;&lt;/p&gt; 
+  &lt;/div&gt; 
 &lt;/div&gt; 
  
 &lt;/body&gt; </diff>
      <filename>website/index.html</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2b6ca2f45c413871ed81d7c1e72f0855cb359ad0</id>
    </parent>
    <parent>
      <id>7443e42395e00ddaee362586471ae948eada4a76</id>
    </parent>
  </parents>
  <author>
    <name>John Nunemaker</name>
    <email>nunemaker@gmail.com</email>
  </author>
  <url>http://github.com/jnunemaker/httparty/commit/35090072152b6495f781aac3859bf3b342469f2c</url>
  <id>35090072152b6495f781aac3859bf3b342469f2c</id>
  <committed-date>2009-09-15T06:09:09-07:00</committed-date>
  <authored-date>2009-09-15T06:09:09-07:00</authored-date>
  <message>Merge branch 'master' of github.com:jnunemaker/httparty</message>
  <tree>a6f41a2b1adf03d01f4f9e4bf5b1362b92ebbe47</tree>
  <committer>
    <name>John Nunemaker</name>
    <email>nunemaker@gmail.com</email>
  </committer>
</commit>
