rest-client 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +2 -0
  4. data/.rubocop-disables.yml +384 -0
  5. data/.rubocop.yml +3 -0
  6. data/.travis.yml +48 -0
  7. data/AUTHORS +98 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE +21 -0
  10. data/README.md +784 -0
  11. data/Rakefile +132 -0
  12. data/bin/restclient +92 -0
  13. data/history.md +324 -0
  14. data/lib/rest-client.rb +2 -0
  15. data/lib/rest_client.rb +2 -0
  16. data/lib/restclient.rb +184 -0
  17. data/lib/restclient/abstract_response.rb +226 -0
  18. data/lib/restclient/exceptions.rb +244 -0
  19. data/lib/restclient/params_array.rb +72 -0
  20. data/lib/restclient/payload.rb +209 -0
  21. data/lib/restclient/platform.rb +49 -0
  22. data/lib/restclient/raw_response.rb +38 -0
  23. data/lib/restclient/request.rb +853 -0
  24. data/lib/restclient/resource.rb +168 -0
  25. data/lib/restclient/response.rb +80 -0
  26. data/lib/restclient/utils.rb +235 -0
  27. data/lib/restclient/version.rb +8 -0
  28. data/lib/restclient/windows.rb +8 -0
  29. data/lib/restclient/windows/root_certs.rb +105 -0
  30. data/rest-client.gemspec +31 -0
  31. data/rest-client.windows.gemspec +19 -0
  32. data/spec/helpers.rb +22 -0
  33. data/spec/integration/_lib.rb +1 -0
  34. data/spec/integration/capath_digicert/244b5494.0 +19 -0
  35. data/spec/integration/capath_digicert/81b9768f.0 +19 -0
  36. data/spec/integration/capath_digicert/README +8 -0
  37. data/spec/integration/capath_digicert/digicert.crt +19 -0
  38. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  39. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  40. data/spec/integration/capath_verisign/README +8 -0
  41. data/spec/integration/capath_verisign/verisign.crt +14 -0
  42. data/spec/integration/certs/digicert.crt +19 -0
  43. data/spec/integration/certs/verisign.crt +14 -0
  44. data/spec/integration/httpbin_spec.rb +87 -0
  45. data/spec/integration/integration_spec.rb +125 -0
  46. data/spec/integration/request_spec.rb +127 -0
  47. data/spec/spec_helper.rb +29 -0
  48. data/spec/unit/_lib.rb +1 -0
  49. data/spec/unit/abstract_response_spec.rb +145 -0
  50. data/spec/unit/exceptions_spec.rb +108 -0
  51. data/spec/unit/master_shake.jpg +0 -0
  52. data/spec/unit/params_array_spec.rb +36 -0
  53. data/spec/unit/payload_spec.rb +263 -0
  54. data/spec/unit/raw_response_spec.rb +18 -0
  55. data/spec/unit/request2_spec.rb +54 -0
  56. data/spec/unit/request_spec.rb +1250 -0
  57. data/spec/unit/resource_spec.rb +134 -0
  58. data/spec/unit/response_spec.rb +241 -0
  59. data/spec/unit/restclient_spec.rb +79 -0
  60. data/spec/unit/utils_spec.rb +147 -0
  61. data/spec/unit/windows/root_certs_spec.rb +22 -0
  62. metadata +282 -0
