tickethub 0.3.51 → 0.3.52
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tickethub/connection.rb +66 -32
- data/lib/tickethub/exceptions.rb +44 -17
- data/lib/tickethub/helpers.rb +33 -1
- data/lib/tickethub/request.rb +72 -51
- data/lib/tickethub/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c3d2fbee50f8b1649c00ce062145feba07d6ad1
|
4
|
+
data.tar.gz: e5ab1ddb6e9503d8d3a7b77c834f04223765f96b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e148ff6eede8074c3b76be0f36f69f79c5143fcf20bba3f6ef79d2784c7c5a90dceebacc38543ff7b8bab5b141be45877f2d0d243fa197442606d5fda4ed639f
|
7
|
+
data.tar.gz: 67e18750bd49ba334f9092d31caa2642e412b9a8d67f0d654a27698608fcbd42deb867d6f7bf4f8b356d09ffa8545b1b5eb96ba258280f58f6e01ce5b5a0c455
|
data/lib/tickethub/connection.rb
CHANGED
@@ -40,6 +40,10 @@ module Tickethub
|
|
40
40
|
request(:head, path, headers, &block)
|
41
41
|
end
|
42
42
|
|
43
|
+
def put(path, body = '', headers = {}, &block)
|
44
|
+
request(:put, path, body, headers, &block)
|
45
|
+
end
|
46
|
+
|
43
47
|
def patch(path, body = '', headers = {}, &block)
|
44
48
|
request(:patch, path, body, headers, &block)
|
45
49
|
end
|
@@ -50,48 +54,72 @@ module Tickethub
|
|
50
54
|
|
51
55
|
protected
|
52
56
|
|
57
|
+
def request=(request)
|
58
|
+
@request = request
|
59
|
+
end
|
60
|
+
|
53
61
|
# Makes a request to the remote service.
|
54
62
|
def request(method, path, *arguments)
|
55
63
|
response = http.send(method, path, *arguments)
|
64
|
+
response.uri = URI.join(endpoint, path)
|
65
|
+
|
56
66
|
handle_response(response)
|
57
67
|
|
58
|
-
rescue Timeout::Error => e
|
59
|
-
raise TimeoutError.new(e.message)
|
68
|
+
rescue Timeout::Error, Net::OpenTimeout => e
|
69
|
+
raise TimeoutError.new(@request, e.message)
|
60
70
|
rescue OpenSSL::SSL::SSLError => e
|
61
|
-
raise SSLError.new(e.message)
|
71
|
+
raise SSLError.new(@request, e.message)
|
72
|
+
rescue SocketError,
|
73
|
+
EOFError,
|
74
|
+
Net::HTTPBadResponse,
|
75
|
+
Net::HTTPHeaderSyntaxError,
|
76
|
+
Net::HTTPServerException,
|
77
|
+
Net::ProtocolError,
|
78
|
+
Errno::ECONNABORTED,
|
79
|
+
Errno::ECONNREFUSED,
|
80
|
+
Errno::ECONNRESET,
|
81
|
+
Errno::ETIMEDOUT,
|
82
|
+
Errno::ENETUNREACH,
|
83
|
+
Errno::EHOSTUNREACH,
|
84
|
+
Errno::EINVAL,
|
85
|
+
Errno::ENOPROTOOPT => e
|
86
|
+
raise ErrnoError.new(@request, e.message)
|
87
|
+
rescue Zlib::DataError,
|
88
|
+
Zlib::BufError => e
|
89
|
+
raise ZlibError.new(@request, e.message)
|
62
90
|
end
|
63
91
|
|
64
92
|
# Handles response and error codes from the remote service.
|
65
93
|
def handle_response(response)
|
66
94
|
case response.code.to_i
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
+
when 200...299
|
96
|
+
response
|
97
|
+
when 300..399
|
98
|
+
raise Redirection.new(@request, response)
|
99
|
+
when 400
|
100
|
+
raise BadRequest.new(@request, response)
|
101
|
+
when 401
|
102
|
+
raise UnauthorizedAccess.new(@request, response)
|
103
|
+
when 403
|
104
|
+
raise ForbiddenAccess.new(@request, response)
|
105
|
+
when 404
|
106
|
+
raise ResourceNotFound.new(@request, response)
|
107
|
+
when 405
|
108
|
+
raise MethodNotAllowed.new(@request, response)
|
109
|
+
when 409
|
110
|
+
raise ResourceConflict.new(@request, response)
|
111
|
+
when 410
|
112
|
+
raise ResourceGone.new(@request, response)
|
113
|
+
when 422
|
114
|
+
raise ResourceInvalid.new(@request, response)
|
115
|
+
when 401...500
|
116
|
+
raise ClientError.new(@request, response)
|
117
|
+
when 500...600
|
118
|
+
raise ServerError.new(@request, response)
|
119
|
+
else
|
120
|
+
raise ResponseError.new(
|
121
|
+
@request, response, "Unknown response code: #{response.code}"
|
122
|
+
)
|
95
123
|
end
|
96
124
|
end
|
97
125
|
|
@@ -113,7 +141,13 @@ module Tickethub
|
|
113
141
|
|
114
142
|
def configure_http(http)
|
115
143
|
http = apply_ssl_options(http)
|
116
|
-
|
144
|
+
|
145
|
+
# Net::HTTP timeouts default to 60 seconds.
|
146
|
+
if timeout
|
147
|
+
http.open_timeout = timeout
|
148
|
+
http.read_timeout = timeout
|
149
|
+
end
|
150
|
+
|
117
151
|
http
|
118
152
|
end
|
119
153
|
|
data/lib/tickethub/exceptions.rb
CHANGED
@@ -1,44 +1,65 @@
|
|
1
1
|
module Tickethub
|
2
|
-
class
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :request
|
4
|
+
|
5
|
+
def initialize(request = nil, message = nil)
|
6
|
+
super(message)
|
7
|
+
@request = request
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
ConnectionError = Error
|
12
|
+
RequestError = Error
|
13
|
+
|
14
|
+
class ResponseError < Error
|
3
15
|
attr_reader :response
|
4
16
|
|
5
|
-
def initialize(response, message = nil)
|
17
|
+
def initialize(request, response, message = nil)
|
18
|
+
super(request, message)
|
6
19
|
@response = response
|
7
|
-
@message = message
|
8
20
|
end
|
9
21
|
|
10
22
|
def to_s
|
11
23
|
message = "Failed."
|
12
24
|
message << " Response code = #{response.code}." if response.respond_to?(:code)
|
13
25
|
message << " Response message = #{response.message}." if response.respond_to?(:message)
|
14
|
-
|
26
|
+
|
27
|
+
if response.respond_to?(:body)
|
28
|
+
# Error messages need to be in UTF-8
|
29
|
+
body = response.body.dup.to_s
|
30
|
+
body = body.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?')
|
31
|
+
message << " Response Body = #{body}."
|
32
|
+
end
|
33
|
+
|
15
34
|
message
|
16
35
|
end
|
17
36
|
end
|
18
37
|
|
19
38
|
# Raised when a Timeout::Error occurs.
|
20
|
-
class TimeoutError <
|
21
|
-
def initialize(message)
|
22
|
-
@message = message
|
23
|
-
end
|
24
|
-
def to_s; @message ;end
|
39
|
+
class TimeoutError < RequestError
|
25
40
|
end
|
26
41
|
|
27
42
|
# Raised when a OpenSSL::SSL::SSLError occurs.
|
28
|
-
class SSLError <
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
43
|
+
class SSLError < RequestError
|
44
|
+
end
|
45
|
+
|
46
|
+
class ErrnoError < RequestError
|
47
|
+
end
|
48
|
+
|
49
|
+
class ZlibError < RequestError
|
33
50
|
end
|
34
51
|
|
35
52
|
# 3xx Redirection
|
36
|
-
class Redirection <
|
53
|
+
class Redirection < ResponseError # :nodoc:
|
54
|
+
def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
|
55
|
+
end
|
56
|
+
|
57
|
+
class RedirectionLoop < ResponseError # :nodoc:
|
37
58
|
def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
|
38
59
|
end
|
39
60
|
|
40
61
|
# 4xx Client Error
|
41
|
-
class ClientError <
|
62
|
+
class ClientError < ResponseError; end # :nodoc:
|
42
63
|
|
43
64
|
# 400 Bad Request
|
44
65
|
class BadRequest < ClientError; end # :nodoc
|
@@ -52,11 +73,17 @@ module Tickethub
|
|
52
73
|
# 404 Not Found
|
53
74
|
class ResourceNotFound < ClientError; end # :nodoc:
|
54
75
|
|
76
|
+
# 409 Conflict
|
77
|
+
class ResourceConflict < ClientError; end # :nodoc:
|
78
|
+
|
79
|
+
# 410 Gone
|
80
|
+
class ResourceGone < ClientError; end # :nodoc:
|
81
|
+
|
55
82
|
# 422 Invalid
|
56
83
|
class ResourceInvalid < ClientError; end # :nodoc:
|
57
84
|
|
58
85
|
# 5xx Server Error
|
59
|
-
class ServerError <
|
86
|
+
class ServerError < ResponseError; end # :nodoc:
|
60
87
|
|
61
88
|
# 405 Method Not Allowed
|
62
89
|
class MethodNotAllowed < ClientError # :nodoc:
|
data/lib/tickethub/helpers.rb
CHANGED
@@ -10,6 +10,14 @@ module Tickethub
|
|
10
10
|
value.to_s.split('_').map {|w| w.capitalize }.join
|
11
11
|
end
|
12
12
|
|
13
|
+
def deep_merge(hash, other_hash)
|
14
|
+
hash.merge(other_hash) do |key, oldval, newval|
|
15
|
+
oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
|
16
|
+
newval = newval.to_hash if newval.respond_to?(:to_hash)
|
17
|
+
oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? deep_merge(oldval, newval) : newval
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
13
21
|
# Stolen from Rack:
|
14
22
|
|
15
23
|
DEFAULT_SEP = /[&;] */n
|
@@ -30,6 +38,22 @@ module Tickethub
|
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
41
|
+
def to_url_param(value, prefix = nil)
|
42
|
+
case value
|
43
|
+
when Array
|
44
|
+
value.map { |v|
|
45
|
+
to_url_param(v, "#{prefix}[]")
|
46
|
+
}.join("&")
|
47
|
+
when Hash
|
48
|
+
value.map { |k, v|
|
49
|
+
to_url_param(v, prefix ? "#{prefix}[#{uri_escape(k)}]" : uri_escape(k))
|
50
|
+
}.join("&")
|
51
|
+
else
|
52
|
+
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
53
|
+
"#{prefix}=#{uri_escape(value)}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
33
57
|
def from_param(param)
|
34
58
|
Rack::Utils.parse_nested_query(param)
|
35
59
|
(value || '').split('&').each do |res|
|
@@ -51,7 +75,15 @@ module Tickethub
|
|
51
75
|
end
|
52
76
|
|
53
77
|
def escape(s)
|
54
|
-
URI.encode_www_form_component(s)
|
78
|
+
URI.encode_www_form_component(s.to_s)
|
79
|
+
end
|
80
|
+
|
81
|
+
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
|
82
|
+
|
83
|
+
def uri_escape(s)
|
84
|
+
s.to_s.gsub(ESCAPE_RE) {|match|
|
85
|
+
'%' + match.unpack('H2' * match.bytesize).join('%').upcase
|
86
|
+
}.tr(' ', '+')
|
55
87
|
end
|
56
88
|
|
57
89
|
if defined?(::Encoding)
|
data/lib/tickethub/request.rb
CHANGED
@@ -2,12 +2,12 @@ require 'securerandom'
|
|
2
2
|
|
3
3
|
module Tickethub
|
4
4
|
class Request
|
5
|
-
|
6
5
|
attr_reader :options, :format, :url
|
7
|
-
attr_accessor :params, :body, :method, :headers
|
8
6
|
|
9
|
-
|
10
|
-
|
7
|
+
attr_accessor :params, :body, :method, :headers,
|
8
|
+
:proxy, :user, :password, :retries,
|
9
|
+
:auth_type, :timeout, :ssl_options,
|
10
|
+
:max_attempts, :follow_redirection
|
11
11
|
|
12
12
|
def initialize(url, options = {})
|
13
13
|
@url = url.to_s
|
@@ -15,16 +15,19 @@ module Tickethub
|
|
15
15
|
@retries = 3
|
16
16
|
@timeout = 10
|
17
17
|
|
18
|
-
@options =
|
18
|
+
@options = {
|
19
|
+
:method => :get,
|
20
|
+
:params => {},
|
21
|
+
:headers => {},
|
22
|
+
:format => :form,
|
23
|
+
:max_attempts => 5,
|
24
|
+
:follow_redirection => true
|
25
|
+
}.merge(options)
|
26
|
+
|
19
27
|
@options.each do |key, val|
|
20
28
|
method = "#{key}="
|
21
29
|
send(method, val) if respond_to?(method)
|
22
30
|
end
|
23
|
-
|
24
|
-
self.method ||= :get
|
25
|
-
self.params ||= {}
|
26
|
-
self.headers ||= {}
|
27
|
-
self.format ||= :form
|
28
31
|
end
|
29
32
|
|
30
33
|
def format=(mime_or_format)
|
@@ -46,50 +49,86 @@ module Tickethub
|
|
46
49
|
@uri = URI.parse(url)
|
47
50
|
@uri.path = '/' if @uri.path.empty?
|
48
51
|
|
49
|
-
if @uri.query
|
50
|
-
@params.merge!(Helpers.from_param(@uri.query))
|
51
|
-
@uri.query = nil
|
52
|
-
end
|
53
|
-
|
54
52
|
@uri
|
55
53
|
end
|
56
54
|
|
55
|
+
def uri_params
|
56
|
+
uri.query ? Helpers.from_param(uri.query) : {}
|
57
|
+
end
|
58
|
+
|
57
59
|
def path
|
58
60
|
uri.path
|
59
61
|
end
|
60
62
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
def query_path
|
64
|
+
query_path = path.dup
|
65
|
+
query_params = uri_params.dup
|
66
|
+
query_params.merge!(params) unless encoded?
|
67
|
+
|
68
|
+
if query_params.any?
|
69
|
+
query_path += '?' + Helpers.to_url_param(query_params)
|
66
70
|
end
|
67
71
|
|
68
|
-
|
72
|
+
query_path
|
73
|
+
end
|
69
74
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
rescue Redirection => error
|
74
|
-
raise error unless error.response['Location']
|
75
|
-
location = URI.parse(error.response['Location'])
|
75
|
+
def encoded?
|
76
|
+
[:post, :put].include?(method)
|
77
|
+
end
|
76
78
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
79
|
+
def encoded
|
80
|
+
params.any? ? format.encode(params) : body
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
+
def execute
|
84
|
+
with_redirection do
|
85
|
+
if encoded?
|
86
|
+
result = connection.send(method, query_path, encoded, build_headers)
|
87
|
+
else
|
88
|
+
result = connection.send(method, query_path, build_headers)
|
89
|
+
end
|
90
|
+
|
91
|
+
Response.new(result, uri)
|
92
|
+
end
|
93
|
+
rescue ServerError, RequestError => err
|
94
|
+
raise err if (@retries -= 1) == 0
|
83
95
|
execute
|
84
96
|
end
|
85
97
|
|
86
98
|
protected
|
87
99
|
|
100
|
+
def with_redirection(&block)
|
101
|
+
attempts = 1
|
102
|
+
|
103
|
+
begin
|
104
|
+
yield
|
105
|
+
rescue Redirection => error
|
106
|
+
raise error unless follow_redirection
|
107
|
+
|
108
|
+
attempts += 1
|
109
|
+
|
110
|
+
raise error unless error.response['Location']
|
111
|
+
raise RedirectionLoop.new(self, error.response) if attempts > max_attempts
|
112
|
+
|
113
|
+
location = error.response['Location'].scrub
|
114
|
+
location = URI.parse(location)
|
115
|
+
|
116
|
+
# Path is relative
|
117
|
+
unless location.host
|
118
|
+
location = URI.join(uri, location)
|
119
|
+
end
|
120
|
+
|
121
|
+
self.url = location.to_s
|
122
|
+
retry
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
88
126
|
def connection
|
89
127
|
Connection.new(uri,
|
90
128
|
:proxy => proxy,
|
91
129
|
:timeout => timeout,
|
92
|
-
:ssl_options => ssl_options
|
130
|
+
:ssl_options => ssl_options,
|
131
|
+
:request => self
|
93
132
|
)
|
94
133
|
end
|
95
134
|
|
@@ -117,23 +156,5 @@ module Tickethub
|
|
117
156
|
.merge(headers)
|
118
157
|
.merge('X-Request-ID' => @id)
|
119
158
|
end
|
120
|
-
|
121
|
-
def query_path
|
122
|
-
query_path = path
|
123
|
-
|
124
|
-
if params.any?
|
125
|
-
query_path += '?' + Helpers.to_param(params)
|
126
|
-
end
|
127
|
-
|
128
|
-
query_path
|
129
|
-
end
|
130
|
-
|
131
|
-
def encoded?
|
132
|
-
[:post, :patch].include?(method)
|
133
|
-
end
|
134
|
-
|
135
|
-
def encoded
|
136
|
-
params.any? ? format.encode(params) : body
|
137
|
-
end
|
138
159
|
end
|
139
160
|
end
|
data/lib/tickethub/version.rb
CHANGED