sevenwire-rest-client 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +151 -0
 - data/Rakefile +48 -0
 - data/VERSION.yml +4 -0
 - data/bin/restclient +82 -0
 - data/lib/rest_client.rb +2 -0
 - data/lib/restclient/exceptions.rb +34 -0
 - data/lib/restclient/mixin/response.rb +43 -0
 - data/lib/restclient/raw_response.rb +30 -0
 - data/lib/restclient/request.rb +232 -0
 - data/lib/restclient/resource.rb +146 -0
 - data/lib/restclient/response.rb +20 -0
 - data/lib/restclient.rb +93 -0
 - data/spec/base.rb +4 -0
 - data/spec/exceptions_spec.rb +12 -0
 - data/spec/mixin/response_spec.rb +46 -0
 - data/spec/raw_response_spec.rb +17 -0
 - data/spec/request_spec.rb +442 -0
 - data/spec/resource_spec.rb +75 -0
 - data/spec/response_spec.rb +16 -0
 - data/spec/restclient_spec.rb +53 -0
 - metadata +79 -0
 
    
        data/README.rdoc
    ADDED
    
    | 
         @@ -0,0 +1,151 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            = REST Client -- simple DSL for accessing REST resources
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            A simple REST client for Ruby, inspired by the Sinatra's microframework style
         
     | 
| 
      
 4 
     | 
    
         
            +
            of specifying actions: get, put, post, delete.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            == Usage: Raw URL
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              require 'rest_client'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              RestClient.get 'http://example.com/resource'
         
     | 
| 
      
 11 
     | 
    
         
            +
              RestClient.get 'https://user:password@example.com/private/resource'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              RestClient.delete 'http://example.com/resource'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            See RestClient module docs for details.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            == Usage: ActiveResource-Style
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              resource = RestClient::Resource.new 'http://example.com/resource'
         
     | 
| 
      
 22 
     | 
    
         
            +
              resource.get
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              private_resource = RestClient::Resource.new 'https://example.com/private/resource', :user => 'adam', :password => 'secret', :timeout => 20, :open_timeout => 5
         
     | 
| 
      
 25 
     | 
    
         
            +
              private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            See RestClient::Resource module docs for details.
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            == Usage: Resource Nesting
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              site = RestClient::Resource.new('http://example.com')
         
     | 
| 
      
 32 
     | 
    
         
            +
              site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            See RestClient::Resource docs for details.
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            == Shell
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            The restclient shell command gives an IRB session with RestClient already loaded:
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              $ restclient
         
     | 
| 
      
 41 
     | 
    
         
            +
              >> RestClient.get 'http://example.com'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            Specify a URL argument for get/post/put/delete on that resource:
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              $ restclient http://example.com
         
     | 
| 
      
 46 
     | 
    
         
            +
              >> put '/resource', 'data'
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            Add a user and password for authenticated resources:
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              $ restclient https://example.com user pass
         
     | 
| 
      
 51 
     | 
    
         
            +
              >> delete '/private/resource'
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            Create ~/.restclient for named sessions:
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              sinatra:
         
     | 
| 
      
 56 
     | 
    
         
            +
                url: http://localhost:4567
         
     | 
| 
      
 57 
     | 
    
         
            +
              rack:
         
     | 
| 
      
 58 
     | 
    
         
            +
                url: http://localhost:9292
         
     | 
| 
      
 59 
     | 
    
         
            +
              private_site:
         
     | 
| 
      
 60 
     | 
    
         
            +
                url: http://example.com
         
     | 
| 
      
 61 
     | 
    
         
            +
                username: user
         
     | 
| 
      
 62 
     | 
    
         
            +
                password: pass
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            Then invoke:
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              $ restclient private_site
         
     | 
| 
      
 67 
     | 
    
         
            +
              
         
     | 
