Skip to content

Commit 71ba242

Browse files
authored
Merge pull request #3174 from sap-contributions/httpclient-socket-connect-timeout
Patch HTTPClient to accept socket_connect_timeout
2 parents 1f94310 + 274620d commit 71ba242

File tree

5 files changed

+161
-101
lines changed

5 files changed

+161
-101
lines changed

lib/diego/client.rb

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
require 'diego/bbs/bbs'
22
require 'diego/errors'
33
require 'diego/routes'
4+
require 'http/httpclient'
45

56
module Diego
67
class Client
78
PROTOBUF_HEADER = { 'Content-Type'.freeze => 'application/x-protobuf'.freeze }.freeze
89

910
def initialize(url:, ca_cert_file:, client_cert_file:, client_key_file:,
10-
connect_timeout:, send_timeout:, receive_timeout:)
11+
connect_timeout:, send_timeout:, receive_timeout:)
1112
ENV['PB_IGNORE_DEPRECATIONS'] ||= 'true'
1213
@client = build_client(
1314
url,
@@ -24,7 +25,7 @@ def ping
2425
client.post(Routes::PING)
2526
end
2627

27-
validate_status!(response: response, statuses: [200])
28+
validate_status_200!(response)
2829
protobuf_decode!(response.body, Bbs::Models::PingResponse)
2930
end
3031

@@ -35,7 +36,7 @@ def upsert_domain(domain:, ttl:)
3536
client.post(Routes::UPSERT_DOMAIN, request, PROTOBUF_HEADER)
3637
end
3738

38-
validate_status!(response: response, statuses: [200])
39+
validate_status_200!(response)
3940
protobuf_decode!(response.body, Bbs::Models::UpsertDomainResponse)
4041
end
4142

@@ -46,7 +47,7 @@ def desire_task(task_definition:, domain:, task_guid:)
4647
client.post(Routes::DESIRE_TASK, request, PROTOBUF_HEADER)
4748
end
4849

49-
validate_status!(response: response, statuses: [200])
50+
validate_status_200!(response)
5051
protobuf_decode!(response.body, Bbs::Models::TaskLifecycleResponse)
5152
end
5253

@@ -57,7 +58,7 @@ def task_by_guid(task_guid)
5758
client.post(Routes::TASK_BY_GUID, request, PROTOBUF_HEADER)
5859
end
5960

60-
validate_status!(response: response, statuses: [200])
61+
validate_status_200!(response)
6162
protobuf_decode!(response.body, Bbs::Models::TaskResponse)
6263
end
6364

@@ -68,7 +69,7 @@ def tasks(domain: '', cell_id: '')
6869
client.post(Routes::LIST_TASKS, request, PROTOBUF_HEADER)
6970
end
7071

71-
validate_status!(response: response, statuses: [200])
72+
validate_status_200!(response)
7273
protobuf_decode!(response.body, Bbs::Models::TasksResponse)
7374
end
7475

@@ -79,7 +80,7 @@ def cancel_task(task_guid)
7980
client.post(Routes::CANCEL_TASK, request, PROTOBUF_HEADER)
8081
end
8182

82-
validate_status!(response: response, statuses: [200])
83+
validate_status_200!(response)
8384
protobuf_decode!(response.body, Bbs::Models::TaskLifecycleResponse)
8485
end
8586

@@ -90,7 +91,7 @@ def desire_lrp(lrp)
9091
client.post(Routes::DESIRE_LRP, request, PROTOBUF_HEADER)
9192
end
9293

93-
validate_status!(response: response, statuses: [200])
94+
validate_status_200!(response)
9495
protobuf_decode!(response.body, Bbs::Models::DesiredLRPLifecycleResponse)
9596
end
9697

@@ -101,7 +102,7 @@ def desired_lrp_by_process_guid(process_guid)
101102
client.post(Routes::DESIRED_LRP_BY_PROCESS_GUID, request, PROTOBUF_HEADER)
102103
end
103104

104-
validate_status!(response: response, statuses: [200])
105+
validate_status_200!(response)
105106
protobuf_decode!(response.body, Bbs::Models::DesiredLRPResponse)
106107
end
107108

@@ -112,7 +113,7 @@ def update_desired_lrp(process_guid, lrp_update)
112113
client.post(Routes::UPDATE_DESIRED_LRP, request, PROTOBUF_HEADER)
113114
end
114115

115-
validate_status!(response: response, statuses: [200])
116+
validate_status_200!(response)
116117
protobuf_decode!(response.body, Bbs::Models::DesiredLRPLifecycleResponse)
117118
end
118119

@@ -123,7 +124,7 @@ def remove_desired_lrp(process_guid)
123124
client.post(Routes::REMOVE_DESIRED_LRP, request, PROTOBUF_HEADER)
124125
end
125126

126-
validate_status!(response: response, statuses: [200])
127+
validate_status_200!(response)
127128
protobuf_decode!(response.body, Bbs::Models::DesiredLRPLifecycleResponse)
128129
end
129130

@@ -134,7 +135,7 @@ def retire_actual_lrp(actual_lrp_key)
134135
client.post(Routes::RETIRE_ACTUAL_LRP, request, PROTOBUF_HEADER)
135136
end
136137

137-
validate_status!(response: response, statuses: [200])
138+
validate_status_200!(response)
138139
protobuf_decode!(response.body, Bbs::Models::ActualLRPLifecycleResponse)
139140
end
140141

@@ -145,7 +146,7 @@ def desired_lrp_scheduling_infos(domain)
145146
client.post(Routes::DESIRED_LRP_SCHEDULING_INFOS, request, PROTOBUF_HEADER)
146147
end
147148

148-
validate_status!(response: response, statuses: [200])
149+
validate_status_200!(response)
149150
protobuf_decode!(response.body, Bbs::Models::DesiredLRPSchedulingInfosResponse)
150151
end
151152

@@ -156,7 +157,7 @@ def actual_lrps_by_process_guid(process_guid)
156157
client.post(Routes::ACTUAL_LRPS, request, PROTOBUF_HEADER)
157158
end
158159

159-
validate_status!(response: response, statuses: [200])
160+
validate_status_200!(response)
160161
protobuf_decode!(response.body, Bbs::Models::ActualLRPsResponse)
161162
end
162163

@@ -180,8 +181,8 @@ def protobuf_encode!(hash, protobuf_message_class)
180181
raise EncodeError.new(e.message)
181182
end
182183

183-
def validate_status!(response:, statuses:)
184-
raise ResponseError.new("failed with status: #{response.status}, body: #{response.body}") unless statuses.include?(response.status)
184+
def validate_status_200!(response)
185+
raise ResponseError.new("failed with status: #{response.status}, body: #{response.body}") unless response.status == 200
185186
end
186187

187188
def protobuf_decode!(message, protobuf_decoder)
@@ -191,11 +192,12 @@ def protobuf_decode!(message, protobuf_decoder)
191192
end
192193

193194
def build_client(url, ca_cert_file, client_cert_file, client_key_file,
194-
connect_timeout, send_timeout, receive_timeout)
195-
client = HTTPClient.new(base_url: url)
196-
client.connect_timeout = connect_timeout
197-
client.send_timeout = send_timeout
198-
client.receive_timeout = receive_timeout
195+
connect_timeout, send_timeout, receive_timeout)
196+
client = HTTPClient.new(base_url: url)
197+
client.socket_connect_timeout = connect_timeout / 2
198+
client.connect_timeout = connect_timeout
199+
client.send_timeout = send_timeout
200+
client.receive_timeout = receive_timeout
199201
client.ssl_config.set_client_cert_file(client_cert_file, client_key_file)
200202
client.ssl_config.set_trust_ca(ca_cert_file)
201203
client

