rest-client 1.6.0

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.

Potentially problematic release.


This version of rest-client might be problematic. Click here for more details.

@@ -0,0 +1,2 @@
1
+ # More logical way to require 'rest-client'
2
+ require File.dirname(__FILE__) + '/restclient'
@@ -0,0 +1,2 @@
1
+ # This file exists for backward compatbility with require 'rest_client'
2
+ require File.dirname(__FILE__) + '/restclient'
@@ -0,0 +1,161 @@
1
+ require 'uri'
2
+ require 'zlib'
3
+ require 'stringio'
4
+
5
+ begin
6
+ require 'net/https'
7
+ rescue LoadError => e
8
+ raise e unless RUBY_PLATFORM =~ /linux/
9
+ raise LoadError, "no such file to load -- net/https. Try running apt-get install libopenssl-ruby"
10
+ end
11
+
12
+ require File.dirname(__FILE__) + '/restclient/exceptions'
13
+ require File.dirname(__FILE__) + '/restclient/request'
14
+ require File.dirname(__FILE__) + '/restclient/abstract_response'
15
+ require File.dirname(__FILE__) + '/restclient/response'
16
+ require File.dirname(__FILE__) + '/restclient/raw_response'
17
+ require File.dirname(__FILE__) + '/restclient/resource'
18
+ require File.dirname(__FILE__) + '/restclient/payload'
19
+ require File.dirname(__FILE__) + '/restclient/net_http_ext'
20
+
21
+ # This module's static methods are the entry point for using the REST client.
22
+ #
23
+ # # GET
24
+ # xml = RestClient.get 'http://example.com/resource'
25
+ # jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
26
+ #
27
+ # # authentication and SSL
28
+ # RestClient.get 'https://user:password@example.com/private/resource'
29
+ #
30
+ # # POST or PUT with a hash sends parameters as a urlencoded form body
31
+ # RestClient.post 'http://example.com/resource', :param1 => 'one'
32
+ #
33
+ # # nest hash parameters
34
+ # RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
35
+ #
36
+ # # POST and PUT with raw payloads
37
+ # RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
38
+ # RestClient.post 'http://example.com/resource.xml', xml_doc
39
+ # RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
40
+ #
41
+ # # DELETE
42
+ # RestClient.delete 'http://example.com/resource'
43
+ #
44
+ # # retreive the response http code and headers
45
+ # res = RestClient.get 'http://example.com/some.jpg'
46
+ # res.code # => 200
47
+ # res.headers[:content_type] # => 'image/jpg'
48
+ #
49
+ # # HEAD
50
+ # RestClient.head('http://example.com').headers
51
+ #
52
+ # To use with a proxy, just set RestClient.proxy to the proper http proxy:
53
+ #
54
+ # RestClient.proxy = "http://proxy.example.com/"
55
+ #
56
+ # Or inherit the proxy from the environment:
57
+ #
58
+ # RestClient.proxy = ENV['http_proxy']
59
+ #
60
+ # For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
61
+ #
62
+ # >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
63
+ # => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
64
+ #
65
+ module RestClient
66
+
67
+ def self.get(url, headers={}, &block)
68
+ Request.execute(:method => :get, :url => url, :headers => headers, &block)
69
+ end
70
+
71
+ def self.post(url, payload, headers={}, &block)
72
+ Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers, &block)
73
+ end
74
+
75
+ def self.put(url, payload, headers={}, &block)
76
+ Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers, &block)
77
+ end
78
+
79
+ def self.delete(url, headers={}, &block)
80
+ Request.execute(:method => :delete, :url => url, :headers => headers, &block)
81
+ end
82
+
83
+ def self.head(url, headers={}, &block)
84
+ Request.execute(:method => :head, :url => url, :headers => headers, &block)
85
+ end
86
+
87
+ class << self
88
+ attr_accessor :proxy
89
+ end
90
+
91
+ # Setup the log for RestClient calls.
92
+ # Value should be a logger but can can be stdout, stderr, or a filename.
93
+ # You can also configure logging by the environment variable RESTCLIENT_LOG.
94
+ def self.log= log
95
+ @@log = create_log log
96
+ end
97
+
98
+ def self.version
99
+ version_path = File.dirname(__FILE__) + "/../VERSION"
100
+ return File.read(version_path).chomp if File.file?(version_path)
101
+ "0.0.0"
102
+ end
103
+
104
+ # Create a log that respond to << like a logger
105
+ # param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
106
+ def self.create_log param
107
+ if param
108
+ if param.is_a? String
109
+ if param == 'stdout'
110
+ stdout_logger = Class.new do
111
+ def << obj
112
+ STDOUT.puts obj
113
+ end
114
+ end
115
+ stdout_logger.new
116
+ elsif param == 'stderr'
117
+ stderr_logger = Class.new do
118
+ def << obj
119
+ STDERR.puts obj
120
+ end
121
+ end
122
+ stderr_logger.new
123
+ else
124
+ file_logger = Class.new do
125
+ attr_writer :target_file
126
+
127
+ def << obj
128
+ File.open(@target_file, 'a') { |f| f.puts obj }
129
+ end
130
+ end
131
+ logger = file_logger.new
132
+ logger.target_file = param
133
+ logger
134
+ end
135
+ else
136
+ param
137
+ end
138
+ end
139
+ end
140
+
141
+ @@env_log = create_log ENV['RESTCLIENT_LOG']
142
+
143
+ @@log = nil
144
+
145
+ def self.log # :nodoc:
146
+ @@env_log || @@log
147
+ end
148
+
149
+ @@before_execution_procs = []
150
+
151
+ # Add a Proc to be called before each request in executed.
152
+ # The proc parameters will be the http request and the request params.
153
+ def self.add_before_execution_proc &proc
154
+ @@before_execution_procs << proc
155
+ end
156
+
157
+ def self.before_execution_procs # :nodoc:
158
+ @@before_execution_procs
159
+ end
160
+
161
+ end
@@ -0,0 +1,89 @@
1
+ require 'cgi'
2
+
3
+ module RestClient
4
+
5
+ module AbstractResponse
6
+
7
+ attr_reader :net_http_res, :args
8
+
9
+ # HTTP status code
10
+ def code
11
+ @code ||= @net_http_res.code.to_i
12
+ end
13
+
14
+ # A hash of the headers, beautified with symbols and underscores.
15
+ # e.g. "Content-type" will become :content_type.
16
+ def headers
17
+ @headers ||= AbstractResponse.beautify_headers(@net_http_res.to_hash)
18
+ end
19
+
20
+ # The raw headers.
21
+ def raw_headers
22
+ @raw_headers ||= @net_http_res.to_hash
23
+ end
24
+
25
+ # Hash of cookies extracted from response headers
26
+ def cookies
27
+ @cookies ||= (self.headers[:set_cookie] || {}).inject({}) do |out, cookie_content|
28
+ CGI::Cookie::parse(cookie_content).each do |key, cookie|
29
+ unless ['expires', 'path'].include? key
30
+ out[CGI::escape(key)] = cookie.value[0] ? (CGI::escape(cookie.value[0]) || '') : ''
31
+ end
32
+ end
33
+ out
34
+ end
35
+ end
36
+
37
+ # Return the default behavior corresponding to the response code:
38
+ # the response itself for code in 200..206, redirection for 301, 302 and 307 in get and head cases, redirection for 303 and an exception in other cases
39
+ def return! request = nil, &block
40
+ if (200..207).include? code
41
+ self
42
+ elsif [301, 302, 307].include? code
43
+ unless [:get, :head].include? args[:method]
44
+ raise Exceptions::EXCEPTIONS_MAP[code], self
45
+ else
46
+ follow_redirection(request, &block)
47
+ end
48
+ elsif code == 303
49
+ args[:method] = :get
50
+ args.delete :payload
51
+ follow_redirection(request, &block)
52
+ elsif Exceptions::EXCEPTIONS_MAP[code]
53
+ raise Exceptions::EXCEPTIONS_MAP[code], self
54
+ else
55
+ raise RequestFailed, self
56
+ end
57
+ end
58
+
59
+ def to_i
60
+ code
61
+ end
62
+
63
+ def description
64
+ "#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
65
+ end
66
+
67
+ # Follow a redirection
68
+ def follow_redirection request = nil, &block
69
+ url = headers[:location]
70
+ if url !~ /^http/
71
+ url = URI.parse(args[:url]).merge(url).to_s
72
+ end
73
+ args[:url] = url
74
+ if request
75
+ args[:password] = request.password
76
+ args[:user] = request.user
77
+ args[:headers] = request.headers
78
+ end
79
+ Request.execute args, &block
80
+ end
81
+
82
+ def AbstractResponse.beautify_headers(headers)
83
+ headers.inject({}) do |out, (key, value)|
84
+ out[key.gsub(/-/, '_').downcase.to_sym] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
85
+ out
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,172 @@
1
+ module RestClient
2
+
3
+ STATUSES = {100 => 'Continue',
4
+ 101 => 'Switching Protocols',
5
+ 102 => 'Processing', #WebDAV
6
+
7
+ 200 => 'OK',
8
+ 201 => 'Created',
9
+ 202 => 'Accepted',
10
+ 203 => 'Non-Authoritative Information', # http/1.1
11
+ 204 => 'No Content',
12
+ 205 => 'Reset Content',
13
+ 206 => 'Partial Content',
14
+ 207 => 'Multi-Status', #WebDAV
15
+
16
+ 300 => 'Multiple Choices',
17
+ 301 => 'Moved Permanently',
18
+ 302 => 'Found',
19
+ 303 => 'See Other', # http/1.1
20
+ 304 => 'Not Modified',
21
+ 305 => 'Use Proxy', # http/1.1
22
+ 306 => 'Switch Proxy', # no longer used
23
+ 307 => 'Temporary Redirect', # http/1.1
24
+
25
+ 400 => 'Bad Request',
26
+ 401 => 'Unauthorized',
27
+ 402 => 'Payment Required',
28
+ 403 => 'Forbidden',
29
+ 404 => 'Resource Not Found',
30
+ 405 => 'Method Not Allowed',
31
+ 406 => 'Not Acceptable',
32
+ 407 => 'Proxy Authentication Required',
33
+ 408 => 'Request Timeout',
34
+ 409 => 'Conflict',
35
+ 410 => 'Gone',
36
+ 411 => 'Length Required',
37
+ 412 => 'Precondition Failed',
38
+ 413 => 'Request Entity Too Large',
39
+ 414 => 'Request-URI Too Long',
40
+ 415 => 'Unsupported Media Type',
41
+ 416 => 'Requested Range Not Satisfiable',
42
+ 417 => 'Expectation Failed',
43
+ 418 => 'I\'m A Teapot',
44
+ 421 => 'Too Many Connections From This IP',
45
+ 422 => 'Unprocessable Entity', #WebDAV
46
+ 423 => 'Locked', #WebDAV
47
+ 424 => 'Failed Dependency', #WebDAV
48
+ 425 => 'Unordered Collection', #WebDAV
49
+ 426 => 'Upgrade Required',
50
+ 449 => 'Retry With', #Microsoft
51
+ 450 => 'Blocked By Windows Parental Controls', #Microsoft
52
+
53
+ 500 => 'Internal Server Error',
54
+ 501 => 'Not Implemented',
55
+ 502 => 'Bad Gateway',
56
+ 503 => 'Service Unavailable',
57
+ 504 => 'Gateway Timeout',
58
+ 505 => 'HTTP Version Not Supported',
59
+ 506 => 'Variant Also Negotiates',
60
+ 507 => 'Insufficient Storage', #WebDAV
61
+ 509 => 'Bandwidth Limit Exceeded', #Apache
62
+ 510 => 'Not Extended'}
63
+
64
+ # Compatibility : make the Response act like a Net::HTTPResponse when needed
65
+ module ResponseForException
66
+ def method_missing symbol, *args
67
+ if net_http_res.respond_to? symbol
68
+ warn "[warning] The response contained in an RestClient::Exception is now a RestClient::Response instead of a Net::HTTPResponse, please update your code"
69
+ net_http_res.send symbol, *args
70
+ else
71
+ super
72
+ end
73
+ end
74
+ end
75
+
76
+ # This is the base RestClient exception class. Rescue it if you want to
77
+ # catch any exception that your request might raise
78
+ # You can get the status code by e.http_code, or see anything about the
79
+ # response via e.response.
80
+ # For example, the entire result body (which is
81
+ # probably an HTML error page) is e.response.
82
+ class Exception < RuntimeError
83
+ attr_accessor :message, :response
84
+
85
+ def initialize response = nil
86
+ @response = response
87
+
88
+ # compatibility: this make the exception behave like a Net::HTTPResponse
89
+ response.extend ResponseForException if response
90
+ end
91
+
92
+ def http_code
93
+ # return integer for compatibility
94
+ @response.code.to_i if @response
95
+ end
96
+
97
+ def http_body
98
+ @response.body if @response
99
+ end
100
+
101
+ def inspect
102
+ "#{self.class} : #{http_code} #{message}"
103
+ end
104
+
105
+ end
106
+
107
+ # Compatibility
108
+ class ExceptionWithResponse < Exception
109
+ end
110
+
111
+ # The request failed with an error code not managed by the code
112
+ class RequestFailed < ExceptionWithResponse
113
+
114
+ def message
115
+ "HTTP status code #{http_code}"
116
+ end
117
+
118
+ def to_s
119
+ message
120
+ end
121
+ end
122
+
123
+ # We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
124
+ module Exceptions
125
+ # Map http status codes to the corresponding exception class
126
+ EXCEPTIONS_MAP = {}
127
+ end
128
+
129
+ STATUSES.each_pair do |code, message|
130
+
131
+ # Compatibility
132
+ superclass = ([304, 401, 404].include? code) ? ExceptionWithResponse : RequestFailed
133
+ klass = Class.new(superclass) do
134
+ send(:define_method, :message) {message}
135
+ end
136
+ klass_constant = const_set message.delete(' \-\''), klass
137
+ Exceptions::EXCEPTIONS_MAP[code] = klass_constant
138
+ end
139
+
140
+ # A redirect was encountered; caught by execute to retry with the new url.
141
+ class Redirect < Exception
142
+
143
+ message = 'Redirect'
144
+
145
+ attr_accessor :url
146
+
147
+ def initialize(url)
148
+ @url = url
149
+ end
150
+ end
151
+
152
+ # The server broke the connection prior to the request completing. Usually
153
+ # this means it crashed, or sometimes that your network connection was
154
+ # severed before it could complete.
155
+ class ServerBrokeConnection < Exception
156
+ message = 'Server broke connection'
157
+ end
158
+
159
+ class SSLCertificateNotVerified < Exception
160
+ def initialize(message)
161
+ super(nil)
162
+ self.message = message
163
+ end
164
+ end
165
+ end
166
+
167
+ # backwards compatibility
168
+ class RestClient::Request
169
+ Redirect = RestClient::Redirect
170
+ Unauthorized = RestClient::Unauthorized
171
+ RequestFailed = RestClient::RequestFailed
172
+ end
@@ -0,0 +1,21 @@
1
+ #
2
+ # Replace the request method in Net::HTTP to sniff the body type
3
+ # and set the stream if appropriate
4
+ #
5
+ # Taken from:
6
+ # http://www.missiondata.com/blog/ruby/29/streaming-data-to-s3-with-ruby/
7
+
8
+ module Net
9
+ class HTTP
10
+ alias __request__ request
11
+
12
+ def request(req, body=nil, &block)
13
+ if body != nil && body.respond_to?(:read)
14
+ req.body_stream = body
15
+ return __request__(req, nil, &block)
16
+ else
17
+ return __request__(req, body, &block)
18
+ end
19
+ end
20
+ end
21
+ end