| 
      
 68 
     | 
    
         
            +
            Use as a one-off, curl-style:
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              $ restclient get http://example.com/resource > output_body
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              $ restclient put http://example.com/resource < input_body
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            == Logging
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            Write calls to a log filename (can also be "stdout" or "stderr"):
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              RestClient.log = '/tmp/restclient.log'
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            Or set an environment variable to avoid modifying the code:
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              $ RESTCLIENT_LOG=stdout path/to/my/program
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            Either produces logs like this:
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              RestClient.get "http://some/resource"
         
     | 
| 
      
 87 
     | 
    
         
            +
              # => 200 OK | text/html 250 bytes
         
     | 
| 
      
 88 
     | 
    
         
            +
              RestClient.put "http://some/resource", "payload"
         
     | 
| 
      
 89 
     | 
    
         
            +
              # => 401 Unauthorized | application/xml 340 bytes
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            Note that these logs are valid Ruby, so you can paste them into the restclient
         
     | 
| 
      
 92 
     | 
    
         
            +
            shell or a script to replay your sequence of rest calls.
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            == Proxy
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            All calls to RestClient, including Resources, will use the proxy specified by
         
     | 
| 
      
 97 
     | 
    
         
            +
            RestClient.proxy:
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
              RestClient.proxy = "http://proxy.example.com/"
         
     | 
| 
      
 100 
     | 
    
         
            +
              RestClient.get "http://some/resource"
         
     | 
| 
      
 101 
     | 
    
         
            +
              # => response from some/resource as proxied through proxy.example.com
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            Often the proxy url is set in an environment variable, so you can do this to
         
     | 
| 
      
 104 
     | 
    
         
            +
            use whatever proxy the system is configured to use:
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
              RestClient.proxy = ENV['http_proxy']
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            == Cookies
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            Request and Response objects know about HTTP cookies, and will automatically
         
     | 
| 
      
 111 
     | 
    
         
            +
            extract and set headers for them as needed:
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              response = RestClient.get 'http://example.com/action_which_sets_session_id'
         
     | 
| 
      
 114 
     | 
    
         
            +
              response.cookies
         
     | 
| 
      
 115 
     | 
    
         
            +
              # => {"_applicatioN_session_id" => "1234"}
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              response2 = RestClient.post(
         
     | 
| 
      
 118 
     | 
    
         
            +
                'http://localhost:3000/',
         
     | 
| 
      
 119 
     | 
    
         
            +
                {:param1 => "foo"},
         
     | 
| 
      
 120 
     | 
    
         
            +
                {:cookies => {:session_id => "1234"}}
         
     | 
| 
      
 121 
     | 
    
         
            +
              )
         
     | 
| 
      
 122 
     | 
    
         
            +
              # ...response body
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            == SSL Client Certificates
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              RestClient::Resource.new(
         
     | 
| 
      
 127 
     | 
    
         
            +
                'https://example.com', 
         
     | 
| 
      
 128 
     | 
    
         
            +
                :ssl_client_cert  =>  OpenSSL::X509::Certificate.new(File.read("cert.pem")), 
         
     | 
| 
      
 129 
     | 
    
         
            +
                :ssl_client_key   =>  OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
         
     | 
| 
      
 130 
     | 
    
         
            +
                :ssl_ca_file      =>  "ca_certificate.pem", 
         
     | 
| 
      
 131 
     | 
    
         
            +
                :verify_ssl       =>  OpenSSL::SSL::VERIFY_PEER 
         
     | 
| 
      
 132 
     | 
    
         
            +
              ).get
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            Self-signed certificates can be generated with the openssl command-line tool.
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            == Meta
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            Written by Adam Wiggins (adam at heroku dot com)
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            Patches contributed by: Chris Anderson, Greg Borenstein, Ardekantur, Pedro
         
     | 
| 
      
 141 
     | 
    
         
            +
            Belo, Rafael Souza, Rick Olson, Aman Gupta, Blake Mizerany, Brian Donovan, Ivan
         
     | 
| 
      
 142 
     | 
    
         
            +
            Makfinsky, Marc-André Cournoyer, Coda Hale, Tetsuo Watanabe, Dusty Doris,
         
     | 