lib/http/httpclient.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
require 'httpclient'
2+
3+
module HTTPClientMonkeyPatch
4+
module SocketConnectTimeout
5+
attr_reader :socket_connect_timeout
6+
7+
def socket_connect_timeout=(timeout)
8+
@socket_connect_timeout = timeout
9+
end
10+
end
11+
12+
module TCPSocketWithConnectTimeout
13+
def create_socket(host, port)
14+
@debug_dev << "! CONNECT TO #{host}:#{port}\n" if @debug_dev
15+
clean_host = host.delete('[]')
16+
if @socket_local == HTTPClient::Site::EMPTY
17+
socket = TCPSocket.new(clean_host, port, connect_timeout: @client.socket_connect_timeout)
18+
else
19+
clean_local = @socket_local.host.delete('[]')
20+
socket = TCPSocket.new(clean_host, port, clean_local, @socket_local.port, connect_timeout: @client.socket_connect_timeout)
21+
end
22+
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) if @tcp_keepalive
23+
if @debug_dev
24+
@debug_dev << "! CONNECTION ESTABLISHED\n"
25+
socket.extend(HTTPClient::DebugSocket)
26+
socket.debug_dev = @debug_dev
27+
end
28+
socket
29+
rescue SystemCallError, SocketError => e
30+
raise e.new(e.message + " (#{host}:#{port})")
31+
end
32+
end
33+
end
34+
35+
class HTTPClient
36+
prepend HTTPClientMonkeyPatch::SocketConnectTimeout
37+
end
38+
39+
class HTTPClient::Session
40+
prepend HTTPClientMonkeyPatch::TCPSocketWithConnectTimeout
41+
end

0 commit comments

Comments
 (0)