[DRE-commits] r4441 - in branches/upstream: . librestclient-ruby librestclient-ruby/current librestclient-ruby/current/bin librestclient-ruby/current/lib librestclient-ruby/current/lib/restclient librestclient-ruby/current/lib/restclient/mixin librestclient-ruby/current/spec librestclient-ruby/current/spec/mixin

Lucas Nussbaum lucas at alioth.debian.org
Sat Dec 12 16:52:10 UTC 2009


Author: lucas
Date: 2009-12-12 16:52:10 +0000 (Sat, 12 Dec 2009)
New Revision: 4441

Added:
   branches/upstream/librestclient-ruby/
   branches/upstream/librestclient-ruby/current/
   branches/upstream/librestclient-ruby/current/.gitignore
   branches/upstream/librestclient-ruby/current/README.rdoc
   branches/upstream/librestclient-ruby/current/Rakefile
   branches/upstream/librestclient-ruby/current/VERSION
   branches/upstream/librestclient-ruby/current/bin/
   branches/upstream/librestclient-ruby/current/bin/restclient
   branches/upstream/librestclient-ruby/current/lib/
   branches/upstream/librestclient-ruby/current/lib/rest_client.rb
   branches/upstream/librestclient-ruby/current/lib/restclient.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/
   branches/upstream/librestclient-ruby/current/lib/restclient/exceptions.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/mixin/
   branches/upstream/librestclient-ruby/current/lib/restclient/mixin/response.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/net_http_ext.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/payload.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/raw_response.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/request.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/resource.rb
   branches/upstream/librestclient-ruby/current/lib/restclient/response.rb
   branches/upstream/librestclient-ruby/current/rest-client.gemspec
   branches/upstream/librestclient-ruby/current/spec/
   branches/upstream/librestclient-ruby/current/spec/base.rb
   branches/upstream/librestclient-ruby/current/spec/exceptions_spec.rb
   branches/upstream/librestclient-ruby/current/spec/master_shake.jpg
   branches/upstream/librestclient-ruby/current/spec/mixin/
   branches/upstream/librestclient-ruby/current/spec/mixin/response_spec.rb
   branches/upstream/librestclient-ruby/current/spec/payload_spec.rb
   branches/upstream/librestclient-ruby/current/spec/raw_response_spec.rb
   branches/upstream/librestclient-ruby/current/spec/request_spec.rb
   branches/upstream/librestclient-ruby/current/spec/resource_spec.rb
   branches/upstream/librestclient-ruby/current/spec/response_spec.rb
   branches/upstream/librestclient-ruby/current/spec/restclient_spec.rb
Log:
[svn-inject] Installing original source of librestclient-ruby

Added: branches/upstream/librestclient-ruby/current/.gitignore
===================================================================
--- branches/upstream/librestclient-ruby/current/.gitignore	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/.gitignore	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,2 @@
+rdoc
+pkg

Added: branches/upstream/librestclient-ruby/current/README.rdoc
===================================================================
--- branches/upstream/librestclient-ruby/current/README.rdoc	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/README.rdoc	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,104 @@
+= REST Client -- simple DSL for accessing REST resources
+
+A simple REST client for Ruby, inspired by the Sinatra's microframework style
+of specifying actions: get, put, post, delete.
+
+== Usage: Raw URL
+
+  require 'rest_client'
+
+  RestClient.get 'http://example.com/resource'
+  RestClient.get 'https://user:password@example.com/private/resource'
+
+  RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
+
+  RestClient.delete 'http://example.com/resource'
+  
+== Multipart
+
+Yeah, that's right!  This does multipart sends for you!
+
+  RestClient.post '/data', :myfile => File.new("/path/to/image.jpg")
+
+This does two things for you:
+
+* Auto-detects that you have a File value sends it as multipart
+* Auto-detects the mime of the file and sets it in the HEAD of the payload for each entry
+
+If you are sending params that do not contain a File object but the payload needs to be multipart then:
+
+  RestClient.post '/data', :foo => 'bar', :multipart => true
+
+== Streaming downloads
+
+RestClient.get('http://some/resource/lotsofdata') do |res|
+  res.read_body do |chunk|
+    .. do something with chunk ..
+  end
+end
+
+See RestClient module docs for more details.
+
+== Usage: ActiveResource-Style
+
+  resource = RestClient::Resource.new 'http://example.com/resource'
+  resource.get
+
+  private_resource = RestClient::Resource.new 'https://example.com/private/resource', 'user', 'pass'
+  private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
+
+See RestClient::Resource module docs for details.
+
+== Usage: Resource Nesting
+
+  site = RestClient::Resource.new('http://example.com')
+  site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
+
+See RestClient::Resource docs for details.
+
+== Shell
+
+The restclient shell command gives an IRB session with RestClient already loaded:
+
+  $ restclient
+  >> RestClient.get 'http://example.com'
+
+Specify a URL argument for get/post/put/delete on that resource:
+
+  $ restclient http://example.com
+  >> put '/resource', 'data'
+
+Add a user and password for authenticated resources:
+
+  $ restclient https://example.com user pass
+  >> delete '/private/resource'
+
+Create ~/.restclient for named sessions:
+
+  sinatra:
+    url: http://localhost:4567
+  rack:
+    url: http://localhost:9292
+  private_site:
+    url: http://example.com
+    username: user
+    password: pass
+
+Then invoke:
+
+  $ restclient private_site
+  
+== Meta
+
+Written by Adam Wiggins (adam at heroku dot com)
+
+Major modifications by Blake Mizerany
+
+Patches contributed by: Chris Anderson, Greg Borenstein, Ardekantur, Pedro Belo, Rafael Souza, Rick Olson, and Aman Gupta
+
+Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
+
+http://rest-client.heroku.com
+
+http://github.com/adamwiggins/rest-client
+

Added: branches/upstream/librestclient-ruby/current/Rakefile
===================================================================
--- branches/upstream/librestclient-ruby/current/Rakefile	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/Rakefile	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,57 @@
+require 'rake'
+
+require 'jeweler'
+
+Jeweler::Tasks.new do |s|
+	s.name = "rest-client"
+	s.description = "A simple REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
+	s.summary = "Simple REST client for Ruby, inspired by microframework syntax for specifying actions."
+	s.author = "Adam Wiggins"
+	s.email = "adam at heroku.com"
+	s.homepage = "http://rest-client.heroku.com/"
+	s.rubyforge_project = "rest-client"
+	s.has_rdoc = true
+	s.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
+	s.executables = %w(restclient)
+end
+
+Jeweler::RubyforgeTasks.new
+
+############################
+
+require 'spec/rake/spectask'
+
+desc "Run all specs"
+Spec::Rake::SpecTask.new('spec') do |t|
+	t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
+	t.spec_files = FileList['spec/*_spec.rb']
+end
+
+desc "Print specdocs"
+Spec::Rake::SpecTask.new(:doc) do |t|
+	t.spec_opts = ["--format", "specdoc", "--dry-run"]
+	t.spec_files = FileList['spec/*_spec.rb']
+end
+
+desc "Run all examples with RCov"
+Spec::Rake::SpecTask.new('rcov') do |t|
+	t.spec_files = FileList['spec/*_spec.rb']
+	t.rcov = true
+	t.rcov_opts = ['--exclude', 'examples']
+end
+
+task :default => :spec
+
+############################
+
+require 'rake/rdoctask'
+
+Rake::RDocTask.new do |t|
+	t.rdoc_dir = 'rdoc'
+	t.title    = "rest-client, fetch RESTful resources effortlessly"
+	t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
+	t.options << '--charset' << 'utf-8'
+	t.rdoc_files.include('README.rdoc')
+	t.rdoc_files.include('lib/*.rb')
+end
+

Added: branches/upstream/librestclient-ruby/current/VERSION
===================================================================
--- branches/upstream/librestclient-ruby/current/VERSION	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/VERSION	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1 @@
+1.1.5

