rest 2.7.2 → 3.0.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.
- checksums.yaml +5 -13
- data/Gemfile.lock +16 -18
- data/README.md +2 -0
- data/lib/rest.rb +3 -1
- data/lib/rest/client.rb +12 -6
- data/lib/rest/version.rb +1 -1
- data/lib/rest/wrappers/base_wrapper.rb +7 -9
- data/lib/rest/wrappers/excon_wrapper.rb +4 -4
- data/lib/rest/wrappers/internal_client/internal/abstract_response.rb +108 -0
- data/lib/rest/wrappers/internal_client/internal/exceptions.rb +194 -0
- data/lib/rest/wrappers/internal_client/internal/mimes.rb +54 -0
- data/lib/rest/wrappers/internal_client/internal/net_http_ext.rb +55 -0
- data/lib/rest/wrappers/internal_client/internal/payload.rb +237 -0
- data/lib/rest/wrappers/internal_client/internal/raw_response.rb +36 -0
- data/lib/rest/wrappers/internal_client/internal/request.rb +322 -0
- data/lib/rest/wrappers/internal_client/internal/resource.rb +173 -0
- data/lib/rest/wrappers/internal_client/internal/response.rb +28 -0
- data/lib/rest/wrappers/internal_client/internal_client.rb +177 -0
- data/lib/rest/wrappers/internal_client_wrapper.rb +127 -0
- data/rest.gemspec +4 -2
- data/test/test_base.rb +1 -1
- data/test/test_performance.rb +1 -1
- data/test/test_rest.rb +6 -4
- metadata +47 -36
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YzdmYjM5NDBhYzMxZjgyZjMyOGE3ZGRiNDZlODI2N2RlNWNiNTI3MQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6c689e6d91135dd2ac6e0f4f0f63ad55ad77ecc2
|
4
|
+
data.tar.gz: 70b63a96e8d9f1bfc566207907359d8d2411af63
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZWZlYjk3M2E0OTRlMWQ5ZTE2MDZkMzQ4NWJmNjZiMWJjODhmZWJjMjE0NzAz
|
11
|
-
NjIzMWZhOWRhZDg2MzY3ZDVkMTBiZDI5NGJmZjdmMWFmOTNkZDY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjAzNjYxMDljOTljNzQ1Y2RiNTRmMmI2NjlmYjYxN2MxOTM3OTlmZjlmMDFi
|
14
|
-
YWU3YWU2OGZmZWRhMTIyNzBiY2U1ZjE0Njk1MGY2M2FiNmFlMjVhMWNmOWE1
|
15
|
-
NDM3NzYxMDZiNzllZWEzMjM5MTg5N2EyMjBiMjZhZmI0MTA0ZGU=
|
6
|
+
metadata.gz: 3e50465d789d0d1f9628a15365ab78d619aab36d74dfc5c00e2f64622e2d875fe7d622840089da6c6629dcbbc13a12858157bebeb9d3108ac73bc8c03a970f83
|
7
|
+
data.tar.gz: d7c8edf6574d60b6f0209d069f56ce7e77166cb0db7df4f257aae20b417378e0394238df9ccd5f272b627fab00f87d499981d6fb832878d324bf3960dcd9fbd4
|
data/Gemfile.lock
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rest (2.7.
|
5
|
-
net-http-persistent
|
6
|
-
rest_client (>= 1.7.1)
|
4
|
+
rest (2.7.1)
|
5
|
+
net-http-persistent (>= 2.9.1)
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: https://rubygems.org/
|
10
9
|
specs:
|
11
|
-
ethon (0.
|
10
|
+
ethon (0.7.1)
|
12
11
|
ffi (>= 1.3.0)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
netrc (0.7.7)
|
12
|
+
excon (0.41.0)
|
13
|
+
ffi (1.9.6)
|
14
|
+
minitest (5.4.3)
|
15
|
+
net-http-persistent (2.9.4)
|
16
|
+
netrc (0.9.0)
|
17
|
+
power_assert (0.2.1)
|
20
18
|
quicky (0.4.0)
|
21
|
-
rake (10.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
uber_config (1.1.0)
|
19
|
+
rake (10.3.2)
|
20
|
+
test-unit (3.0.7)
|
21
|
+
power_assert
|
22
|
+
typhoeus (0.6.9)
|
23
|
+
ethon (>= 0.7.1)
|
24
|
+
uber_config (1.1.1)
|
28
25
|
|
29
26
|
PLATFORMS
|
30
27
|
ruby
|
@@ -32,6 +29,7 @@ PLATFORMS
|
|
32
29
|
DEPENDENCIES
|
33
30
|
excon
|
34
31
|
minitest
|
32
|
+
netrc
|
35
33
|
quicky (>= 0.4.0)
|
36
34
|
rake
|
37
35
|
rest!
|
data/README.md
CHANGED
@@ -16,6 +16,7 @@ Features
|
|
16
16
|
* Chooses best client you have installed on your system based on what we have found performs the best.
|
17
17
|
* Currently net_http_persistent and typhoeus are nearly the same, but since net_http_persistent doesn't have a binary
|
18
18
|
dependency, it wins.
|
19
|
+
* You can run performance tests yourself by running: `ruby test/test_performance.rb`, quite a difference between the libs.
|
19
20
|
* Handles 503 errors with exponential backoff.
|
20
21
|
|
21
22
|
|
@@ -39,6 +40,7 @@ Supported http libraries are:
|
|
39
40
|
* rest_client
|
40
41
|
* net_http_persistent
|
41
42
|
* typhoeus
|
43
|
+
* internal - this gem's built in client.
|
42
44
|
|
43
45
|
Then use it:
|
44
46
|
|
data/lib/rest.rb
CHANGED
data/lib/rest/client.rb
CHANGED
@@ -14,8 +14,6 @@ require 'rest/errors'
|
|
14
14
|
|
15
15
|
module Rest
|
16
16
|
|
17
|
-
require 'rest/wrappers/base_wrapper'
|
18
|
-
|
19
17
|
@@logger = Logger.new(STDOUT)
|
20
18
|
@@logger.level = Logger::INFO
|
21
19
|
|
@@ -43,6 +41,7 @@ module Rest
|
|
43
41
|
@@backing_gems[:typhoeus] = BackingGem.new(:typhoeus, 'typhoeus')
|
44
42
|
@@backing_gems[:rest_client] = BackingGem.new(:rest_client, 'rest_client')
|
45
43
|
@@backing_gems[:net_http_persistent] = BackingGem.new(:net_http_persistent, 'net/http/persistent')
|
44
|
+
@@backing_gems[:internal] = BackingGem.new(:internal, 'internal_client')
|
46
45
|
|
47
46
|
def self.backing_gems
|
48
47
|
@@backing_gems
|
@@ -77,11 +76,16 @@ module Rest
|
|
77
76
|
require File.expand_path('wrappers/net_http_persistent_wrapper', File.dirname(__FILE__))
|
78
77
|
@wrapper = Rest::Wrappers::NetHttpPersistentWrapper.new(self)
|
79
78
|
@logger.debug "Using net-http-persistent gem."
|
80
|
-
|
79
|
+
elsif @gem == :rest_client
|
80
|
+
require File.expand_path('wrappers/rest_client_wrapper', File.dirname(__FILE__))
|
81
81
|
@wrapper = Rest::Wrappers::RestClientWrapper.new
|
82
82
|
hint = (options[:gem] ? "" : "NOTICE: Please install 'typhoeus' gem or upgrade to Ruby 2.X for optimal performance.")
|
83
83
|
puts hint
|
84
84
|
@logger.debug "Using rest-client gem. #{hint}"
|
85
|
+
else # use internal client
|
86
|
+
require File.expand_path('wrappers/internal_client_wrapper', File.dirname(__FILE__))
|
87
|
+
@wrapper = Rest::Wrappers::InternalClientWrapper.new
|
88
|
+
@logger.debug "Using rest internal client. #{hint}"
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
@@ -92,10 +96,12 @@ module Rest
|
|
92
96
|
gems_to_try << :net_http_persistent
|
93
97
|
gems_to_try << :typhoeus
|
94
98
|
gems_to_try << :rest_client
|
99
|
+
gems_to_try << :internal
|
95
100
|
else
|
96
101
|
# net-http-persistent has issues with ssl and keep-alive connections on ruby < 1.9.3p327
|
97
102
|
gems_to_try << :typhoeus
|
98
103
|
gems_to_try << :rest_client
|
104
|
+
gems_to_try << :internal
|
99
105
|
end
|
100
106
|
gems_to_try.each_with_index do |g, i|
|
101
107
|
bg = Rest.backing_gems[g]
|
@@ -165,11 +171,11 @@ module Rest
|
|
165
171
|
raise ex if current_retry == max_retries - 1
|
166
172
|
|
167
173
|
pow = (4 ** (current_retry)) * 100 # milliseconds
|
168
|
-
|
174
|
+
#puts 'pow=' + pow.to_s
|
169
175
|
s = rand * pow
|
170
|
-
|
176
|
+
#puts 's=' + s.to_s
|
171
177
|
sleep_secs = 1.0 * s / 1000.0
|
172
|
-
|
178
|
+
#puts 'sleep for ' + sleep_secs.to_s
|
173
179
|
current_retry += 1
|
174
180
|
@logger.debug "#{ex.code} Received. Retrying #{current_retry} out of #{max_retries} max in #{sleep_secs} seconds."
|
175
181
|
sleep sleep_secs
|
data/lib/rest/version.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# we need client for post_file
|
2
|
+
|
1
3
|
module Rest
|
2
4
|
class BaseWrapper
|
3
5
|
|
@@ -15,10 +17,10 @@ module Rest
|
|
15
17
|
req_hash.delete(:headers)
|
16
18
|
end
|
17
19
|
|
18
|
-
r2 =
|
19
|
-
response = Rest::Wrappers::
|
20
|
-
rescue
|
21
|
-
raise Rest::Wrappers::
|
20
|
+
r2 = Rest::InternalClient.post(url, req_hash, headers)
|
21
|
+
response = Rest::Wrappers::InternalClientResponseWrapper.new(r2)
|
22
|
+
rescue Rest::InternalClient::Exception => ex
|
23
|
+
raise Rest::Wrappers::InternalClientExceptionWrapper.new(ex)
|
22
24
|
end
|
23
25
|
response
|
24
26
|
end
|
@@ -40,7 +42,7 @@ module Rest
|
|
40
42
|
# Provide a headers_orig method in your wrapper to allow this to work
|
41
43
|
def headers
|
42
44
|
new_h = {}
|
43
|
-
headers_orig.each_pair do |k,v|
|
45
|
+
headers_orig.each_pair do |k, v|
|
44
46
|
if v.is_a?(Array) && v.size == 1
|
45
47
|
v = v[0]
|
46
48
|
end
|
@@ -51,7 +53,3 @@ module Rest
|
|
51
53
|
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
55
|
-
# we need it for post_file, ok as gem already depends on it
|
56
|
-
require 'rest/wrappers/rest_client_wrapper'
|
57
|
-
|
@@ -51,7 +51,7 @@ module Rest
|
|
51
51
|
req_hash[:query] = req_hash[:params] if req_hash[:params]
|
52
52
|
#p req_hash
|
53
53
|
response = excon_request(url, req_hash)
|
54
|
-
rescue RestClient::Exception => ex
|
54
|
+
rescue Rest::RestClient::Exception => ex
|
55
55
|
#p ex
|
56
56
|
raise ExconExceptionWrapper.new(ex)
|
57
57
|
end
|
@@ -75,7 +75,7 @@ module Rest
|
|
75
75
|
req_hash[:url] = url
|
76
76
|
to_json_parts(req_hash)
|
77
77
|
response = excon_request(url, req_hash)
|
78
|
-
rescue RestClient::Exception => ex
|
78
|
+
rescue Rest::RestClient::Exception => ex
|
79
79
|
raise HttpError.new(ex.response, ex.http_code)
|
80
80
|
end
|
81
81
|
response
|
@@ -87,7 +87,7 @@ module Rest
|
|
87
87
|
req_hash[:method] = :put
|
88
88
|
req_hash[:url] = url
|
89
89
|
response = excon_request(url, req_hash)
|
90
|
-
rescue RestClient::Exception => ex
|
90
|
+
rescue Rest::RestClient::Exception => ex
|
91
91
|
raise RestClientExceptionWrapper.new(ex)
|
92
92
|
end
|
93
93
|
response
|
@@ -111,7 +111,7 @@ module Rest
|
|
111
111
|
req_hash[:method] = :delete
|
112
112
|
req_hash[:url] = url
|
113
113
|
response = excon_request(url, req_hash)
|
114
|
-
rescue RestClient::Exception => ex
|
114
|
+
rescue Rest::RestClient::Exception => ex
|
115
115
|
raise RestClientExceptionWrapper.new(ex)
|
116
116
|
end
|
117
117
|
response
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Rest
|
4
|
+
module InternalClient
|
5
|
+
|
6
|
+
module AbstractResponse
|
7
|
+
|
8
|
+
attr_reader :net_http_res, :args
|
9
|
+
|
10
|
+
# HTTP status code
|
11
|
+
def code
|
12
|
+
@code ||= @net_http_res.code.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
# A hash of the headers, beautified with symbols and underscores.
|
16
|
+
# e.g. "Content-type" will become :content_type.
|
17
|
+
def headers
|
18
|
+
@headers ||= AbstractResponse.beautify_headers(@net_http_res.to_hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
# The raw headers.
|
22
|
+
def raw_headers
|
23
|
+
@raw_headers ||= @net_http_res.to_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
# Hash of cookies extracted from response headers
|
27
|
+
def cookies
|
28
|
+
@cookies ||= (self.headers[:set_cookie] || {}).inject({}) do |out, cookie_content|
|
29
|
+
out.merge parse_cookie(cookie_content)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return the default behavior corresponding to the response code:
|
34
|
+
# 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
|
35
|
+
def return! request = nil, result = nil, & block
|
36
|
+
if (200..207).include? code
|
37
|
+
self
|
38
|
+
elsif [301, 302, 307].include? code
|
39
|
+
unless [:get, :head].include? args[:method]
|
40
|
+
raise Exceptions::EXCEPTIONS_MAP[code].new(self, code)
|
41
|
+
else
|
42
|
+
follow_redirection(request, result, & block)
|
43
|
+
end
|
44
|
+
elsif code == 303
|
45
|
+
args[:method] = :get
|
46
|
+
args.delete :payload
|
47
|
+
follow_redirection(request, result, & block)
|
48
|
+
elsif Exceptions::EXCEPTIONS_MAP[code]
|
49
|
+
raise Exceptions::EXCEPTIONS_MAP[code].new(self, code)
|
50
|
+
else
|
51
|
+
raise RequestFailed.new(self, code)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_i
|
56
|
+
code
|
57
|
+
end
|
58
|
+
|
59
|
+
def description
|
60
|
+
"#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Follow a redirection
|
64
|
+
def follow_redirection request = nil, result = nil, & block
|
65
|
+
url = headers[:location]
|
66
|
+
if url !~ /^http/
|
67
|
+
url = URI.parse(args[:url]).merge(url).to_s
|
68
|
+
end
|
69
|
+
args[:url] = url
|
70
|
+
if request
|
71
|
+
if request.max_redirects == 0
|
72
|
+
raise MaxRedirectsReached
|
73
|
+
end
|
74
|
+
args[:password] = request.password
|
75
|
+
args[:user] = request.user
|
76
|
+
args[:headers] = request.headers
|
77
|
+
args[:max_redirects] = request.max_redirects - 1
|
78
|
+
# pass any cookie set in the result
|
79
|
+
if result && result['set-cookie']
|
80
|
+
args[:headers][:cookies] = (args[:headers][:cookies] || {}).merge(parse_cookie(result['set-cookie']))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
Request.execute args, &block
|
84
|
+
end
|
85
|
+
|
86
|
+
def AbstractResponse.beautify_headers(headers)
|
87
|
+
headers.inject({}) do |out, (key, value)|
|
88
|
+
out[key.gsub(/-/, '_').downcase.to_sym] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
|
89
|
+
out
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
# Parse a cookie value and return its content in an Hash
|
96
|
+
def parse_cookie cookie_content
|
97
|
+
out = {}
|
98
|
+
CGI::Cookie::parse(cookie_content).each do |key, cookie|
|
99
|
+
unless ['expires', 'path'].include? key
|
100
|
+
out[CGI::escape(key)] = cookie.value[0] ? (CGI::escape(cookie.value[0]) || '') : ''
|
101
|
+
end
|
102
|
+
end
|
103
|
+
out
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module Rest
|
2
|
+
module InternalClient
|
3
|
+
|
4
|
+
STATUSES = {100 => 'Continue',
|
5
|
+
101 => 'Switching Protocols',
|
6
|
+
102 => 'Processing', #WebDAV
|
7
|
+
|
8
|
+
200 => 'OK',
|
9
|
+
201 => 'Created',
|
10
|
+
202 => 'Accepted',
|
11
|
+
203 => 'Non-Authoritative Information', # http/1.1
|
12
|
+
204 => 'No Content',
|
13
|
+
205 => 'Reset Content',
|
14
|
+
206 => 'Partial Content',
|
15
|
+
207 => 'Multi-Status', #WebDAV
|
16
|
+
|
17
|
+
300 => 'Multiple Choices',
|
18
|
+
301 => 'Moved Permanently',
|
19
|
+
302 => 'Found',
|
20
|
+
303 => 'See Other', # http/1.1
|
21
|
+
304 => 'Not Modified',
|
22
|
+
305 => 'Use Proxy', # http/1.1
|
23
|
+
306 => 'Switch Proxy', # no longer used
|
24
|
+
307 => 'Temporary Redirect', # http/1.1
|
25
|
+
|
26
|
+
400 => 'Bad Request',
|
27
|
+
401 => 'Unauthorized',
|
28
|
+
402 => 'Payment Required',
|
29
|
+
403 => 'Forbidden',
|
30
|
+
404 => 'Resource Not Found',
|
31
|
+
405 => 'Method Not Allowed',
|
32
|
+
406 => 'Not Acceptable',
|
33
|
+
407 => 'Proxy Authentication Required',
|
34
|
+
408 => 'Request Timeout',
|
35
|
+
409 => 'Conflict',
|
36
|
+
410 => 'Gone',
|
37
|
+
411 => 'Length Required',
|
38
|
+
412 => 'Precondition Failed',
|
39
|
+
413 => 'Request Entity Too Large',
|
40
|
+
414 => 'Request-URI Too Long',
|
41
|
+
415 => 'Unsupported Media Type',
|
42
|
+
416 => 'Requested Range Not Satisfiable',
|
43
|
+
417 => 'Expectation Failed',
|
44
|
+
418 => 'I\'m A Teapot',
|
45
|
+
421 => 'Too Many Connections From This IP',
|
46
|
+
422 => 'Unprocessable Entity', #WebDAV
|
47
|
+
423 => 'Locked', #WebDAV
|
48
|
+
424 => 'Failed Dependency', #WebDAV
|
49
|
+
425 => 'Unordered Collection', #WebDAV
|
50
|
+
426 => 'Upgrade Required',
|
51
|
+
449 => 'Retry With', #Microsoft
|
52
|
+
450 => 'Blocked By Windows Parental Controls', #Microsoft
|
53
|
+
|
54
|
+
500 => 'Internal Server Error',
|
55
|
+
501 => 'Not Implemented',
|
56
|
+
502 => 'Bad Gateway',
|
57
|
+
503 => 'Service Unavailable',
|
58
|
+
504 => 'Gateway Timeout',
|
59
|
+
505 => 'HTTP Version Not Supported',
|
60
|
+
506 => 'Variant Also Negotiates',
|
61
|
+
507 => 'Insufficient Storage', #WebDAV
|
62
|
+
509 => 'Bandwidth Limit Exceeded', #Apache
|
63
|
+
510 => 'Not Extended'}
|
64
|
+
|
65
|
+
# Compatibility : make the Response act like a Net::HTTPResponse when needed
|
66
|
+
module ResponseForException
|
67
|
+
def method_missing symbol, *args
|
68
|
+
if net_http_res.respond_to? symbol
|
69
|
+
warn "[warning] The response contained in an InternalClient::Exception is now a InternalClient::Response instead of a Net::HTTPResponse, please update your code"
|
70
|
+
net_http_res.send symbol, *args
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# This is the base InternalClient exception class. Rescue it if you want to
|
78
|
+
# catch any exception that your request might raise
|
79
|
+
# You can get the status code by e.http_code, or see anything about the
|
80
|
+
# response via e.response.
|
81
|
+
# For example, the entire result body (which is
|
82
|
+
# probably an HTML error page) is e.response.
|
83
|
+
class Exception < RuntimeError
|
84
|
+
attr_accessor :response
|
85
|
+
attr_writer :message
|
86
|
+
|
87
|
+
def initialize response = nil, initial_response_code = nil
|
88
|
+
@response = response
|
89
|
+
@message = nil
|
90
|
+
@initial_response_code = initial_response_code
|
91
|
+
|
92
|
+
# compatibility: this make the exception behave like a Net::HTTPResponse
|
93
|
+
response.extend ResponseForException if response
|
94
|
+
end
|
95
|
+
|
96
|
+
def http_code
|
97
|
+
# return integer for compatibility
|
98
|
+
if @response
|
99
|
+
@response.code.to_i
|
100
|
+
else
|
101
|
+
@initial_response_code
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def http_body
|
106
|
+
@response.body if @response
|
107
|
+
end
|
108
|
+
|
109
|
+
def inspect
|
110
|
+
"#{message}: #{http_body}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_s
|
114
|
+
inspect
|
115
|
+
end
|
116
|
+
|
117
|
+
def message
|
118
|
+
@message || self.class.name
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
# Compatibility
|
124
|
+
class ExceptionWithResponse < Exception
|
125
|
+
end
|
126
|
+
|
127
|
+
# The request failed with an error code not managed by the code
|
128
|
+
class RequestFailed < ExceptionWithResponse
|
129
|
+
|
130
|
+
def message
|
131
|
+
"HTTP status code #{http_code}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_s
|
135
|
+
message
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
140
|
+
module Exceptions
|
141
|
+
# Map http status codes to the corresponding exception class
|
142
|
+
EXCEPTIONS_MAP = {}
|
143
|
+
end
|
144
|
+
|
145
|
+
STATUSES.each_pair do |code, message|
|
146
|
+
|
147
|
+
# Compatibility
|
148
|
+
superclass = ([304, 401, 404].include? code) ? ExceptionWithResponse : RequestFailed
|
149
|
+
klass = Class.new(superclass) do
|
150
|
+
send(:define_method, :message) { "#{http_code ? "#{http_code} " : ''}#{message}" }
|
151
|
+
end
|
152
|
+
klass_constant = const_set message.delete(' \-\''), klass
|
153
|
+
Exceptions::EXCEPTIONS_MAP[code] = klass_constant
|
154
|
+
end
|
155
|
+
|
156
|
+
# A redirect was encountered; caught by execute to retry with the new url.
|
157
|
+
class Redirect < Exception
|
158
|
+
|
159
|
+
def message
|
160
|
+
'Redirect'
|
161
|
+
end
|
162
|
+
|
163
|
+
attr_accessor :url
|
164
|
+
|
165
|
+
def initialize(url)
|
166
|
+
@url = url
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class MaxRedirectsReached < Exception
|
171
|
+
def message
|
172
|
+
'Maximum number of redirect reached'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# The server broke the connection prior to the request completing. Usually
|
177
|
+
# this means it crashed, or sometimes that your network connection was
|
178
|
+
# severed before it could complete.
|
179
|
+
class ServerBrokeConnection < Exception
|
180
|
+
def initialize(message = 'Server broke connection')
|
181
|
+
super nil, nil
|
182
|
+
self.message = message
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class SSLCertificateNotVerified < Exception
|
187
|
+
def initialize(message)
|
188
|
+
super nil, nil
|
189
|
+
self.message = message
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|