| 
      
 143 
     | 
    
         
            +
            Lennon Day-Reynolds, James Edward Gray II, Cyril Rohr, Juan Alvarez, and Adam
         
     | 
| 
      
 144 
     | 
    
         
            +
            Jacob
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            http://rest-client.heroku.com
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
            http://github.com/adamwiggins/rest-client
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            begin
         
     | 
| 
      
 5 
     | 
    
         
            +
              require 'jeweler'
         
     | 
| 
      
 6 
     | 
    
         
            +
              Jeweler::Tasks.new do |gem|
         
     | 
| 
      
 7 
     | 
    
         
            +
                gem.name = "rest-client"
         
     | 
| 
      
 8 
     | 
    
         
            +
                gem.summary = %Q{Simple REST client for Ruby, inspired by microframework syntax for specifying actions.}
         
     | 
| 
      
 9 
     | 
    
         
            +
                gem.email = "adam@heroku.com"
         
     | 
| 
      
 10 
     | 
    
         
            +
                gem.homepage = "http://rest-client.heroku.com/"
         
     | 
| 
      
 11 
     | 
    
         
            +
                gem.authors = ["Adam Wiggins"]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 16 
     | 
    
         
            +
              puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            require 'spec/rake/spectask'
         
     | 
| 
      
 20 
     | 
    
         
            +
            Spec::Rake::SpecTask.new(:spec) do |spec|
         
     | 
| 
      
 21 
     | 
    
         
            +
              spec.libs << 'lib' << 'spec'
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.spec_files = FileList['spec/**/*_spec.rb']
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            Spec::Rake::SpecTask.new(:rcov) do |spec|
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.libs << 'lib' << 'spec'
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.pattern = 'spec/**/*_spec.rb'
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.rcov = true
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            task :default => :spec
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            require 'rake/rdoctask'
         
     | 
| 
      
 35 
     | 
    
         
            +
            Rake::RDocTask.new do |rdoc|
         
     | 
| 
      
 36 
     | 
    
         
            +
              if File.exist?('VERSION.yml')
         
     | 
| 
      
 37 
     | 
    
         
            +
                config = YAML.load(File.read('VERSION.yml'))
         
     | 
| 
      
 38 
     | 
    
         
            +
                version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
         
     | 
| 
      
 39 
     | 
    
         
            +
              else
         
     | 
| 
      
 40 
     | 
    
         
            +
                version = ""
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              rdoc.rdoc_dir = 'rdoc'
         
     | 
| 
      
 44 
     | 
    
         
            +
              rdoc.title = "rest-client #{version}"
         
     | 
| 
      
 45 
     | 
    
         
            +
              rdoc.rdoc_files.include('README*')
         
     | 
| 
      
 46 
     | 
    
         
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
    
        data/VERSION.yml
    ADDED
    
    
    
        data/bin/restclient
    ADDED
    
    | 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            $:.unshift File.dirname(__FILE__) + "/../lib"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'restclient'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require "yaml"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            def usage(why = nil)
         
     | 
| 
      
 9 
     | 
    
         
            +
              puts "failed for reason: #{why}" if why
         
     | 
| 
      
 10 
     | 
    
         
            +
              puts "usage: restclient [get|put|post|delete] url|name [username] [password]"
         
     | 
| 
      
 11 
     | 
    
         
            +
              puts "  The verb is optional, if you leave it off you'll get an interactive shell."
         
     | 
| 
      
 12 
     | 
    
         
            +
              puts "  put and post both take the input body on stdin."
         
     | 
| 
      
 13 
     | 
    
         
            +
              exit(1)
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            if %w(get put post delete).include? ARGV.first
         
     | 
| 
      
 17 
     | 
    
         
            +
              @verb = ARGV.shift
         
     | 
| 
      
 18 
     | 
    
         
            +
            else
         
     | 