Added: branches/upstream/librestclient-ruby/current/bin/restclient
===================================================================
--- branches/upstream/librestclient-ruby/current/bin/restclient	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/bin/restclient	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,87 @@
+#!/usr/bin/env ruby
+
+$:.unshift File.dirname(__FILE__) + "/../lib"
+require 'restclient'
+
+require "yaml"
+
+def usage(why = nil)
+	puts "failed for reason: #{why}" if why
+	puts "usage: restclient [get|put|post|delete] url|name [username] [password]"
+	puts "  The verb is optional, if you leave it off you'll get an interactive shell."
+	puts "  put and post both take the input body on stdin."
+	exit(1)
+end
+
+if %w(get put post delete).include? ARGV.first
+	@verb = ARGV.shift
+else
+	@verb = nil
+end
+
+ at url = ARGV.shift || 'http://localhost:4567'
+
+config = YAML.load(File.read(ENV['HOME'] + "/.restclient")) rescue {}
+
+ at url, @username, @password = if c = config[@url]
+	[c['url'], c['username'], c['password']]
+else
+	[@url, *ARGV]
+end
+
+usage("invalid url '#{@url}") unless @url =~ /^https?/
+usage("too few args") unless ARGV.size < 3
+
+def r
+	@r ||= RestClient::Resource.new(@url, @username, @password)
+end
+
+r # force rc to load
+
+if @verb
+	begin
+		if %w(put post).include? @verb
+			puts r.send(@verb, STDIN.read)
+		else
+			puts r.send(@verb)
+		end
+		exit 0
+	rescue RestClient::Exception => e
+		puts e.response.body if e.respond_to? :response
+		raise
+	end
+end
+
+%w(get post put delete).each do |m|
+ eval <<-end_eval
+def #{m}(path, *args, &b)
+	r[path].#{m}(*args, &b)
+end
+ end_eval
+end
+
+def method_missing(s, *args, &b)
+	super unless r.respond_to?(s)
+	begin
+		r.send(s, *args, &b)
+	rescue RestClient::RequestFailed => e
+		print STDERR, e.response.body
+		raise e
+	end
+end
+
+require 'irb'
+require 'irb/completion'
+
+if File.exists? ".irbrc"
+	ENV['IRBRC'] = ".irbrc"
+end
+
+if File.exists?(rcfile = "~/.restclientrc")
+	load(rcfile)
+end
+
+ARGV.clear
+
+IRB.start
+exit!


Property changes on: branches/upstream/librestclient-ruby/current/bin/restclient
___________________________________________________________________
Added: svn:executable
   + 

Added: branches/upstream/librestclient-ruby/current/lib/rest_client.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/rest_client.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/rest_client.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,2 @@
+# This file exists for backward compatbility with require 'rest_client'
+require File.dirname(__FILE__) + '/restclient'