@@ -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,184 @@
1
+ require 'net/http'
2
+ require 'openssl'
3
+ require 'stringio'
4
+ require 'uri'
5
+ require 'zlib'
6
+
7
+ require File.dirname(__FILE__) + '/restclient/version'
8
+ require File.dirname(__FILE__) + '/restclient/platform'
9
+ require File.dirname(__FILE__) + '/restclient/exceptions'
10
+ require File.dirname(__FILE__) + '/restclient/utils'
11
+ require File.dirname(__FILE__) + '/restclient/request'
12
+ require File.dirname(__FILE__) + '/restclient/abstract_response'
13
+ require File.dirname(__FILE__) + '/restclient/response'
14
+ require File.dirname(__FILE__) + '/restclient/raw_response'
15
+ require File.dirname(__FILE__) + '/restclient/resource'
16
+ require File.dirname(__FILE__) + '/restclient/params_array'
17
+ require File.dirname(__FILE__) + '/restclient/payload'
18
+ require File.dirname(__FILE__) + '/restclient/windows'
19
+
20
+ # This module's static methods are the entry point for using the REST client.
21
+ #
22
+ # # GET
23
+ # xml = RestClient.get 'http://example.com/resource'
24
+ # jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
25
+ #
26
+ # # authentication and SSL
27
+ # RestClient.get 'https://user:password@example.com/private/resource'
28
+ #
29
+ # # POST or PUT with a hash sends parameters as a urlencoded form body
30
+ # RestClient.post 'http://example.com/resource', :param1 => 'one'
31
+ #
32
+ # # nest hash parameters
33
+ # RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
34
+ #
35
+ # # POST and PUT with raw payloads
36
+ # RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
37
+ # RestClient.post 'http://example.com/resource.xml', xml_doc
38
+ # RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
39
+ #
40
+ # # DELETE
41
+ # RestClient.delete 'http://example.com/resource'
42
+ #
43
+ # # retreive the response http code and headers
44
+ # res = RestClient.get 'http://example.com/some.jpg'
45
+ # res.code # => 200
46
+ # res.headers[:content_type] # => 'image/jpg'
47
+ #
48
+ # # HEAD
49
+ # RestClient.head('http://example.com').headers
50
+ #
51
+ # To use with a proxy, just set RestClient.proxy to the proper http proxy:
52
+ #
53
+ # RestClient.proxy = "http://proxy.example.com/"
54
+ #
55
+ # Or inherit the proxy from the environment:
56
+ #
57
+ # RestClient.proxy = ENV['http_proxy']
58
+ #
59
+ # For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
60
+ #
61
+ # >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
62
+ # => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
63
+ #
64
+ module RestClient
65
+
66
+ def self.get(url, headers={}, &block)
67
+ Request.execute(:method => :get, :url => url, :headers => headers, &block)
68
+ end
69
+
70
+ def self.post(url, payload, headers={}, &block)
71
+ Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers, &block)
72
+ end
73
+
74
+ def self.patch(url, payload, headers={}, &block)
75
+ Request.execute(:method => :patch, :url => url, :payload => payload, :headers => headers, &block)
76
+ end
77
+
78
+ def self.put(url, payload, headers={}, &block)
79
+ Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers, &block)
80
+ end
81
+
82
+ def self.delete(url, headers={}, &block)
83
+ Request.execute(:method => :delete, :url => url, :headers => headers, &block)
84
+ end
85
+
86
+ def self.head(url, headers={}, &block)
87
+ Request.execute(:method => :head, :url => url, :headers => headers, &block)
88
+ end
89
+
90
+ def self.options(url, headers={}, &block)
91
+ Request.execute(:method => :options, :url => url, :headers => headers, &block)
92
+ end
93
+
94
+ # A global proxy URL to use for all requests. This can be overridden on a
95
+ # per-request basis by passing `:proxy` to RestClient::Request.
96
+ def self.proxy
97
+ @proxy ||= nil
98
+ end
99
+
100
+ def self.proxy=(value)
101
+ @proxy = value
102
+ @proxy_set = true
103
+ end
104
+
105
+ # Return whether RestClient.proxy was set explicitly. We use this to
106
+ # differentiate between no value being set and a value explicitly set to nil.
107
+ #
108
+ # @return [Boolean]
109
+ #
110
+ def self.proxy_set?
111
+ @proxy_set ||= false
112
+ end
113
+
114
+ # Setup the log for RestClient calls.
115
+ # Value should be a logger but can can be stdout, stderr, or a filename.
116
+ # You can also configure logging by the environment variable RESTCLIENT_LOG.
117
+ def self.log= log
118
+ @@log = create_log log
119
+ end
120
+
121
+ # Create a log that respond to << like a logger
122
+ # param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
123
+ def self.create_log param
124
+ if param
125
+ if param.is_a? String
126
+ if param == 'stdout'
127
+ stdout_logger = Class.new do
128
+ def << obj
129
+ STDOUT.puts obj
130
+ end
131
+ end
132
+ stdout_logger.new
133
+ elsif param == 'stderr'
134
+ stderr_logger = Class.new do
135
+ def << obj
136
+ STDERR.puts obj
137
+ end
138
+ end
139
+ stderr_logger.new
140
+ else
141
+ file_logger = Class.new do
142
+ attr_writer :target_file
143
+
144
+ def << obj
145
+ File.open(@target_file, 'a') { |f| f.puts obj }
146
+ end
147
+ end
148
+ logger = file_logger.new
149
+ logger.target_file = param
150
+ logger
151
+ end
152
+ else
153
+ param
154
+ end
155
+ end
156
+ end
157
+
158
+ @@env_log = create_log ENV['RESTCLIENT_LOG']
159
+
160
+ @@log = nil
161
+
162
+ def self.log # :nodoc:
163
+ @@env_log || @@log
164
+ end
165
+
166
+ @@before_execution_procs = []
167
+
168
+ # Add a Proc to be called before each request in executed.
169
+ # The proc parameters will be the http request and the request params.
170
+ def self.add_before_execution_proc &proc
171
+ raise ArgumentError.new('block is required') unless proc
172
+ @@before_execution_procs << proc
173
+ end
174
+
175
+ # Reset the procs to be called before each request is executed.
176
+ def self.reset_before_execution_procs
177
+ @@before_execution_procs = []
178
+ end
179
+
180
+ def self.before_execution_procs # :nodoc:
181
+ @@before_execution_procs
182
+ end
183
+
184
+ end
@@ -0,0 +1,226 @@
1
+ require 'cgi'
2
+ require 'http-cookie'
3
+
4
+ module RestClient
5
+
6
+ module AbstractResponse
7
+
8
+ attr_reader :net_http_res, :request
9
+
10
+ def inspect
11
+ raise NotImplementedError.new('must override in subclass')
12
+ end
13
+
14
+ # HTTP status code
15
+ def code
16
+ @code ||= @net_http_res.code.to_i
17
+ end
18
+
19
+ def history
20
+ @history ||= request.redirection_history || []
21
+ end
22
+
23
+ # A hash of the headers, beautified with symbols and underscores.
24
+ # e.g. "Content-type" will become :content_type.
25
+ def headers
26
+ @headers ||= AbstractResponse.beautify_headers(@net_http_res.to_hash)
27
+ end
28
+
29
+ # The raw headers.
30
+ def raw_headers
31
+ @raw_headers ||= @net_http_res.to_hash
32
+ end
33
+
34
+ def response_set_vars(net_http_res, request)
35
+ @net_http_res = net_http_res
36
+ @request = request
37
+
38
+ # prime redirection history
39
+ history
40
+ end
41
+
42
+ # Hash of cookies extracted from response headers.
43
+ #
44
+ # NB: This will return only cookies whose domain matches this request, and
45
+ # may not even return all of those cookies if there are duplicate names.
46
+ # Use the full cookie_jar for more nuanced access.
47
+ #
48
+ # @see #cookie_jar
49
+ #
50
+ # @return [Hash]
51
+ #
52
+ def cookies
53
+ hash = {}
54
+
55
+ cookie_jar.cookies(@request.uri).each do |cookie|
56
+ hash[cookie.name] = cookie.value
57
+ end
58
+
59
+ hash
60
+ end
61
+
62
+ # Cookie jar extracted from response headers.
63
+ #
64
+ # @return [HTTP::CookieJar]
65
+ #
66
+ def cookie_jar
67
+ return @cookie_jar if defined?(@cookie_jar) && @cookie_jar
68
+
69
+ jar = @request.cookie_jar.dup
70
+ headers.fetch(:set_cookie, []).each do |cookie|
71
+ jar.parse(cookie, @request.uri)
72
+ end
73
+
74
+ @cookie_jar = jar
75
+ end
76
+
77
+ # Return the default behavior corresponding to the response code:
78
+ #
79
+ # For 20x status codes: return the response itself
80
+ #
81
+ # For 30x status codes:
82
+ # 301, 302, 307: redirect GET / HEAD if there is a Location header
83
+ # 303: redirect, changing method to GET, if there is a Location header
84
+ #
85
+ # For all other responses, raise a response exception
86
+ #
87
+ def return!(&block)
88
+ case code
89
+ when 200..207
90
+ self
91
+ when 301, 302, 307
92
+ case request.method
93
+ when 'get', 'head'
94
+ check_max_redirects
95
+ follow_redirection(&block)
96
+ else
97
+ raise exception_with_response
98
+ end
99
+ when 303
100
+ check_max_redirects
101
+ follow_get_redirection(&block)
102
+ else
103
+ raise exception_with_response
104
+ end
105
+ end
106
+
107
+ def to_i
108
+ warn('warning: calling Response#to_i is not recommended')
109
+ super
110
+ end
111
+
112
+ def description
113
+ "#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
114
+ end
115
+
116
+ # Follow a redirection response by making a new HTTP request to the
117
+ # redirection target.
118
+ def follow_redirection(&block)
119
+ _follow_redirection(request.args.dup, &block)
120
+ end
121
+
122
+ # Follow a redirection response, but change the HTTP method to GET and drop
123
+ # the payload from the original request.
124
+ def follow_get_redirection(&block)
125
+ new_args = request.args.dup
126
+ new_args[:method] = :get
127
+ new_args.delete(:payload)
128
+
129
+ _follow_redirection(new_args, &block)
130
+ end
131
+
132
+ # Convert headers hash into canonical form.
133
+ #
134
+ # Header names will be converted to lowercase symbols with underscores
135
+ # instead of hyphens.
136
+ #
137
+ # Headers specified multiple times will be joined by comma and space,
138
+ # except for Set-Cookie, which will always be an array.
139
+ #
140
+ # Per RFC 2616, if a server sends multiple headers with the same key, they
141
+ # MUST be able to be joined into a single header by a comma. However,
142
+ # Set-Cookie (RFC 6265) cannot because commas are valid within cookie
143
+ # definitions. The newer RFC 7230 notes (3.2.2) that Set-Cookie should be
144
+ # handled as a special case.
145
+ #
146
+ # http://tools.ietf.org/html/rfc2616#section-4.2
147
+ # http://tools.ietf.org/html/rfc7230#section-3.2.2
148
+ # http://tools.ietf.org/html/rfc6265
149
+ #
150
+ # @param headers [Hash]
151
+ # @return [Hash]
152
+ #
153
+ def self.beautify_headers(headers)
154
+ headers.inject({}) do |out, (key, value)|
155
+ key_sym = key.tr('-', '_').downcase.to_sym
156
+
157
+ # Handle Set-Cookie specially since it cannot be joined by comma.
158
+ if key.downcase == 'set-cookie'
159
+ out[key_sym] = value
160
+ else
161
+ out[key_sym] = value.join(', ')
162
+ end
163
+
164
+ out
165
+ end
166
+ end
167
+
168
+ private
169
+
170
+ # Follow a redirection
171
+ #
172
+ # @param new_args [Hash] Start with this hash of arguments for the
173
+ # redirection request. The hash will be mutated, so be sure to dup any
174
+ # existing hash that should not be modified.
175
+ #
176
+ def _follow_redirection(new_args, &block)
177
+
178
+ # parse location header and merge into existing URL
179
+ url = headers[:location]
180
+
181
+ # cannot follow redirection if there is no location header
182
+ unless url
183
+ raise exception_with_response
184
+ end
185
+
186
+ # handle relative redirects
187
+ unless url.start_with?('http')
188
+ url = URI.parse(request.url).merge(url).to_s
189
+ end
190
+ new_args[:url] = url
191
+
192
+ new_args[:password] = request.password
193
+ new_args[:user] = request.user
194
+ new_args[:headers] = request.headers
195
+ new_args[:max_redirects] = request.max_redirects - 1
196
+
197
+ # pass through our new cookie jar
198
+ new_args[:cookies] = cookie_jar
199
+
200
+ # prepare new request
201
+ new_req = Request.new(new_args)
202
+
203
+ # append self to redirection history
204
+ new_req.redirection_history = history + [self]
205
+
206
+ # execute redirected request
207
+ new_req.execute(&block)
208
+ end
209
+
210
+ def check_max_redirects
211
+ if request.max_redirects <= 0
212
+ raise exception_with_response
213
+ end
214
+ end
215
+
216
+ def exception_with_response
217
+ begin
218
+ klass = Exceptions::EXCEPTIONS_MAP.fetch(code)
219
+ rescue KeyError
220
+ raise RequestFailed.new(self, code)
221
+ end
222
+
223
+ raise klass.new(self, code)
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,244 @@
1
+ module RestClient
2
+
3
+ # Hash of HTTP status code => message.
4
+ #
5
+ # 1xx: Informational - Request received, continuing process
6
+ # 2xx: Success - The action was successfully received, understood, and
7
+ # accepted
8
+ # 3xx: Redirection - Further action must be taken in order to complete the
9
+ # request
10
+ # 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
11
+ # 5xx: Server Error - The server failed to fulfill an apparently valid
12
+ # request
13
+ #
14
+ # @see
15
+ # http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
16
+ #
17
+ STATUSES = {100 => 'Continue',
18
+ 101 => 'Switching Protocols',
19
+ 102 => 'Processing', #WebDAV
20
+
21
+ 200 => 'OK',
22
+ 201 => 'Created',
23
+ 202 => 'Accepted',
24
+ 203 => 'Non-Authoritative Information', # http/1.1
25
+ 204 => 'No Content',
26
+ 205 => 'Reset Content',
27
+ 206 => 'Partial Content',
28
+ 207 => 'Multi-Status', #WebDAV
29
+ 208 => 'Already Reported', # RFC5842
30
+ 226 => 'IM Used', # RFC3229
31
+
32
+ 300 => 'Multiple Choices',
33
+ 301 => 'Moved Permanently',
34
+ 302 => 'Found',
35
+ 303 => 'See Other', # http/1.1
36
+ 304 => 'Not Modified',
37
+ 305 => 'Use Proxy', # http/1.1
38
+ 306 => 'Switch Proxy', # no longer used
39
+ 307 => 'Temporary Redirect', # http/1.1
40
+ 308 => 'Permanent Redirect', # RFC7538
41
+
42
+ 400 => 'Bad Request',
43
+ 401 => 'Unauthorized',
44
+ 402 => 'Payment Required',
45
+ 403 => 'Forbidden',
46
+ 404 => 'Not Found',
47
+ 405 => 'Method Not Allowed',
48
+ 406 => 'Not Acceptable',
49
+ 407 => 'Proxy Authentication Required',
50
+ 408 => 'Request Timeout',
51
+ 409 => 'Conflict',
52
+ 410 => 'Gone',
53
+ 411 => 'Length Required',
54
+ 412 => 'Precondition Failed',
55
+ 413 => 'Payload Too Large', # RFC7231 (renamed, see below)
56
+ 414 => 'URI Too Long', # RFC7231 (renamed, see below)
57
+ 415 => 'Unsupported Media Type',
58
+ 416 => 'Range Not Satisfiable', # RFC7233 (renamed, see below)
59
+ 417 => 'Expectation Failed',
60
+ 418 => 'I\'m A Teapot', #RFC2324
61
+ 421 => 'Too Many Connections From This IP',
62
+ 422 => 'Unprocessable Entity', #WebDAV
63
+ 423 => 'Locked', #WebDAV
64
+ 424 => 'Failed Dependency', #WebDAV
65
+ 425 => 'Unordered Collection', #WebDAV
66
+ 426 => 'Upgrade Required',
67
+ 428 => 'Precondition Required', #RFC6585
68
+ 429 => 'Too Many Requests', #RFC6585
69
+ 431 => 'Request Header Fields Too Large', #RFC6585
70
+ 449 => 'Retry With', #Microsoft
71
+ 450 => 'Blocked By Windows Parental Controls', #Microsoft
72
+
73
+ 500 => 'Internal Server Error',
74
+ 501 => 'Not Implemented',
75
+ 502 => 'Bad Gateway',
76
+ 503 => 'Service Unavailable',
77
+ 504 => 'Gateway Timeout',
78
+ 505 => 'HTTP Version Not Supported',
79
+ 506 => 'Variant Also Negotiates',
80
+ 507 => 'Insufficient Storage', #WebDAV
81
+ 508 => 'Loop Detected', # RFC5842
82
+ 509 => 'Bandwidth Limit Exceeded', #Apache
83
+ 510 => 'Not Extended',
84
+ 511 => 'Network Authentication Required', # RFC6585
85
+ }
86
+
87
+ STATUSES_COMPATIBILITY = {
88
+ # The RFCs all specify "Not Found", but "Resource Not Found" was used in
89
+ # earlier RestClient releases.
90
+ 404 => ['ResourceNotFound'],
91
+
92
+ # HTTP 413 was renamed to "Payload Too Large" in RFC7231.
93
+ 413 => ['RequestEntityTooLarge'],
94
+
95
+ # HTTP 414 was renamed to "URI Too Long" in RFC7231.
96
+ 414 => ['RequestURITooLong'],
97
+
98
+ # HTTP 416 was renamed to "Range Not Satisfiable" in RFC7233.
99
+ 416 => ['RequestedRangeNotSatisfiable'],
100
+ }
101
+
102
+
103
+ # This is the base RestClient exception class. Rescue it if you want to
104
+ # catch any exception that your request might raise
105
+ # You can get the status code by e.http_code, or see anything about the
106
+ # response via e.response.
107
+ # For example, the entire result body (which is
108
+ # probably an HTML error page) is e.response.
109
+ class Exception < RuntimeError
110
+ attr_accessor :response
111
+ attr_accessor :original_exception
112
+ attr_writer :message
113
+
114
+ def initialize response = nil, initial_response_code = nil
115
+ @response = response
116
+ @message = nil
117
+ @initial_response_code = initial_response_code
118
+ end
119
+
120
+ def http_code
121
+ # return integer for compatibility
122
+ if @response
123
+ @response.code.to_i
124
+ else
125
+ @initial_response_code
126
+ end
127
+ end
128
+
129
+ def http_headers
130
+ @response.headers if @response
131
+ end
132
+
133
+ def http_body
134
+ @response.body if @response
135
+ end
136
+
137
+ def to_s
138
+ message
139
+ end
140
+
141
+ def message
142
+ @message || default_message
143
+ end
144
+
145
+ def default_message
146
+ self.class.name
147
+ end
148
+ end
149
+
150
+ # Compatibility
151
+ class ExceptionWithResponse < Exception
152
+ end
153
+
154
+ # The request failed with an error code not managed by the code
155
+ class RequestFailed < ExceptionWithResponse
156
+
157
+ def default_message
158
+ "HTTP status code #{http_code}"
159
+ end
160
+
161
+ def to_s
162
+ message
163
+ end
164
+ end
165
+
166
+ # RestClient exception classes. TODO: move all exceptions into this module.
167
+ #
168
+ # We will a create an exception for each status code, see
169
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
170
+ #
171
+ module Exceptions
172
+ # Map http status codes to the corresponding exception class
173
+ EXCEPTIONS_MAP = {}
174
+ end
175
+
176
+ # Create HTTP status exception classes
177
+ STATUSES.each_pair do |code, message|
178
+ klass = Class.new(RequestFailed) do
179
+ send(:define_method, :default_message) {"#{http_code ? "#{http_code} " : ''}#{message}"}
180
+ end
181
+ klass_constant = const_set(message.delete(' \-\''), klass)
182
+ Exceptions::EXCEPTIONS_MAP[code] = klass_constant
183
+ end
184
+
185
+ # Create HTTP status exception classes used for backwards compatibility
186
+ STATUSES_COMPATIBILITY.each_pair do |code, compat_list|
187
+ klass = Exceptions::EXCEPTIONS_MAP.fetch(code)
188
+ compat_list.each do |old_name|
189
+ const_set(old_name, klass)
190
+ end
191
+ end
192
+
193
+ module Exceptions
194
+ # We have to split the Exceptions module like we do here because the
195
+ # EXCEPTIONS_MAP is under Exceptions, but we depend on
196
+ # RestClient::RequestTimeout below.
197
+
198
+ # Base class for request timeouts.
199
+ #
200
+ # NB: Previous releases of rest-client would raise RequestTimeout both for
201
+ # HTTP 408 responses and for actual connection timeouts.
202
+ class Timeout < RestClient::RequestTimeout
203
+ def initialize(message=nil, original_exception=nil)
204
+ super(nil, nil)
205
+ self.message = message if message
206
+ self.original_exception = original_exception if original_exception
207
+ end
208
+ end
209
+
210
+ # Timeout when connecting to a server. Typically wraps Net::OpenTimeout (in
211
+ # ruby 2.0 or greater).
212
+ class OpenTimeout < Timeout
213
+ def default_message
214
+ 'Timed out connecting to server'
215
+ end
216
+ end
217
+
218
+ # Timeout when reading from a server. Typically wraps Net::ReadTimeout (in
219
+ # ruby 2.0 or greater).
220
+ class ReadTimeout < Timeout
221
+ def default_message
222
+ 'Timed out reading data from server'
223
+ end
224
+ end
225
+ end
226
+
227
+
228
+ # The server broke the connection prior to the request completing. Usually
229
+ # this means it crashed, or sometimes that your network connection was
230
+ # severed before it could complete.
231
+ class ServerBrokeConnection < Exception
232
+ def initialize(message = 'Server broke connection')
233
+ super nil, nil
234
+ self.message = message
235
+ end
236
+ end
237
+
238
+ class SSLCertificateNotVerified < Exception
239
+ def initialize(message = 'SSL certificate not verified')
240
+ super nil, nil
241
+ self.message = message
242
+ end
243
+ end
244
+ end