| 
      
 19 
     | 
    
         
            +
              @verb = nil
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            @url = ARGV.shift || 'http://localhost:4567'
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            config = YAML.load(File.read(ENV['HOME'] + "/.restclient")) rescue {}
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            @url, @username, @password = if c = config[@url]
         
     | 
| 
      
 27 
     | 
    
         
            +
              [c['url'], c['username'], c['password']]
         
     | 
| 
      
 28 
     | 
    
         
            +
            else
         
     | 
| 
      
 29 
     | 
    
         
            +
              [@url, *ARGV]
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            usage("invalid url '#{@url}") unless @url =~ /^https?/
         
     | 
| 
      
 33 
     | 
    
         
            +
            usage("too few args") unless ARGV.size < 3
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            def r
         
     | 
| 
      
 36 
     | 
    
         
            +
              @r ||= RestClient::Resource.new(@url, @username, @password)
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            r # force rc to load
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            if @verb
         
     | 
| 
      
 42 
     | 
    
         
            +
              begin
         
     | 
| 
      
 43 
     | 
    
         
            +
                if %w(put post).include? @verb
         
     | 
| 
      
 44 
     | 
    
         
            +
                  puts r.send(@verb, STDIN.read)
         
     | 
| 
      
 45 
     | 
    
         
            +
                else
         
     | 
| 
      
 46 
     | 
    
         
            +
                  puts r.send(@verb)
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
                exit 0
         
     | 
| 
      
 49 
     | 
    
         
            +
              rescue RestClient::Exception => e
         
     | 
| 
      
 50 
     | 
    
         
            +
                puts e.response.body if e.respond_to? :response
         
     | 
| 
      
 51 
     | 
    
         
            +
                raise
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            %w(get post put delete).each do |m|
         
     | 
| 
      
 56 
     | 
    
         
            +
             eval <<-end_eval
         
     | 
| 
      
 57 
     | 
    
         
            +
            def #{m}(path, *args, &b)
         
     | 
| 
      
 58 
     | 
    
         
            +
              r[path].#{m}(*args, &b)
         
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
| 
      
 60 
     | 
    
         
            +
             end_eval
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            def method_missing(s, *args, &b)
         
     | 
| 
      
 64 
     | 
    
         
            +
              super unless r.respond_to?(s)
         
     | 
| 
      
 65 
     | 
    
         
            +
              r.send(s, *args, &b)
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            require 'irb'
         
     | 
| 
      
 69 
     | 
    
         
            +
            require 'irb/completion'
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            if File.exists? ".irbrc"
         
     | 
| 
      
 72 
     | 
    
         
            +
              ENV['IRBRC'] = ".irbrc"
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            if File.exists?(rcfile = "~/.restclientrc")
         
     | 
| 
      
 76 
     | 
    
         
            +
              load(rcfile)
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            ARGV.clear
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            IRB.start
         
     | 
| 
      
 82 
     | 
    
         
            +
            exit!
         
     | 
    
        data/lib/rest_client.rb
    ADDED
    
    
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RestClient
         
     | 
| 
      
 2 
     | 
    
         
            +
              # This is the base RestClient exception class. Rescue it if you want to
         
     | 
| 
      
 3 
     | 
    
         
            +
              # catch any exception that your request might raise
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Exception < RuntimeError
         
     | 