Added: branches/upstream/librestclient-ruby/current/lib/restclient/exceptions.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/exceptions.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/exceptions.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,88 @@
+module RestClient
+	# This is the base RestClient exception class. Rescue it if you want to
+	# catch any exception that your request might raise
+	class Exception < RuntimeError
+		def message(default=nil)
+			self.class::ErrorMessage
+		end
+	end
+
+	# Base RestClient exception when there's a response available
+	class ExceptionWithResponse < Exception
+		attr_accessor :response
+
+		def initialize(response=nil)
+			@response = response
+		end
+
+		def http_code
+			@response.code.to_i if @response
+		end
+
+		def http_body
+			RestClient::Request.decode(@response['content-encoding'], @response.body) if @response
+		end
+	end
+
+	# A redirect was encountered; caught by execute to retry with the new url.
+	class Redirect < Exception
+		ErrorMessage = "Redirect"
+
+		attr_accessor :url
+		def initialize(url)
+			@url = url
+		end
+	end
+
+	class NotModified < ExceptionWithResponse
+		ErrorMessage = 'NotModified'
+	end
+
+	# Authorization is required to access the resource specified.
+	class Unauthorized < ExceptionWithResponse
+		ErrorMessage = 'Unauthorized'
+	end
+
+	# No resource was found at the given URL.
+	class ResourceNotFound < ExceptionWithResponse
+		ErrorMessage = 'Resource not found'
+	end
+
+	# The server broke the connection prior to the request completing.  Usually
+	# this means it crashed, or sometimes that your network connection was
+	# severed before it could complete.
+	class ServerBrokeConnection < Exception
+		ErrorMessage = 'Server broke connection'
+	end
+
+	# The server took too long to respond.
+	class RequestTimeout < Exception
+		ErrorMessage = 'Request timed out'
+	end
+
+	# The request failed, meaning the remote HTTP server returned a code other
+	# than success, unauthorized, or redirect.
+	#
+	# The exception message attempts to extract the error from the XML, using
+	# format returned by Rails: <errors><error>some message</error></errors>
+	#
+	# You can get the status code by e.http_code, or see anything about the
+	# response via e.response.  For example, the entire result body (which is
+	# probably an HTML error page) is e.response.body.
+	class RequestFailed < ExceptionWithResponse
+		def message
+			"HTTP status code #{http_code}"
+		end
+
+		def to_s
+			message
+		end
+	end
+end
+
+# backwards compatibility
+class RestClient::Request
+	Redirect = RestClient::Redirect
+	Unauthorized = RestClient::Unauthorized
+	RequestFailed = RestClient::RequestFailed
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/mixin/response.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/mixin/response.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/mixin/response.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,43 @@
+module RestClient
+	module Mixin
+		module Response
+			attr_reader :net_http_res
+
+			# HTTP status code, always 200 since RestClient throws exceptions for
+			# other codes.
+			def code
+				@code ||= @net_http_res.code.to_i
+			end
+
+			# A hash of the headers, beautified with symbols and underscores.
+			# e.g. "Content-type" will become :content_type.
+			def headers
+				@headers ||= self.class.beautify_headers(@net_http_res.to_hash)
+			end
+
+			# Hash of cookies extracted from response headers
+			def cookies
+				@cookies ||= (self.headers[:set_cookie] || "").split('; ').inject({}) do |out, raw_c|
+					key, val = raw_c.split('=')
+					unless %w(expires domain path secure).member?(key)
+						out[key] = val
+					end
+					out
+				end
+			end
+
+			def self.included(receiver)
+				receiver.extend(RestClient::Mixin::Response::ClassMethods)
+			end
+
+			module ClassMethods
+				def beautify_headers(headers)
+					headers.inject({}) do |out, (key, value)|
+						out[key.gsub(/-/, '_').to_sym] = value.first
+					out
+					end
+				end
+			end
+		end
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/net_http_ext.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/net_http_ext.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/net_http_ext.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,21 @@
+#
+# Replace the request method in Net::HTTP to sniff the body type
+# and set the stream if appropriate
+#
+# Taken from:	
+# http://www.missiondata.com/blog/ruby/29/streaming-data-to-s3-with-ruby/
+
+module Net
+	class HTTP
+		alias __request__ request
+
+		def request(req, body=nil, &block)
+			if body != nil && body.respond_to?(:read)
+				req.body_stream = body
+				return __request__(req, nil, &block)
+			else
+				return __request__(req, body, &block)
+			end
+		end
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/payload.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/payload.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/payload.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,206 @@
+require "tempfile"
+require "stringio"
+
+module RestClient
+	module Payload
+		extend self
+
+		def generate(params)
+			if params.is_a?(String)
+				Base.new(params)
+			elsif params
+				if params.delete(:multipart) == true || has_file?(params)
+					Multipart.new(params)
+				else
+					UrlEncoded.new(params)
+				end
+			else
+				nil
+			end
+		end
+
+		def has_file?(params)
+			params.any? do |_, v|
+				case v
+				when Hash
+					has_file?(v)
+				else
+					v.respond_to?(:path) && v.respond_to?(:read)
+				end
+			end
+		end
+
+		class Base
+			def initialize(params)
+				build_stream(params)
+			end
+
+			def build_stream(params)
+				@stream = StringIO.new(params)
+				@stream.seek(0)
+			end
+
+			def read(bytes=nil)
+				@stream.read(bytes)
+			end
+			alias :to_s :read
+
+			def escape(v)
+				URI.escape(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
+			end
+
+			def headers
+				{ 'Content-Length' => size.to_s }
+			end
+
+			def size
+				@stream.size
+			end
+			alias :length :size
+
+			def close
+				@stream.close
+			end
+
+			def inspect
+				to_s.inspect
+			end
+		end
+
+		class UrlEncoded < Base
+			def build_stream(params)
+				@stream = StringIO.new(params.map do |k,v| 
+					"#{escape(k)}=#{escape(v)}"
+				end.join("&"))
+				@stream.seek(0)
+			end
+
+			def headers
+				super.merge({ 'Content-Type' => 'application/x-www-form-urlencoded' })
+			end
+		end
+
+		class Multipart < Base
+			EOL = "\r\n"
+
+			def build_stream(params)
+				b = "--#{boundary}"
+
+				@stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
+				@stream.write(b + EOL)
+				x = params.to_a
+				last_index = x.length - 1
+				x.each_with_index do |a, index|
+					k, v = *a
+					if v.respond_to?(:read) && v.respond_to?(:path)
+						create_file_field(@stream, k,v)
+					else
+						create_regular_field(@stream, k,v)
+					end
+					@stream.write(EOL + b)
+					@stream.write(EOL) unless last_index == index
+				end
+				@stream.write('--')
+				@stream.write(EOL)
+				@stream.seek(0)
+			end
+
+			def create_regular_field(s, k, v)
+				s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"")
+				s.write(EOL)
+				s.write(EOL)
+				s.write(v)
+			end
+
+			def create_file_field(s, k, v)
+				begin
+					s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"; filename=\"#{File.basename(v.path)}\"#{EOL}")
+					s.write("Content-Type: #{mime_for(v.path)}#{EOL}")
+					s.write(EOL)
+					while data = v.read(8124)
+						s.write(data)
+					end
+				ensure
+					v.close
+				end
+			end
+
+			def mime_for(path)
+				ext = File.extname(path)[1..-1]
+				MIME_TYPES[ext] || 'text/plain'
+			end
+
+			def boundary
+				@boundary ||= rand(1_000_000).to_s
+			end
+
+			def headers
+				super.merge({'Content-Type' => %Q{multipart/form-data; boundary="#{boundary}"}})
+			end
+
+			def close
+				@stream.close
+			end
+		end
+
+		# :stopdoc:
+		# From WEBrick.
+		MIME_TYPES = {
+			"ai"    => "application/postscript",
+			"asc"   => "text/plain",
+			"avi"   => "video/x-msvideo",
+			"bin"   => "application/octet-stream",
+			"bmp"   => "image/bmp",
+			"class" => "application/octet-stream",
+			"cer"   => "application/pkix-cert",
+			"crl"   => "application/pkix-crl",
+			"crt"   => "application/x-x509-ca-cert",
+			"css"   => "text/css",
+			"dms"   => "application/octet-stream",
+			"doc"   => "application/msword",
+			"dvi"   => "application/x-dvi",
+			"eps"   => "application/postscript",
+			"etx"   => "text/x-setext",
+			"exe"   => "application/octet-stream",
+			"gif"   => "image/gif",
+			"gz"   => "application/x-gzip",
+			"htm"   => "text/html",
+			"html"  => "text/html",
+			"jpe"   => "image/jpeg",
+			"jpeg"  => "image/jpeg",
+			"jpg"   => "image/jpeg",
+			"js"    => "text/javascript",
+			"lha"   => "application/octet-stream",
+			"lzh"   => "application/octet-stream",
+			"mov"   => "video/quicktime",
+			"mpe"   => "video/mpeg",
+			"mpeg"  => "video/mpeg",
+			"mpg"   => "video/mpeg",
+			"pbm"   => "image/x-portable-bitmap",
+			"pdf"   => "application/pdf",
+			"pgm"   => "image/x-portable-graymap",
+			"png"   => "image/png",
+			"pnm"   => "image/x-portable-anymap",
+			"ppm"   => "image/x-portable-pixmap",
+			"ppt"   => "application/vnd.ms-powerpoint",
+			"ps"    => "application/postscript",
+			"qt"    => "video/quicktime",
+			"ras"   => "image/x-cmu-raster",
+			"rb"    => "text/plain",
+			"rd"    => "text/plain",
+			"rtf"   => "application/rtf",
+			"sgm"   => "text/sgml",
+			"sgml"  => "text/sgml",
+			"tif"   => "image/tiff",
+			"tiff"  => "image/tiff",
+			"txt"   => "text/plain",
+			"xbm"   => "image/x-xbitmap",
+			"xls"   => "application/vnd.ms-excel",
+			"xml"   => "text/xml",
+			"xpm"   => "image/x-xpixmap",
+			"xwd"   => "image/x-xwindowdump",
+			"zip"   => "application/zip",
+		}
+		# :startdoc:
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/raw_response.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/raw_response.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/raw_response.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,30 @@
+require File.dirname(__FILE__) + '/mixin/response'
+
+module RestClient
+	# The response from RestClient on a raw request looks like a string, but is 
+	# actually one of these.  99% of the time you're making a rest call all you 
+	# care about is the body, but on the occassion you want to fetch the 
+	# headers you can:
+	#
+	#   RestClient.get('http://example.com').headers[:content_type]
+	#
+	# In addition, if you do not use the response as a string, you can access
+	# a Tempfile object at res.file, which contains the path to the raw 
+	# downloaded request body.  
+	class RawResponse 
+		include RestClient::Mixin::Response
+
+		attr_reader :file
+
+		def initialize(tempfile, net_http_res)
+			@net_http_res = net_http_res
+			@file = tempfile
+		end
+
+		def to_s
+			@file.open
+			@file.read
+		end
+
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/request.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/request.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/request.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,241 @@
+require 'tempfile'
+
+module RestClient
+	# This class is used internally by RestClient to send the request, but you can also
+	# access it internally if you'd like to use a method not directly supported by the
+	# main API.  For example:
+	#
+	#   RestClient::Request.execute(:method => :head, :url => 'http://example.com')
+	#
+	class Request
+		attr_reader :method, :url, :payload, :headers,
+			:cookies, :user, :password, :timeout, :open_timeout,
+			:verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file,
+			:raw_response
+
+		def self.execute(args)
+			new(args).execute
+		end
+
+		def initialize(args)
+			@method = args[:method] or raise ArgumentError, "must pass :method"
+			@url = args[:url] or raise ArgumentError, "must pass :url"
+			@headers = args[:headers] || {}
+			@cookies = @headers.delete(:cookies) || args[:cookies] || {}
+			@payload = Payload.generate(args[:payload])
+			@user = args[:user]
+			@password = args[:password]
+			@timeout = args[:timeout]
+			@open_timeout = args[:open_timeout]
+			@raw_response = args[:raw_response] || false
+			@verify_ssl = args[:verify_ssl] || false
+			@ssl_client_cert = args[:ssl_client_cert] || nil
+			@ssl_client_key  = args[:ssl_client_key] || nil
+			@ssl_ca_file = args[:ssl_ca_file] || nil
+			@tf = nil # If you are a raw request, this is your tempfile
+		end
+
+		def execute
+			execute_inner
+		rescue Redirect => e
+			@url = e.url
+			@method = :get
+			@payload = nil
+			execute
+		end
+
+		def execute_inner
+			uri = parse_url_with_auth(url)
+			transmit uri, net_http_request_class(method).new(uri.request_uri, make_headers(headers)), payload
+		end
+
+		def make_headers(user_headers)
+			unless @cookies.empty?
+				user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
+			end
+
+			headers = default_headers.merge(user_headers).inject({}) do |final, (key, value)|
+				final[key.to_s.gsub(/_/, '-').capitalize] = value.to_s
+				final
+			end
+
+			headers.merge!(@payload.headers) if @payload
+			headers
+		end
+
+		def net_http_class
+			if RestClient.proxy
+				proxy_uri = URI.parse(RestClient.proxy)
+				Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
+			else
+				Net::HTTP
+			end
+		end
+
+		def net_http_request_class(method)
+			Net::HTTP.const_get(method.to_s.capitalize)
+		end
+
+		def parse_url(url)
+			url = "http://#{url}" unless url.match(/^http/)
+			URI.parse(url)
+		end
+
+		def parse_url_with_auth(url)
+			uri = parse_url(url)
+			@user = uri.user if uri.user
+			@password = uri.password if uri.password
+			uri
+		end
+
+		def process_payload(p=nil, parent_key=nil)
+			unless p.is_a?(Hash)
+				p
+			else
+				@headers[:content_type] ||= 'application/x-www-form-urlencoded'
+				p.keys.map do |k|
+					key = parent_key ? "#{parent_key}[#{k}]" : k
+					if p[k].is_a? Hash
+						process_payload(p[k], key)
+					else
+						value = URI.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
+						"#{key}=#{value}"
+					end
+				end.join("&")
+			end
+		end
+
+		def transmit(uri, req, payload)
+			setup_credentials(req)
+
+			net = net_http_class.new(uri.host, uri.port)
+			net.use_ssl = uri.is_a?(URI::HTTPS)
+			if @verify_ssl == false
+        net.verify_mode = OpenSSL::SSL::VERIFY_NONE
+      elsif @verify_ssl.is_a? Integer
+        net.verify_mode = @verify_ssl
+      end
+			net.cert = @ssl_client_cert if @ssl_client_cert
+			net.key = @ssl_client_key if @ssl_client_key
+			net.ca_file = @ssl_ca_file if @ssl_ca_file
+			net.read_timeout = @timeout if @timeout
+			net.open_timeout = @open_timeout if @open_timeout
+
+			display_log request_log
+
+			net.start do |http|
+				res = http.request(req, payload) { |http_response| fetch_body(http_response) }
+				result = process_result(res)
+				display_log response_log(res)
+
+				if result.kind_of?(String) or @method == :head
+					Response.new(result, res)
+				elsif @raw_response
+					RawResponse.new(@tf, res)
+				else
+					nil
+				end
+			end
+		rescue EOFError
+			raise RestClient::ServerBrokeConnection
+		rescue Timeout::Error
+			raise RestClient::RequestTimeout
+		end
+
+		def setup_credentials(req)
+			req.basic_auth(user, password) if user
+		end
+
+		def fetch_body(http_response)
+			if @raw_response
+				# Taken from Chef, which as in turn...
+				# Stolen from http://www.ruby-forum.com/topic/166423
+				# Kudos to _why!
+				@tf = Tempfile.new("rest-client") 
+				size, total = 0, http_response.header['Content-Length'].to_i
+				http_response.read_body do |chunk|
+					@tf.write(chunk) 
+					size += chunk.size
+					if size == 0
+						display_log("#{@method} #{@url} done (0 length file)")
+					elsif total == 0
+						display_log("#{@method} #{@url} (zero content length)")
+					else
+						display_log("#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total])
+					end
+				end
+				@tf.close
+				@tf
+			else
+				http_response.read_body
+			end
+			http_response
+		end
+
+		def process_result(res)
+			if res.code =~ /\A2\d{2}\z/ 
+				# We don't decode raw requests
+				unless @raw_response
+					self.class.decode res['content-encoding'], res.body if res.body
+				end
+			elsif %w(301 302 303).include? res.code
+				url = res.header['Location']
+
+				if url !~ /^http/
+					uri = URI.parse(@url)
+					uri.path = "/#{url}".squeeze('/')
+					url = uri.to_s
+				end
+
+				raise Redirect, url
+			elsif res.code == "304"
+				raise NotModified, res
+			elsif res.code == "401"
+				raise Unauthorized, res
+			elsif res.code == "404"
+				raise ResourceNotFound, res
+			else
+				raise RequestFailed, res
+			end
+		end
+
+		def self.decode(content_encoding, body)
+			if content_encoding == 'gzip' and not body.empty?
+				Zlib::GzipReader.new(StringIO.new(body)).read
+			elsif content_encoding == 'deflate'
+				Zlib::Inflate.new.inflate(body)
+			else
+				body
+			end
+		end
+
+		def request_log
+			out = []
+			out << "RestClient.#{method} #{url.inspect}"
+			out << (payload.size > 100 ? "(#{payload.size} byte payload)".inspect : payload.inspect) if payload
+			out << headers.inspect.gsub(/^\{/, '').gsub(/\}$/, '') unless headers.empty?
+			out.join(', ')
+		end
+
+		def response_log(res)
+			size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
+			"# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
+		end
+
+		def display_log(msg)
+			return unless log_to = RestClient.log
+
+			if log_to == 'stdout'
+				STDOUT.puts msg
+			elsif log_to == 'stderr'
+				STDERR.puts msg
+			else
+				File.open(log_to, 'a') { |f| f.puts msg }
+			end
+		end
+
+		def default_headers
+			{ :accept => '*/*; q=0.5, application/xml', :accept_encoding => 'gzip, deflate' }
+		end
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/resource.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/resource.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/resource.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,146 @@
+module RestClient
+	# A class that can be instantiated for access to a RESTful resource,
+	# including authentication.
+	#
+	# Example:
+	#
+	#   resource = RestClient::Resource.new('http://some/resource')
+	#   jpg = resource.get(:accept => 'image/jpg')
+	#
+	# With HTTP basic authentication:
+	#
+	#   resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
+	#   resource.delete
+	#
+	# With a timeout (seconds):
+	#
+	#   RestClient::Resource.new('http://slow', :timeout => 10)
+	#
+	# With an open timeout (seconds):
+	#
+	#   RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
+	#
+	# You can also use resources to share common headers. For headers keys,
+	# symbols are converted to strings. Example:
+	#
+	#   resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
+	#
+	# This header will be transported as X-Client-Version (notice the X prefix,
+	# capitalization and hyphens)
+	#
+	# Use the [] syntax to allocate subresources:
+	#
+	#   site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
+	#   site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
+	#
+	class Resource
+		attr_reader :url, :options
+
+		def initialize(url, options={}, backwards_compatibility=nil)
+			@url = url
+			if options.class == Hash
+				@options = options
+			else # compatibility with previous versions
+				@options = { :user => options, :password => backwards_compatibility }
+			end
+		end
+
+		def get(additional_headers={}, &b)
+			headers = (options[:headers] || {}).merge(additional_headers)
+			Request.execute(options.merge(
+				:method => :get,
+				:url => url,
+				:headers => headers), &b)
+		end
+
+		def post(payload, additional_headers={}, &b)
+			headers = (options[:headers] || {}).merge(additional_headers)
+			Request.execute(options.merge(
+				:method => :post,
+				:url => url,
+				:payload => payload,
+				:headers => headers), &b)
+		end
+
+		def put(payload, additional_headers={}, &b)
+			headers = (options[:headers] || {}).merge(additional_headers)
+			Request.execute(options.merge(
+				:method => :put,
+				:url => url,
+				:payload => payload,
+				:headers => headers), &b)
+		end
+
+		def delete(additional_headers={}, &b)
+			headers = (options[:headers] || {}).merge(additional_headers)
+			Request.execute(options.merge(
+				:method => :delete,
+				:url => url,
+				:headers => headers), &b)
+		end
+
+		def to_s
+			url
+		end
+
+		def user
+			options[:user]
+		end
+
+		def password
+			options[:password]
+		end
+
+		def headers
+			options[:headers] || {}
+		end
+
+		def timeout
+			options[:timeout]
+		end
+		
+		def open_timeout
+			options[:open_timeout]
+		end
+
+		# Construct a subresource, preserving authentication.
+		#
+		# Example:
+		#
+		#   site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
+		#   site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
+		#
+		# This is especially useful if you wish to define your site in one place and
+		# call it in multiple locations:
+		#
+		#   def orders
+		#     RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
+		#   end
+		#
+		#   orders.get                     # GET http://example.com/orders
+		#   orders['1'].get                # GET http://example.com/orders/1
+		#   orders['1/items'].delete       # DELETE http://example.com/orders/1/items
+		#
+		# Nest resources as far as you want:
+		#
+		#   site = RestClient::Resource.new('http://example.com')
+		#   posts = site['posts']
+		#   first_post = posts['1']
+		#   comments = first_post['comments']
+		#   comments.post 'Hello', :content_type => 'text/plain'
+		#
+		def [](suburl)
+			self.class.new(concat_urls(url, suburl), options)
+		end
+
+		def concat_urls(url, suburl)   # :nodoc:
+			url = url.to_s
+			suburl = suburl.to_s
+			if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
+				url + suburl
+			else
+				"#{url}/#{suburl}"
+			end
+		end
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient/response.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient/response.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient/response.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,20 @@
+require File.dirname(__FILE__) + '/mixin/response'
+
+module RestClient
+	# The response from RestClient looks like a string, but is actually one of
+	# these.  99% of the time you're making a rest call all you care about is
+	# the body, but on the occassion you want to fetch the headers you can:
+	#
+	#   RestClient.get('http://example.com').headers[:content_type]
+	#
+	class Response < String
+
+		include RestClient::Mixin::Response
+
+		def initialize(string, net_http_res)
+			@net_http_res = net_http_res
+			super(string || "")
+		end
+
+	end
+end

Added: branches/upstream/librestclient-ruby/current/lib/restclient.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/lib/restclient.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/lib/restclient.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,107 @@
+require 'uri'
+require 'zlib'
+require 'stringio'
+
+begin
+	require 'net/https'
+rescue LoadError => e
+	raise e unless RUBY_PLATFORM =~ /linux/
+	raise LoadError, "no such file to load -- net/https. Try running apt-get install libopenssl-ruby"
+end
+
+require File.dirname(__FILE__) + '/restclient/request'
+require File.dirname(__FILE__) + '/restclient/mixin/response'
+require File.dirname(__FILE__) + '/restclient/response'
+require File.dirname(__FILE__) + '/restclient/raw_response'
+require File.dirname(__FILE__) + '/restclient/resource'
+require File.dirname(__FILE__) + '/restclient/exceptions'
+require File.dirname(__FILE__) + '/restclient/payload'
+require File.dirname(__FILE__) + '/restclient/net_http_ext'
+
+# This module's static methods are the entry point for using the REST client.
+#
+#   # GET
+#   xml = RestClient.get 'http://example.com/resource'
+#   jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
+#
+#   # authentication and SSL
+#   RestClient.get 'https://user:password@example.com/private/resource'
+#
+#   # POST or PUT with a hash sends parameters as a urlencoded form body
+#   RestClient.post 'http://example.com/resource', :param1 => 'one'
+#
+#   # nest hash parameters
+#   RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
+#
+#   # POST and PUT with raw payloads
+#   RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
+#   RestClient.post 'http://example.com/resource.xml', xml_doc
+#   RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
+#
+#   # DELETE
+#   RestClient.delete 'http://example.com/resource'
+#
+#   # retreive the response http code and headers
+#   res = RestClient.get 'http://example.com/some.jpg'
+#   res.code                    # => 200
+#   res.headers[:content_type]  # => 'image/jpg'
+#
+#   # HEAD
+#   RestClient.head('http://example.com').headers
+#
+# To use with a proxy, just set RestClient.proxy to the proper http proxy:
+#
+#   RestClient.proxy = "http://proxy.example.com/"
+#
+# Or inherit the proxy from the environment:
+#
+#   RestClient.proxy = ENV['http_proxy']
+#
+# For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
+#
+#   >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
+#   => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
+#
+module RestClient
+	def self.get(url, headers={})
+		Request.execute(:method => :get, :url => url, :headers => headers)
+	end
+
+	def self.post(url, payload, headers={})
+		Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers)
+	end
+
+	def self.put(url, payload, headers={})
+		Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers)
+	end
+
+	def self.delete(url, headers={})
+		Request.execute(:method => :delete, :url => url, :headers => headers)
+	end
+
+	def self.head(url, headers={})
+		Request.execute(:method => :head, :url => url, :headers => headers)
+	end
+
+	class << self
+		attr_accessor :proxy
+	end
+
+	# Print log of RestClient calls.  Value can be stdout, stderr, or a filename.
+	# You can also configure logging by the environment variable RESTCLIENT_LOG.
+	def self.log=(log)
+		@@log = log
+	end
+
+	def self.log    # :nodoc:
+		return ENV['RESTCLIENT_LOG'] if ENV['RESTCLIENT_LOG']
+		return @@log if defined? @@log
+		nil
+	end
+
+  def self.version
+    version_path = File.dirname(__FILE__) + "/../VERSION"
+    return File.read(version_path).chomp if File.file?(version_path)
+    "0.0.0"
+  end
+end

