-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
connection.rb
169 lines (144 loc) · 4.59 KB
/
connection.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
require 'uri'
require 'net/http'
require 'net/https'
require 'benchmark'
module ActiveMerchant
class Connection
include NetworkConnectionRetries
MAX_RETRIES = 3
OPEN_TIMEOUT = 60
READ_TIMEOUT = 60
VERIFY_PEER = true
CA_FILE = File.expand_path('../certs/cacert.pem', File.dirname(__FILE__))
CA_PATH = nil
RETRY_SAFE = false
RUBY_184_POST_HEADERS = { "Content-Type" => "application/x-www-form-urlencoded" }
attr_accessor :endpoint
attr_accessor :open_timeout
attr_accessor :read_timeout
attr_accessor :verify_peer
attr_accessor :ssl_version
attr_accessor :ca_file
attr_accessor :ca_path
attr_accessor :pem
attr_accessor :pem_password
attr_accessor :wiredump_device
attr_accessor :logger
attr_accessor :tag
attr_accessor :ignore_http_status
attr_accessor :max_retries
attr_accessor :proxy_address
attr_accessor :proxy_port
def initialize(endpoint)
@endpoint = endpoint.is_a?(URI) ? endpoint : URI.parse(endpoint)
@open_timeout = OPEN_TIMEOUT
@read_timeout = READ_TIMEOUT
@retry_safe = RETRY_SAFE
@verify_peer = VERIFY_PEER
@ca_file = CA_FILE
@ca_path = CA_PATH
@max_retries = MAX_RETRIES
@ignore_http_status = false
@ssl_version = nil
@proxy_address = nil
@proxy_port = nil
end
def request(method, body, headers = {})
request_start = Time.now.to_f
retry_exceptions(:max_retries => max_retries, :logger => logger, :tag => tag) do
begin
info "connection_http_method=#{method.to_s.upcase} connection_uri=#{endpoint}", tag
result = nil
realtime = Benchmark.realtime do
result = case method
when :get
raise ArgumentError, "GET requests do not support a request body" if body
http.get(endpoint.request_uri, headers)
when :post
debug body
http.post(endpoint.request_uri, body, RUBY_184_POST_HEADERS.merge(headers))
when :put
debug body
http.put(endpoint.request_uri, body, headers)
when :delete
# It's kind of ambiguous whether the RFC allows bodies
# for DELETE requests. But Net::HTTP's delete method
# very unambiguously does not.
raise ArgumentError, "DELETE requests do not support a request body" if body
http.delete(endpoint.request_uri, headers)
else
raise ArgumentError, "Unsupported request method #{method.to_s.upcase}"
end
end
info "--> %d %s (%d %.4fs)" % [result.code, result.message, result.body ? result.body.length : 0, realtime], tag
debug result.body
result
end
end
ensure
info "connection_request_total_time=%.4fs" % [Time.now.to_f - request_start], tag
end
private
def http
http = Net::HTTP.new(endpoint.host, endpoint.port, proxy_address, proxy_port)
configure_debugging(http)
configure_timeouts(http)
configure_ssl(http)
configure_cert(http)
http
end
def configure_debugging(http)
http.set_debug_output(wiredump_device)
end
def configure_timeouts(http)
http.open_timeout = open_timeout
http.read_timeout = read_timeout
end
def configure_ssl(http)
return unless endpoint.scheme == "https"
http.use_ssl = true
http.ssl_version = ssl_version if ssl_version
if verify_peer
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = ca_file
http.ca_path = ca_path
else
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end
def configure_cert(http)
return if pem.blank?
http.cert = OpenSSL::X509::Certificate.new(pem)
if pem_password
http.key = OpenSSL::PKey::RSA.new(pem, pem_password)
else
http.key = OpenSSL::PKey::RSA.new(pem)
end
end
def handle_response(response)
if @ignore_http_status then
return response.body
else
case response.code.to_i
when 200...300
response.body
else
raise ResponseError.new(response)
end
end
end
def debug(message, tag = nil)
log(:debug, message, tag)
end
def info(message, tag = nil)
log(:info, message, tag)
end
def error(message, tag = nil)
log(:error, message, tag)
end
def log(level, message, tag)
message = "[#{tag}] #{message}" if tag
logger.send(level, message) if logger
end
end
end