| 
      
 5 
     | 
    
         
            +
                def message(default=nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  self.class::ErrorMessage
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # Base RestClient exception when there's a response available
         
     | 
| 
      
 11 
     | 
    
         
            +
              class ExceptionWithResponse < Exception
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :response
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(response=nil)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @response = response
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def http_code
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @response.code.to_i if @response
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # The server broke the connection prior to the request completing.  Usually
         
     | 
| 
      
 24 
     | 
    
         
            +
              # this means it crashed, or sometimes that your network connection was
         
     | 
| 
      
 25 
     | 
    
         
            +
              # severed before it could complete.
         
     | 
| 
      
 26 
     | 
    
         
            +
              class ServerBrokeConnection < Exception
         
     | 
| 
      
 27 
     | 
    
         
            +
                ErrorMessage = 'Server broke connection'
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              # The server took too long to respond.
         
     | 
| 
      
 31 
     | 
    
         
            +
              class RequestTimeout < Exception
         
     | 
| 
      
 32 
     | 
    
         
            +
                ErrorMessage = 'Request timed out'
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RestClient
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Mixin
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Response
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :net_http_res
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  # HTTP status code, always 200 since RestClient throws exceptions for
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # other codes.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def code
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @code ||= @net_http_res.code.to_i
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  # A hash of the headers, beautified with symbols and underscores.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # e.g. "Content-type" will become :content_type.
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def headers
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @headers ||= self.class.beautify_headers(@net_http_res.to_hash)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  # Hash of cookies extracted from response headers
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def cookies
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @cookies ||= (self.headers[:set_cookie] || "").split('; ').inject({}) do |out, raw_c|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      key, val = raw_c.split('=')
         
     | 
| 
      
 22 
     | 
    
         
            +
                      unless %w(expires domain path secure).member?(key)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        out[key] = val
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
                      out
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def self.included(receiver)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    receiver.extend(RestClient::Mixin::Response::ClassMethods)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 34 
     | 
    
         
            +
                    def beautify_headers(headers)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      headers.inject({}) do |out, (key, value)|
         
     | 
| 
      
 36 
     | 
    
         
            +
                        out[key.gsub(/-/, '_').to_sym] = value.first
         
     | 
| 
      
 37 
     | 
    
         
            +
                      out
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/mixin/response'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RestClient
         
     | 
| 
      
 4 
     | 
    
         
            +
              # The response from RestClient on a raw request looks like a string, but is 
         
     | 
| 
      
 5 
     | 
    
         
            +
              # actually one of these.  99% of the time you're making a rest call all you 
         
     | 
| 
      
 6 
     | 
    
         
            +
              # care about is the body, but on the occassion you want to fetch the 
         
     | 
| 
      
 7 
     | 
    
         
            +
              # headers you can:
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   RestClient.get('http://example.com').headers[:content_type]
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              # In addition, if you do not use the response as a string, you can access
         
     | 
| 
      
 12 
     | 
    
         
            +
              # a Tempfile object at res.file, which contains the path to the raw 
         
     | 
| 
      
 13 
     | 
    
         
            +
              # downloaded request body.  
         
     | 
| 
      
 14 
     | 
    
         
            +
              class RawResponse 
         
     | 
| 
      
 15 
     | 
    
         
            +
                include RestClient::Mixin::Response
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                attr_reader :file
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def initialize(tempfile, net_http_res)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @net_http_res = net_http_res
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @file = tempfile
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @file.open
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @file.read
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,232 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'tempfile'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RestClient
         
     | 
| 
      
 4 
     | 
    
         
            +
              # This class is used internally by RestClient to send the request, but you can also
         
     | 
| 
      
 5 
     | 
    
         
            +
              # access it internally if you'd like to use a method not directly supported by the
         
     | 
| 
      
 6 
     | 
    
         
            +
              # main API.  For example:
         
     | 
| 
      
 7 
     | 
    
         
            +
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              #   RestClient::Request.execute(:method => :head, :url => 'http://example.com')
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Request
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_reader :method, :url, :payload, :headers,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :cookies, :user, :password, :timeout, :open_timeout,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  :verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  :raw_response
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def self.execute(args)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  new(args).execute
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def initialize(args)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @method = args[:method] or raise ArgumentError, "must pass :method"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @url = args[:url] or raise ArgumentError, "must pass :url"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @headers = args[:headers] || {}
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @cookies = @headers.delete(:cookies) || args[:cookies] || {}
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @payload = process_payload(args[:payload])
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @user = args[:user]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @password = args[:password]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @timeout = args[:timeout]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @open_timeout = args[:open_timeout]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @raw_response = args[:raw_response] || false
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @verify_ssl = args[:verify_ssl] || false
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @ssl_client_cert = args[:ssl_client_cert] || nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @ssl_client_key  = args[:ssl_client_key] || nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @ssl_ca_file = args[:ssl_ca_file] || nil
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @tf = nil # If you are a raw request, this is your tempfile
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def execute
         
     | 
| 
      
 39 
     | 
    
         
            +
                  execute_inner
         
     | 
| 
      
 40 
     | 
    
         
            +
                rescue Redirect => e
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @url = e.url
         
     | 
| 
      
 42 
     | 
    
         
            +
                  execute
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def execute_inner
         
     | 
| 
      
 46 
     | 
    
         
            +
                  uri = parse_url_with_auth(url)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  transmit uri, net_http_request_class(method).new(uri.request_uri, make_headers(headers)), payload
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def make_headers(user_headers)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  unless @cookies.empty?
         
     | 
| 
      
 52 
     | 
    
         
            +
                    user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  default_headers.merge(user_headers).inject({}) do |final, (key, value)|
         
     | 
| 
      
 56 
     | 
    
         
            +
                    final[key.to_s.gsub(/_/, '-').capitalize] = value.to_s
         
     | 
| 
      
 57 
     | 
    
         
            +
                  final
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def net_http_class
         
     | 
| 
      
 62 
     | 
    
         
            +
                  if RestClient.proxy
         
     | 
| 
      
 63 
     | 
    
         
            +
                    proxy_uri = URI.parse(RestClient.proxy)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  else
         
     | 
| 
      
 66 
     | 
    
         
            +
                    Net::HTTP
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def net_http_request_class(method)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  Net::HTTP.const_get(method.to_s.capitalize)
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def parse_url(url)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  url = "http://#{url}" unless url.match(/^http/)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  URI.parse(url)
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def parse_url_with_auth(url)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  uri = parse_url(url)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  @user = uri.user if uri.user
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @password = uri.password if uri.password
         
     | 
| 
      
 83 
     | 
    
         
            +
                  uri
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def process_payload(p=nil, parent_key=nil)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  unless p.is_a?(Hash)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    p
         
     | 
| 
      
 89 
     | 
    
         
            +
                  else
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @headers[:content_type] ||= 'application/x-www-form-urlencoded'
         
     | 
| 
      
 91 
     | 
    
         
            +
                    p.keys.map do |k|
         
     | 
| 
      
 92 
     | 
    
         
            +
                      key = parent_key ? "#{parent_key}[#{k}]" : k
         
     | 
| 
      
 93 
     | 
    
         
            +
                      if p[k].is_a? Hash
         
     | 
| 
      
 94 
     | 
    
         
            +
                        process_payload(p[k], key)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      else
         
     | 
| 
      
 96 
     | 
    
         
            +
                        value = URI.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
         
     | 
| 
      
 97 
     | 
    
         
            +
                        "#{key}=#{value}"
         
     | 
| 
      
 98 
     | 
    
         
            +
                      end
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end.join("&")
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                def transmit(uri, req, payload)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  setup_credentials(req)
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  net = net_http_class.new(uri.host, uri.port)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  net.use_ssl = uri.is_a?(URI::HTTPS)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  net.verify_mode = OpenSSL::SSL::VERIFY_NONE if @verify_ssl == false
         
     | 
| 
      
 109 
     | 
    
         
            +
                  net.cert = @ssl_client_cert if @ssl_client_cert
         
     | 
| 
      
 110 
     | 
    
         
            +
                  net.key = @ssl_client_key if @ssl_client_key
         
     | 
| 
      
 111 
     | 
    
         
            +
                  net.ca_file = @ssl_ca_file if @ssl_ca_file
         
     | 
| 
      
 112 
     | 
    
         
            +
                  net.read_timeout = @timeout if @timeout
         
     | 
| 
      
 113 
     | 
    
         
            +
                  net.open_timeout = @open_timeout if @open_timeout
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  display_log request_log
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  net.start do |http|
         
     | 
| 
      
 118 
     | 
    
         
            +
                    res = http.request(req, payload) { |http_response| fetch_body(http_response) }
         
     | 
| 
      
 119 
     | 
    
         
            +
                    result = process_result(res)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    display_log response_log(res)
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    if result.kind_of?(String) or @method == :head
         
     | 
| 
      
 123 
     | 
    
         
            +
                      Response.new(result, res)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    elsif @raw_response
         
     | 
| 
      
 125 
     | 
    
         
            +
                      RawResponse.new(@tf, res)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    else
         
     | 
| 
      
 127 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
                rescue EOFError
         
     | 
| 
      
 131 
     | 
    
         
            +
                  raise RestClient::ServerBrokeConnection
         
     | 
| 
      
 132 
     | 
    
         
            +
                rescue Timeout::Error
         
     | 
| 
      
 133 
     | 
    
         
            +
                  raise RestClient::RequestTimeout
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                def setup_credentials(req)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  req.basic_auth(user, password) if user
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                def fetch_body(http_response)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  if @raw_response
         
     | 
| 
      
 142 
     | 
    
         
            +
                    # Taken from Chef, which as in turn...
         
     | 
| 
      
 143 
     | 
    
         
            +
                    # Stolen from http://www.ruby-forum.com/topic/166423
         
     | 
| 
      
 144 
     | 
    
         
            +
                    # Kudos to _why!
         
     | 
| 
      
 145 
     | 
    
         
            +
                    @tf = Tempfile.new("rest-client") 
         
     | 
| 
      
 146 
     | 
    
         
            +
                    size, total = 0, http_response.header['Content-Length'].to_i
         
     | 
| 
      
 147 
     | 
    
         
            +
                    http_response.read_body do |chunk|
         
     | 
| 
      
 148 
     | 
    
         
            +
                      @tf.write(chunk) 
         
     | 
| 
      
 149 
     | 
    
         
            +
                      size += chunk.size
         
     | 
| 
      
 150 
     | 
    
         
            +
                      if size == 0
         
     | 
| 
      
 151 
     | 
    
         
            +
                        display_log("#{@method} #{@url} done (0 length file)")
         
     | 
| 
      
 152 
     | 
    
         
            +
                      elsif total == 0
         
     | 
| 
      
 153 
     | 
    
         
            +
                        display_log("#{@method} #{@url} (zero content length)")
         
     | 
| 
      
 154 
     | 
    
         
            +
                      else
         
     | 
| 
      
 155 
     | 
    
         
            +
                        display_log("#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total])
         
     | 
| 
      
 156 
     | 
    
         
            +
                      end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    @tf.close
         
     | 
| 
      
 159 
     | 
    
         
            +
                    @tf
         
     | 
| 
      
 160 
     | 
    
         
            +
                  else
         
     | 
| 
      
 161 
     | 
    
         
            +
                    http_response.read_body
         
     | 
| 
      
 162 
     | 
    
         
            +
                  end
         
     | 
| 
      
 163 
     | 
    
         
            +
                  http_response
         
     | 
| 
      
 164 
     | 
    
         
            +
                end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                def process_result(res)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  if res.code =~ /\A2\d{2}\z/ 
         
     | 
| 
      
 168 
     | 
    
         
            +
                    # We don't decode raw requests
         
     | 
| 
      
 169 
     | 
    
         
            +
                    unless @raw_response
         
     | 
| 
      
 170 
     | 
    
         
            +
                      decode res['content-encoding'], res.body if res.body
         
     | 
| 
      
 171 
     | 
    
         
            +
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
                  elsif %w(301 302 303).include? res.code
         
     | 
| 
      
 173 
     | 
    
         
            +
                    url = res.header['Location']
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                    if url !~ /^http/
         
     | 
| 
      
 176 
     | 
    
         
            +
                      uri = URI.parse(@url)
         
     | 
| 
      
 177 
     | 
    
         
            +
                      uri.path = "/#{url}".squeeze('/')
         
     | 
| 
      
 178 
     | 
    
         
            +
                      url = uri.to_s
         
     | 
| 
      
 179 
     | 
    
         
            +
                    end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                    "Redirected to: #{url}"
         
     | 
| 
      
 182 
     | 
    
         
            +
                  elsif res.code == "304"
         
     | 
| 
      
 183 
     | 
    
         
            +
                    "Not Modified"
         
     | 
| 
      
 184 
     | 
    
         
            +
                  elsif res.code == "401"
         
     | 
| 
      
 185 
     | 
    
         
            +
                    "Unauthorized"
         
     | 
| 
      
 186 
     | 
    
         
            +
                  elsif res.code == "404"
         
     | 
| 
      
 187 
     | 
    
         
            +
                    "Not Found"
         
     | 
| 
      
 188 
     | 
    
         
            +
                  else
         
     | 
| 
      
 189 
     | 
    
         
            +
                    "Failed"
         
     | 
| 
      
 190 
     | 
    
         
            +
                  end
         
     | 
| 
      
 191 
     | 
    
         
            +
                end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                def decode(content_encoding, body)
         
     | 
| 
      
 194 
     | 
    
         
            +
                  if content_encoding == 'gzip' and not body.empty?
         
     | 
| 
      
 195 
     | 
    
         
            +
                    Zlib::GzipReader.new(StringIO.new(body)).read
         
     | 
| 
      
 196 
     | 
    
         
            +
                  elsif content_encoding == 'deflate'
         
     | 
| 
      
 197 
     | 
    
         
            +
                    Zlib::Inflate.new.inflate(body)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  else
         
     | 
| 
      
 199 
     | 
    
         
            +
                    body
         
     | 
| 
      
 200 
     | 
    
         
            +
                  end
         
     | 
| 
      
 201 
     | 
    
         
            +
                end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                def request_log
         
     | 
| 
      
 204 
     | 
    
         
            +
                  out = []
         
     | 
| 
      
 205 
     | 
    
         
            +
                  out << "RestClient.#{method} #{url.inspect}"
         
     | 
| 
      
 206 
     | 
    
         
            +
                  out << (payload.size > 100 ? "(#{payload.size} byte payload)".inspect : payload.inspect) if payload
         
     | 
| 
      
 207 
     | 
    
         
            +
                  out << headers.inspect.gsub(/^\{/, '').gsub(/\}$/, '') unless headers.empty?
         
     | 
| 
      
 208 
     | 
    
         
            +
                  out.join(', ')
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                def response_log(res)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  size = @raw_response ? File.size(@tf.path) : res.body.size
         
     | 
| 
      
 213 
     | 
    
         
            +
                  "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
         
     | 
| 
      
 214 
     | 
    
         
            +
                end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                def display_log(msg)
         
     | 
| 
      
 217 
     | 
    
         
            +
                  return unless log_to = RestClient.log
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  if log_to == 'stdout'
         
     | 
| 
      
 220 
     | 
    
         
            +
                    STDOUT.puts msg
         
     | 
| 
      
 221 
     | 
    
         
            +
                  elsif log_to == 'stderr'
         
     | 
| 
      
 222 
     | 
    
         
            +
                    STDERR.puts msg
         
     | 
| 
      
 223 
     | 
    
         
            +
                  else
         
     | 
| 
      
 224 
     | 
    
         
            +
                    File.open(log_to, 'a') { |f| f.puts msg }
         
     | 
| 
      
 225 
     | 
    
         
            +
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                def default_headers
         
     | 
| 
      
 229 
     | 
    
         
            +
                  { :accept => 'application/xml', :accept_encoding => 'gzip, deflate' }
         
     | 
| 
      
 230 
     | 
    
         
            +
                end
         
     | 
| 
      
 231 
     | 
    
         
            +
              end
         
     | 
| 
      
 232 
     | 
    
         
            +
            end
         
     |