Added: branches/upstream/librestclient-ruby/current/rest-client.gemspec
===================================================================
--- branches/upstream/librestclient-ruby/current/rest-client.gemspec	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/rest-client.gemspec	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,70 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+  s.name = %q{rest-client}
+  s.version = "1.1.5"
+
+  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+  s.authors = ["Adam Wiggins"]
+  s.date = %q{2009-08-12}
+  s.default_executable = %q{restclient}
+  s.description = %q{A simple REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.}
+  s.email = %q{adam at heroku.com}
+  s.executables = ["restclient"]
+  s.extra_rdoc_files = [
+    "README.rdoc"
+  ]
+  s.files = [
+    "README.rdoc",
+     "Rakefile",
+     "VERSION",
+     "bin/restclient",
+     "lib/rest_client.rb",
+     "lib/restclient.rb",
+     "lib/restclient/exceptions.rb",
+     "lib/restclient/mixin/response.rb",
+     "lib/restclient/net_http_ext.rb",
+     "lib/restclient/payload.rb",
+     "lib/restclient/raw_response.rb",
+     "lib/restclient/request.rb",
+     "lib/restclient/resource.rb",
+     "lib/restclient/response.rb",
+     "spec/base.rb",
+     "spec/exceptions_spec.rb",
+     "spec/master_shake.jpg",
+     "spec/mixin/response_spec.rb",
+     "spec/payload_spec.rb",
+     "spec/raw_response_spec.rb",
+     "spec/request_spec.rb",
+     "spec/resource_spec.rb",
+     "spec/response_spec.rb",
+     "spec/restclient_spec.rb"
+  ]
+  s.homepage = %q{http://rest-client.heroku.com/}
+  s.rdoc_options = ["--charset=UTF-8"]
+  s.require_paths = ["lib"]
+  s.rubyforge_project = %q{rest-client}
+  s.rubygems_version = %q{1.3.5}
+  s.summary = %q{Simple REST client for Ruby, inspired by microframework syntax for specifying actions.}
+  s.test_files = [
+    "spec/base.rb",
+     "spec/exceptions_spec.rb",
+     "spec/mixin/response_spec.rb",
+     "spec/payload_spec.rb",
+     "spec/raw_response_spec.rb",
+     "spec/request_spec.rb",
+     "spec/resource_spec.rb",
+     "spec/response_spec.rb",
+     "spec/restclient_spec.rb"
+  ]
+
+  if s.respond_to? :specification_version then
+    current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+    s.specification_version = 3
+
+    if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+    else
+    end
+  else
+  end
+end

Added: branches/upstream/librestclient-ruby/current/spec/base.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/base.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/base.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,10 @@
+require 'rubygems'
+require 'spec'
+
+begin
+  require "ruby-debug"
+rescue LoadError
+  # NOP, ignore
+end
+
+require File.dirname(__FILE__) + '/../lib/restclient'

Added: branches/upstream/librestclient-ruby/current/spec/exceptions_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/exceptions_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/exceptions_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,65 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient::Exception do
+	it "sets the exception message to ErrorMessage" do
+		RestClient::ResourceNotFound.new.message.should == 'Resource not found'
+	end
+
+	it "contains exceptions in RestClient" do
+		RestClient::Unauthorized.new.should be_a_kind_of(RestClient::Exception)
+		RestClient::ServerBrokeConnection.new.should be_a_kind_of(RestClient::Exception)
+	end
+end
+
+describe RestClient::RequestFailed do
+	before do
+		@response = mock('HTTP Response', :code => '502')
+	end
+
+	it "stores the http response on the exception" do
+		begin
+			raise RestClient::RequestFailed, :response
+		rescue RestClient::RequestFailed => e
+			e.response.should == :response
+		end
+	end
+
+	it "http_code convenience method for fetching the code as an integer" do
+		RestClient::RequestFailed.new(@response).http_code.should == 502
+	end
+
+	it "http_body convenience method for fetching the body (decoding when necessary)" do
+		@response.stub!(:[]).with('content-encoding').and_return('gzip')
+		@response.stub!(:body).and_return('compressed body')
+		RestClient::Request.should_receive(:decode).with('gzip', 'compressed body').and_return('plain body')
+		RestClient::RequestFailed.new(@response).http_body.should == 'plain body'
+	end
+
+	it "shows the status code in the message" do
+		RestClient::RequestFailed.new(@response).to_s.should match(/502/)
+	end
+end
+
+describe RestClient::ResourceNotFound do
+	it "also has the http response attached" do
+		begin
+			raise RestClient::ResourceNotFound, :response
+		rescue RestClient::ResourceNotFound => e
+			e.response.should == :response
+		end
+	end
+end
+
+describe "backwards compatibility" do
+	it "alias RestClient::Request::Redirect to RestClient::Redirect" do
+		RestClient::Request::Redirect.should == RestClient::Redirect
+	end
+
+	it "alias RestClient::Request::Unauthorized to RestClient::Unauthorized" do
+		RestClient::Request::Unauthorized.should == RestClient::Unauthorized
+	end
+
+	it "alias RestClient::Request::RequestFailed to RestClient::RequestFailed" do
+		RestClient::Request::RequestFailed.should == RestClient::RequestFailed
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/master_shake.jpg
===================================================================
(Binary files differ)


Property changes on: branches/upstream/librestclient-ruby/current/spec/master_shake.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: branches/upstream/librestclient-ruby/current/spec/mixin/response_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/mixin/response_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/mixin/response_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,46 @@
+require File.dirname(__FILE__) + '/../base'
+
+class MockResponse
+	include RestClient::Mixin::Response
+
+	def initialize(body, res)
+		@net_http_res = res
+		@body = @body
+	end
+end
+
+describe RestClient::Mixin::Response do
+	before do
+		@net_http_res = mock('net http response')
+		@response = MockResponse.new('abc', @net_http_res)
+	end
+
+	it "fetches the numeric response code" do
+		@net_http_res.should_receive(:code).and_return('200')
+		@response.code.should == 200
+	end
+
+	it "beautifies the headers by turning the keys to symbols" do
+		h = RestClient::Response.beautify_headers('content-type' => [ 'x' ])
+		h.keys.first.should == :content_type
+	end
+
+	it "beautifies the headers by turning the values to strings instead of one-element arrays" do
+		h = RestClient::Response.beautify_headers('x' => [ 'text/html' ] )
+		h.values.first.should == 'text/html'
+	end
+
+	it "fetches the headers" do
+		@net_http_res.should_receive(:to_hash).and_return('content-type' => [ 'text/html' ])
+		@response.headers.should == { :content_type => 'text/html' }
+	end
+
+	it "extracts cookies from response headers" do
+		@net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
+		@response.cookies.should == { 'session_id' => '1' }
+	end
+
+	it "can access the net http result directly" do
+		@response.net_http_res.should == @net_http_res
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/payload_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/payload_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/payload_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,76 @@
+require File.dirname(__FILE__) + "/base"
+
+describe RestClient::Payload do
+	context "A regular Payload" do
+		it "should should default content-type to standard enctype" do
+			RestClient::Payload::UrlEncoded.new({}).headers['Content-Type'].
+				should == 'application/x-www-form-urlencoded'
+		end
+
+		it "should form properly encoded params" do
+			RestClient::Payload::UrlEncoded.new({:foo => 'bar'}).to_s.
+				should == "foo=bar"
+		end
+	end
+
+	context "A multipart Payload" do
+		it "should should default content-type to standard enctype" do
+			m = RestClient::Payload::Multipart.new({})
+			m.stub!(:boundary).and_return(123)
+			m.headers['Content-Type'].should == 'multipart/form-data; boundary="123"'
+		end
+
+		it "should form properly seperated multipart data" do
+			m = RestClient::Payload::Multipart.new({:foo => "bar", :bar => "baz"})
+			m.to_s.should == <<-EOS
+--#{m.boundary}\r
+Content-Disposition: multipart/form-data; name="bar"\r
+\r
+baz\r
+--#{m.boundary}\r
+Content-Disposition: multipart/form-data; name="foo"\r
+\r
+bar\r
+--#{m.boundary}--\r
+EOS
+		end
+
+		it "should form properly seperated multipart data" do
+			f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
+			m = RestClient::Payload::Multipart.new({:foo => f})
+			m.to_s.should == <<-EOS
+--#{m.boundary}\r
+Content-Disposition: multipart/form-data; name="foo"; filename="master_shake.jpg"\r
+Content-Type: image/jpeg\r
+\r
+#{IO.read(f.path)}\r
+--#{m.boundary}--\r
+EOS
+		end
+	end
+
+	context "Payload generation" do
+		it "should recognize standard urlencoded params" do
+			RestClient::Payload.generate({"foo" => 'bar'}).should be_kind_of(RestClient::Payload::UrlEncoded)
+		end
+		
+		it "should recognize multipart params" do
+			f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
+
+			RestClient::Payload.generate({"foo" => f}).should be_kind_of(RestClient::Payload::Multipart)
+		end
+		
+		it "should be multipart if forced" do
+			RestClient::Payload.generate({"foo" => "bar", :multipart => true}).should be_kind_of(RestClient::Payload::Multipart)
+		end
+
+		it "should return data if no of the above" do
+		  RestClient::Payload.generate("data").should be_kind_of(RestClient::Payload::Base)
+		end
+
+		it "should recognize nested multipart payloads" do
+			f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
+			RestClient::Payload.generate({"foo" => {"file" => f}}).should be_kind_of(RestClient::Payload::Multipart)
+		end
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/raw_response_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/raw_response_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/raw_response_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,17 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient::RawResponse do
+	before do
+		@tf = mock("Tempfile", :read => "the answer is 42", :open => true)
+		@net_http_res = mock('net http response')
+		@response = RestClient::RawResponse.new(@tf, @net_http_res)
+	end
+
+	it "behaves like string" do
+		@response.to_s.should == 'the answer is 42'
+	end
+
+	it "exposes a Tempfile" do
+		@response.file.should == @tf
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/request_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/request_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/request_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,484 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient::Request do
+	before do
+		@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
+
+		@uri = mock("uri")
+		@uri.stub!(:request_uri).and_return('/resource')
+		@uri.stub!(:host).and_return('some')
+		@uri.stub!(:port).and_return(80)
+
+		@net = mock("net::http base")
+		@http = mock("net::http connection")
+		Net::HTTP.stub!(:new).and_return(@net)
+		@net.stub!(:start).and_yield(@http)
+		@net.stub!(:use_ssl=)
+		@net.stub!(:verify_mode=)
+	end
+
+	it "accept */* mimetype, preferring xml" do
+		@request.default_headers[:accept].should == '*/*; q=0.5, application/xml'
+	end
+
+	it "decodes an uncompressed result body by passing it straight through" do
+		RestClient::Request.decode(nil, 'xyz').should == 'xyz'
+	end
+
+	it "decodes a gzip body" do
+		RestClient::Request.decode('gzip', "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000").should == "i'm gziped\n"
+	end
+
+	it "ingores gzip for empty bodies" do
+		RestClient::Request.decode('gzip', '').should be_empty
+	end
+
+	it "decodes a deflated body" do
+		RestClient::Request.decode('deflate', "x\234+\316\317MUHIM\313I,IMQ(I\255(\001\000A\223\006\363").should == "some deflated text"
+	end
+
+	it "processes a successful result" do
+		res = mock("result")
+		res.stub!(:code).and_return("200")
+		res.stub!(:body).and_return('body')
+		res.stub!(:[]).with('content-encoding').and_return(nil)
+		@request.process_result(res).should == 'body'
+	end
+
+	it "doesn't classify successful requests as failed" do
+		203.upto(206) do |code|
+			res = mock("result")
+			res.stub!(:code).and_return(code.to_s)
+			res.stub!(:body).and_return("")
+			res.stub!(:[]).with('content-encoding').and_return(nil)
+			@request.process_result(res).should be_empty
+		end
+	end
+
+	it "parses a url into a URI object" do
+		URI.should_receive(:parse).with('http://example.com/resource')
+		@request.parse_url('http://example.com/resource')
+	end
+
+	it "adds http:// to the front of resources specified in the syntax example.com/resource" do
+		URI.should_receive(:parse).with('http://example.com/resource')
+		@request.parse_url('example.com/resource')
+	end
+
+	it "extracts the username and password when parsing http://user:password@example.com/" do
+		URI.stub!(:parse).and_return(mock('uri', :user => 'joe', :password => 'pass1'))
+		@request.parse_url_with_auth('http://joe:pass1@example.com/resource')
+		@request.user.should == 'joe'
+		@request.password.should == 'pass1'
+	end
+
+	it "doesn't overwrite user and password (which may have already been set by the Resource constructor) if there is no user/password in the url" do
+		URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
+		@request = RestClient::Request.new(:method => 'get', :url => 'example.com', :user => 'beth', :password => 'pass2')
+		@request.parse_url_with_auth('http://example.com/resource')
+		@request.user.should == 'beth'
+		@request.password.should == 'pass2'
+	end
+
+	it "correctly formats cookies provided to the constructor" do
+		URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
+		@request = RestClient::Request.new(:method => 'get', :url => 'example.com', :cookies => {:session_id => '1' })
+		@request.should_receive(:default_headers).and_return({'foo' => 'bar'})
+		headers = @request.make_headers({}).should == { 'Foo' => 'bar', 'Cookie' => 'session_id=1'}
+	end
+
+	it "determines the Net::HTTP class to instantiate by the method name" do
+		@request.net_http_request_class(:put).should == Net::HTTP::Put
+	end
+
+	it "merges user headers with the default headers" do
+		@request.should_receive(:default_headers).and_return({ '1' => '2' })
+		headers = @request.make_headers('3' => '4')
+		headers.should have_key('1')
+		headers['1'].should == '2'
+		headers.should have_key('3')
+		headers['3'].should == '4'
+	end
+
+	it "prefers the user header when the same header exists in the defaults" do
+		@request.should_receive(:default_headers).and_return({ '1' => '2' })
+		headers = @request.make_headers('1' => '3')
+		headers.should have_key('1')
+		headers['1'].should == '3'
+	end
+
+	it "converts header symbols from :content_type to 'Content-type'" do
+		@request.should_receive(:default_headers).and_return({})
+		headers = @request.make_headers(:content_type => 'abc')
+		headers.should have_key('Content-type')
+		headers['Content-type'].should == 'abc'
+	end
+
+	it "converts header values to strings" do
+		@request.make_headers('A' => 1)['A'].should == '1'
+	end
+
+	it "executes by constructing the Net::HTTP object, headers, and payload and calling transmit" do
+		@request.should_receive(:parse_url_with_auth).with('http://some/resource').and_return(@uri)
+		klass = mock("net:http class")
+		@request.should_receive(:net_http_request_class).with(:put).and_return(klass)
+		klass.should_receive(:new).and_return('result')
+		@request.should_receive(:transmit).with(@uri, 'result', kind_of(RestClient::Payload::Base))
+		@request.execute_inner
+	end
+
+	it "transmits the request with Net::HTTP" do
+		@http.should_receive(:request).with('req', 'payload')
+		@request.should_receive(:process_result)
+		@request.should_receive(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "uses SSL when the URI refers to a https address" do
+		@uri.stub!(:is_a?).with(URI::HTTPS).and_return(true)
+		@net.should_receive(:use_ssl=).with(true)
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "sends nil payloads" do
+		@http.should_receive(:request).with('req', nil)
+		@request.should_receive(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', nil)
+	end
+
+	it "passes non-hash payloads straight through" do
+		@request.process_payload("x").should == "x"
+	end
+
+	it "converts a hash payload to urlencoded data" do
+		@request.process_payload(:a => 'b c+d').should == "a=b%20c%2Bd"
+	end
+
+	it "accepts nested hashes in payload" do
+		payload = @request.process_payload(:user => { :name => 'joe', :location => { :country => 'USA', :state => 'CA' }})
+		payload.should include('user[name]=joe')
+		payload.should include('user[location][country]=USA')
+		payload.should include('user[location][state]=CA')
+	end
+
+	it "set urlencoded content_type header on hash payloads" do
+		@request.process_payload(:a => 1)
+		@request.headers[:content_type].should == 'application/x-www-form-urlencoded'
+	end
+
+	it "sets up the credentials prior to the request" do
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+
+		@request.stub!(:user).and_return('joe')
+		@request.stub!(:password).and_return('mypass')
+		@request.should_receive(:setup_credentials).with('req')
+
+		@request.transmit(@uri, 'req', nil)
+	end
+
+	it "does not attempt to send any credentials if user is nil" do
+		@request.stub!(:user).and_return(nil)
+		req = mock("request")
+		req.should_not_receive(:basic_auth)
+		@request.setup_credentials(req)
+	end
+
+	it "setup credentials when there's a user" do
+		@request.stub!(:user).and_return('joe')
+		@request.stub!(:password).and_return('mypass')
+		req = mock("request")
+		req.should_receive(:basic_auth).with('joe', 'mypass')
+		@request.setup_credentials(req)
+	end
+
+	it "catches EOFError and shows the more informative ServerBrokeConnection" do
+		@http.stub!(:request).and_raise(EOFError)
+		lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::ServerBrokeConnection)
+	end
+
+	it "execute calls execute_inner" do
+		@request.should_receive(:execute_inner)
+		@request.execute
+	end
+
+	it "class method execute wraps constructor" do
+		req = mock("rest request")
+		RestClient::Request.should_receive(:new).with(1 => 2).and_return(req)
+		req.should_receive(:execute)
+		RestClient::Request.execute(1 => 2)
+	end
+
+	it "raises a Redirect with the new location when the response is in the 30x range" do
+		res = mock('response', :code => '301', :header => { 'Location' => 'http://new/resource' })
+		lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://new/resource'}
+	end
+
+	it "handles redirects with relative paths" do
+		res = mock('response', :code => '301', :header => { 'Location' => 'index' })
+		lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://some/index' }
+	end
+
+	it "handles redirects with absolute paths" do
+		@request.instance_variable_set('@url', 'http://some/place/else')
+		res = mock('response', :code => '301', :header => { 'Location' => '/index' })
+		lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://some/index' }
+	end
+
+	it "uses GET and clears payload when following 30x redirects" do
+		url = "http://example.com/redirected"
+
+		@request.should_receive(:execute_inner).once.ordered.and_raise(RestClient::Redirect.new(url))
+
+		@request.should_receive(:execute_inner).once.ordered do
+			@request.url.should == url
+			@request.method.should == :get
+			@request.payload.should be_nil
+		end
+
+		@request.execute
+	end
+
+	it "raises Unauthorized when the response is 401" do
+		res = mock('response', :code => '401')
+		lambda { @request.process_result(res) }.should raise_error(RestClient::Unauthorized)
+	end
+
+	it "raises ResourceNotFound when the response is 404" do
+		res = mock('response', :code => '404')
+		lambda { @request.process_result(res) }.should raise_error(RestClient::ResourceNotFound)
+	end
+
+	it "raises RequestFailed otherwise" do
+		res = mock('response', :code => '500')
+		lambda { @request.process_result(res) }.should raise_error(RestClient::RequestFailed)
+	end
+
+	it "creates a proxy class if a proxy url is given" do
+		RestClient.stub!(:proxy).and_return("http://example.com/")
+		@request.net_http_class.should include(Net::HTTP::ProxyDelta)
+	end
+
+	it "creates a non-proxy class if a proxy url is not given" do
+		@request.net_http_class.should_not include(Net::HTTP::ProxyDelta)
+	end
+
+	it "logs a get request" do
+		RestClient::Request.new(:method => :get, :url => 'http://url').request_log.should ==
+		'RestClient.get "http://url"'
+	end
+
+	it "logs a post request with a small payload" do
+		RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo').request_log.should ==
+		'RestClient.post "http://url", "foo"'
+	end
+
+	it "logs a post request with a large payload" do
+		RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).request_log.should ==
+		'RestClient.post "http://url", "(1000 byte payload)"'
+	end
+
+	it "logs input headers as a hash" do
+		RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain' }).request_log.should ==
+		'RestClient.get "http://url", :accept=>"text/plain"'
+	end
+
+	it "logs a response including the status code, content type, and result body size in bytes" do
+		res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
+		res.stub!(:[]).with('Content-type').and_return('text/html')
+		@request.response_log(res).should == "# => 200 OK | text/html 4 bytes"
+	end
+
+	it "logs a response with a nil Content-type" do
+		res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
+		res.stub!(:[]).with('Content-type').and_return(nil)
+		@request.response_log(res).should == "# => 200 OK |  4 bytes"
+	end
+
+	it "logs a response with a nil body" do
+		res = mock('result', :code => '200', :class => Net::HTTPOK, :body => nil)
+		res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
+		@request.response_log(res).should == "# => 200 OK | text/html 0 bytes"
+	end
+
+	it "strips the charset from the response content type" do
+		res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
+		res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
+		@request.response_log(res).should == "# => 200 OK | text/html 4 bytes"
+	end
+
+	it "displays the log to stdout" do
+		RestClient.stub!(:log).and_return('stdout')
+		STDOUT.should_receive(:puts).with('xyz')
+		@request.display_log('xyz')
+	end
+
+	it "displays the log to stderr" do
+		RestClient.stub!(:log).and_return('stderr')
+		STDERR.should_receive(:puts).with('xyz')
+		@request.display_log('xyz')
+	end
+
+	it "append the log to the requested filename" do
+		RestClient.stub!(:log).and_return('/tmp/restclient.log')
+		f = mock('file handle')
+		File.should_receive(:open).with('/tmp/restclient.log', 'a').and_yield(f)
+		f.should_receive(:puts).with('xyz')
+		@request.display_log('xyz')
+	end
+
+	it "set read_timeout" do
+		@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+
+		@net.should_receive(:read_timeout=).with(123)
+
+		@request.transmit(@uri, 'req', nil)
+	end
+
+	it "set open_timeout" do
+		@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+
+		@net.should_receive(:open_timeout=).with(123)
+
+		@request.transmit(@uri, 'req', nil)
+	end
+
+	it "should default to not verifying ssl certificates" do
+		@request.verify_ssl.should == false
+	end
+
+  it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
+    @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+    @http.stub!(:request)
+    @request.stub!(:process_result)
+    @request.stub!(:response_log)
+    @request.transmit(@uri, 'req', 'payload')
+  end
+
+	it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
+		@request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
+		@net.should_not_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+  it "should set net.verify_mode to the passed value if verify_ssl is an OpenSSL constant" do
+    mode     = OpenSSL::SSL::VERIFY_PEER |
+               OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
+		@request = RestClient::Request.new( :method     => :put,
+		                                    :url        => 'https://some/resource',
+		                                    :payload    => 'payload',
+		                                    :verify_ssl => mode )
+    @net.should_receive(:verify_mode=).with(mode)
+    @http.stub!(:request)
+    @request.stub!(:process_result)
+    @request.stub!(:response_log)
+    @request.transmit(@uri, 'req', 'payload')
+  end
+
+	it "should default to not having an ssl_client_cert" do
+		@request.ssl_client_cert.should be(nil)
+	end
+
+	it "should set the ssl_client_cert if provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload',
+			:ssl_client_cert => "whatsupdoc!"
+		)
+		@net.should_receive(:cert=).with("whatsupdoc!")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "should not set the ssl_client_cert if it is not provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload'
+		)
+		@net.should_not_receive(:cert=).with("whatsupdoc!")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "should default to not having an ssl_client_key" do
+		@request.ssl_client_key.should be(nil)
+	end
+
+	it "should set the ssl_client_key if provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload',
+			:ssl_client_key => "whatsupdoc!"
+		)
+		@net.should_receive(:key=).with("whatsupdoc!")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "should not set the ssl_client_key if it is not provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload'
+		)
+		@net.should_not_receive(:key=).with("whatsupdoc!")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+	
+	it "should default to not having an ssl_ca_file" do
+		@request.ssl_ca_file.should be(nil)
+	end
+
+	it "should set the ssl_ca_file if provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload',
+			:ssl_ca_file => "Certificate Authority File"
+		)
+		@net.should_receive(:ca_file=).with("Certificate Authority File")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+
+	it "should not set the ssl_ca_file if it is not provided" do
+		@request = RestClient::Request.new(
+			:method => :put, 
+			:url => 'https://some/resource', 
+			:payload => 'payload'
+		)
+		@net.should_not_receive(:ca_file=).with("Certificate Authority File")
+		@http.stub!(:request)
+		@request.stub!(:process_result)
+		@request.stub!(:response_log)
+		@request.transmit(@uri, 'req', 'payload')
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/resource_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/resource_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/resource_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,75 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient::Resource do
+	before do
+		@resource = RestClient::Resource.new('http://some/resource', :user => 'jane', :password => 'mypass', :headers => { 'X-Something' => '1'})
+	end
+
+	context "Resource delegation" do
+		it "GET" do
+			RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => { 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
+			@resource.get
+		end
+
+		it "POST" do
+			RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
+			@resource.post 'abc', :content_type => 'image/jpg'
+		end
+
+		it "PUT" do
+			RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
+			@resource.put 'abc', :content_type => 'image/jpg'
+		end
+
+		it "DELETE" do
+			RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => { 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
+			@resource.delete
+		end
+
+		it "overrides resource headers" do
+			RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => { 'X-Something' => '2'}, :user => 'jane', :password => 'mypass')
+			@resource.get 'X-Something' => '2'
+		end
+	end
+
+	it "can instantiate with no user/password" do
+		@resource = RestClient::Resource.new('http://some/resource')
+	end
+
+	it "is backwards compatible with previous constructor" do
+		@resource = RestClient::Resource.new('http://some/resource', 'user', 'pass')
+		@resource.user.should == 'user'
+		@resource.password.should == 'pass'
+	end
+
+	it "concatinates urls, inserting a slash when it needs one" do
+		@resource.concat_urls('http://example.com', 'resource').should == 'http://example.com/resource'
+	end
+
+	it "concatinates urls, using no slash if the first url ends with a slash" do
+		@resource.concat_urls('http://example.com/', 'resource').should == 'http://example.com/resource'
+	end
+
+	it "concatinates urls, using no slash if the second url starts with a slash" do
+		@resource.concat_urls('http://example.com', '/resource').should == 'http://example.com/resource'
+	end
+
+	it "concatinates even non-string urls, :posts + 1 => 'posts/1'" do
+		@resource.concat_urls(:posts, 1).should == 'posts/1'
+	end
+
+	it "offers subresources via []" do
+		parent = RestClient::Resource.new('http://example.com')
+		parent['posts'].url.should == 'http://example.com/posts'
+	end
+
+	it "transports options to subresources" do
+		parent = RestClient::Resource.new('http://example.com', :user => 'user', :password => 'password')
+		parent['posts'].user.should == 'user'
+		parent['posts'].password.should == 'password'
+	end
+
+	it "prints its url with to_s" do
+		RestClient::Resource.new('x').to_s.should == 'x'
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/response_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/response_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/response_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,16 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient::Response do
+	before do
+		@net_http_res = mock('net http response')
+		@response = RestClient::Response.new('abc', @net_http_res)
+	end
+
+	it "behaves like string" do
+		@response.should == 'abc'
+	end
+
+	it "accepts nil strings and sets it to empty for the case of HEAD" do
+		RestClient::Response.new(nil, @net_http_res).should == ""
+	end
+end

Added: branches/upstream/librestclient-ruby/current/spec/restclient_spec.rb
===================================================================
--- branches/upstream/librestclient-ruby/current/spec/restclient_spec.rb	                        (rev 0)
+++ branches/upstream/librestclient-ruby/current/spec/restclient_spec.rb	2009-12-12 16:52:10 UTC (rev 4441)
@@ -0,0 +1,53 @@
+require File.dirname(__FILE__) + '/base'
+
+describe RestClient do
+	describe "API" do
+		it "GET" do
+			RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {})
+			RestClient.get('http://some/resource')
+		end
+
+		it "POST" do
+			RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'payload', :headers => {})
+			RestClient.post('http://some/resource', 'payload')
+		end
+
+		it "PUT" do
+			RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'payload', :headers => {})
+			RestClient.put('http://some/resource', 'payload')
+		end
+
+		it "DELETE" do
+			RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {})
+			RestClient.delete('http://some/resource')
+		end
+
+		it "HEAD" do
+			RestClient::Request.should_receive(:execute).with(:method => :head, :url => 'http://some/resource', :headers => {})
+			RestClient.head('http://some/resource')
+		end
+	end
+
+	describe "logging" do
+		after do
+			RestClient.log = nil
+		end
+
+		it "gets the log source from the RESTCLIENT_LOG environment variable" do
+			ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return('from env')
+			RestClient.log = 'from class method'
+			RestClient.log.should == 'from env'
+		end
+
+		it "sets a destination for log output, used if no environment variable is set" do
+			ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return(nil)
+			RestClient.log = 'from class method'
+			RestClient.log.should == 'from class method'
+		end
+
+		it "returns nil (no logging) if neither are set (default)" do
+			ENV.stub!(:[]).with('RESTCLIENT_LOG').and_return(nil)
+			RestClient.log.should == nil
+		end
+	end
+end




More information about the Pkg-ruby-extras-commits mailing list