Skip to content

Commit bc7e4c2

Browse files
Adding persistence connections buckets for ssl contexts (#22)
Adding persistence connections buckets for ssl contexts (#22)
1 parent 64af567 commit bc7e4c2

File tree

11 files changed

+155
-9
lines changed

11 files changed

+155
-9
lines changed

.rubocop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ AllCops:
1616
- gemfile/**/*
1717
Exclude:
1818
- vendor/**/*
19+
- spec/files/**/*
1920

2021
RSpec/SpecFilePathFormat:
2122
Enabled: false

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
ezclient (1.7.1)
4+
ezclient (1.7.2)
55
http (>= 4)
66

77
GEM

lib/ezclient/client.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ def request(verb, url, **options)
2828

2929
keep_alive_timeout = options.delete(:keep_alive)
3030
api_auth = options.delete(:api_auth)
31+
ssl_context = options[:ssl_context]
3132

3233
if keep_alive_timeout
33-
client = persistent_client_registry.for(url, timeout: keep_alive_timeout)
34+
client = persistent_client_registry.for(
35+
url, ssl_context: ssl_context, timeout: keep_alive_timeout
36+
)
3437
else
3538
client = HTTP::Client.new
3639
end

lib/ezclient/persistent_client_registry.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,31 @@ def initialize
55
self.registry = {}
66
end
77

8-
def for(url, timeout:)
8+
def for(url, ssl_context:, timeout:)
99
cleanup_registry!
10-
uri = HTTP::URI.parse(url)
11-
registry[uri.origin] ||= EzClient::PersistentClient.new(uri.origin, timeout)
10+
11+
origin = get_origin(url)
12+
registry[origin] ||= {}
13+
14+
ssl_bucket = ssl_context&.cert ? get_cert_sha256(ssl_context.cert) : nil
15+
registry[origin][ssl_bucket] ||= EzClient::PersistentClient.new(origin, timeout)
1216
end
1317

1418
private
1519

1620
attr_accessor :registry
1721

22+
def get_cert_sha256(cert)
23+
Digest::SHA256.hexdigest(cert.to_der)
24+
end
25+
26+
def get_origin(url)
27+
HTTP::URI.parse(url).origin
28+
end
29+
1830
def cleanup_registry!
19-
registry.delete_if { |_origin, client| client.timed_out? }
31+
registry.each_value do |ssl_buckets|
32+
ssl_buckets.delete_if { |_ssl_bucket, client| client.timed_out? }
33+
end
2034
end
2135
end

lib/ezclient/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module EzClient
4-
VERSION = "1.7.1"
4+
VERSION = "1.7.2"
55
end

spec/files/cert1/cert.pem

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDBzCCAe+gAwIBAgIUfinV8A6FiRyqX5ADPL13gzN5Q2YwDQYJKoZIhvcNAQEL
3+
BQAwEzERMA8GA1UEAwwIbXl0ZXN0Q0EwHhcNMjUwNTE1MTIxODE4WhcNMjYwNTE1
4+
MTIxODE4WjATMREwDwYDVQQDDAhteXRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQAD
5+
ggEPADCCAQoCggEBAKI5bLYi31jooJYjusgscCL0vcaH3pu1pyB3ajuLWjbjxaxf
6+
h1u+JH3vTQaxaSaP9K7hSfjtd0QO4xaopmZKP/kFTgp8juC8HQhzUlz51syp2I72
7+
AFKzmwnKiiQQh7mGHF2kWG5n8DjwY6F/7FohktTiUBBw1r/OypFGphVfz7iURNsU
8+
/iOpwK63zSdqOoSgai35s1AmlTBB0eoldM/Ju6rSF0x712Y6bL2cK3dl1V3yG3sd
9+
hXLkC9nOLnvOFUxyjXH/q4clvVblTP6IA+ez2EpIhkG4i+ZcEkIRY7YbH2GyFoxu
10+
FS12fiLAi48zIbe1yz0nkrJZZTTw9o16A7+JHfECAwEAAaNTMFEwHQYDVR0OBBYE
11+
FLyfG4zgydqWDtzyN1jpDBkn571MMB8GA1UdIwQYMBaAFLyfG4zgydqWDtzyN1jp
12+
DBkn571MMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE2Nzooz
13+
PJbBi1vUGl9EkRPHuzZFHBR2YZvUQiIfH5TTigV3SeN2JoYacFqzcj8U7tFDoro5
14+
i9VI89DJP+Kze2QADSkzR0o0mXb6HLDdJh+4/mGtWvkrMdhXW+Wr7i1x66jBmlrs
15+
2ea+gTVcefyOhYm8LgD2V9mowQ8+iq+iOzbyYLd+rqnWzymQHz6trMZG7sy64OXk
16+
tkzDH55eMjr34hi8mRlmfN/j7GAX+RnDVTI/kamIb8Yq/KJ0SmRIL8O5WdY2G85D
17+
h5lU7YdnmBiDMqHOZbWSFT5L2vVUGEmAbl6dFpWgA/+mgb/OkeshKtfQWcINBDpH
18+
Y6/1M+ULD7AFW4g=
19+
-----END CERTIFICATE-----

spec/files/cert1/key.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCiOWy2It9Y6KCW
3+
I7rILHAi9L3Gh96btacgd2o7i1o248WsX4dbviR9700GsWkmj/Su4Un47XdEDuMW
4+
qKZmSj/5BU4KfI7gvB0Ic1Jc+dbMqdiO9gBSs5sJyookEIe5hhxdpFhuZ/A48GOh
5+
f+xaIZLU4lAQcNa/zsqRRqYVX8+4lETbFP4jqcCut80najqEoGot+bNQJpUwQdHq
6+
JXTPybuq0hdMe9dmOmy9nCt3ZdVd8ht7HYVy5AvZzi57zhVMco1x/6uHJb1W5Uz+
7+
iAPns9hKSIZBuIvmXBJCEWO2Gx9hshaMbhUtdn4iwIuPMyG3tcs9J5KyWWU08PaN
8+
egO/iR3xAgMBAAECggEAB6YfANh/QPKDrd3vPuR6K2pwRJs1QmYWhFKfwkElZrdR
9+
zk6ZHoOGNh+ReW+7MOuyjQiyLkfzar9WnZkj8r3sqxnBBAAQVDrdFeqqwcJa9SlL
10+
Uh75xWx9XSu9BzXLUdKnuueWmYASRNEFgEDR8gRUEhsTTNnRL605AmVly9YJwIlp
11+
Ql/OMxdJFqmY8O8wEfyjYdWw7fk5JfqjAxcWwoZZjcXxrke8ue92hM1Z/pMDUBow
12+
0pWousx6UVbbw4etjB6GjyPzA0esQYxXRjGcEAMznne41SAsfWAggnChhuNhV+lA
13+
2GGRbCPLyck8Ce7K8UjY14bymUMMeVEpFXdedrh2lQKBgQDVfMbwrss4KNHwde0f
14+
IBe4fQLQjBvelUBwDDgdQVHUygL6TWzsRKAmLV+A1HzPFuch5+FQK08fJImtE2Ci
15+
xZPTAb5Nhs/S00W8UQLoH1L9O7g1nq7WxEKR08CJ8o7T+t3CMfqBlHLBx4jGf9HK
16+
NrjErK3mGA9BPEeGH9rzCqhFlQKBgQDCh1e3+3CBnBePlsfv3RIo40Cm2s/OjUVU
17+
jSawx14KZRtZUSa8bvU5J60AXDNsIG+9/kJuFm4fXNYCKo21l+jT271vxDrA5oFg
18+
Lr+DoiojmE7M9ZteR3zkOEnvjr3aANTcTkQ7k+M+2iY6V4SsCNhXl0d3W2QA2xv+
19+
zUG7Sssn7QKBgQCu+9BANLUjOeoiEzahfXeT4vtsnnq1bVZcwNc5u3FsXYwlR1MR
20+
MYqm4CfYe9I1F8upMduvD2CR4SvrredWY2Wv3UzzVJ2Ba2RMX4ZnZk1qfQmXAZLD
21+
PChoSM0XBLZnL8eWRcrTbS7GgFsugFQfT80Qf40l/PB8AwGJARFAhqq4JQKBgQCi
22+
nIC3S3jA37rSTTjVSffkNhPVZxRPlche5Z9yJzZ1eg9imnPHEPnszT3RD0HtITBH
23+
okPlwtpLXU+IgAn1wwbeEtJIm8CBgC6mOG3fm6+eEbPNoYI/TYMZQ/SKTMhndEp7
24+
3vEq3HUaFUHfg0lkhgBTOCKFo9/01zSPywUni15IAQKBgQDNGWS0hKS46jzM7MYh
25+
pwX5Dom/8QMbWuksRWX/bh5+5OhmPwH4aJTU8JFiMPrbtHoHfwcAYgrq746TiOd+
26+
VH/VSr8YiaKjaPJG44sfsxhw/blrrhUUxOZi5RHxa2dTA83TVphFbG4sCFgRKNnl
27+
bctg+wD5IZjsRbY1LHOY8tsqag==
28+
-----END PRIVATE KEY-----

spec/files/cert2/cert.pem

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDBzCCAe+gAwIBAgIUUX0xpjoENDArPfJpKuvoP8Mq5KswDQYJKoZIhvcNAQEL
3+
BQAwEzERMA8GA1UEAwwIbXl0ZXN0Q0EwHhcNMjUwNTE1MTIxOTA3WhcNMjYwNTE1
4+
MTIxOTA3WjATMREwDwYDVQQDDAhteXRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQAD
5+
ggEPADCCAQoCggEBAL212a7o5gL9wPf6jPqWN/nupPLaNJ8TQ0eqTpfkJw2Tk/Nu
6+
fO7+e92xCUzIFr1F5p61i3QoNil7S1F11s5JtuDEhjUsoyiWyt4NGJYOyTkoeLf8
7+
OAt1/vjypVLo8lqZHu5n9MaXW9BT4FyDVDcH8Bo2UKbP42PHdOOxllkhY4hyuC/o
8+
zxpnT5nqiC6Lwblu4IdqLQA7J2u+4ZESS6tY1N7tvFJvrDfp36SESABgV3KVhct2
9+
SAUZnwsM4lcIrx2Bt0FMU7Frwr3LpPl7Xg5tz93MPjDvlRwNStHoXm2ZGv6I6yIA
10+
PbQEh0ut+Z7cbBAVOaTmXUjzk2/tIqnyDjyhyOsCAwEAAaNTMFEwHQYDVR0OBBYE
11+
FL1iafEVzvkcSv+RnO/vT36uWvAFMB8GA1UdIwQYMBaAFL1iafEVzvkcSv+RnO/v
12+
T36uWvAFMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEXLP+/k
13+
1n/1S8AZOsmbaTiR+NBNCZx9JoGuqa5FZK/9cCchVd76bVPJLLu/mPBsLPHbNdhh
14+
3XrP+s6NyvJd4QlHnk6OFxtqZB+wYY43dWtaoJxRc1bS6+xvhB6XQo5P/+5bLkzP
15+
pc1Roc474SuldJ5im+D/xbEwGUHarpeKp/H1tKfYObUH3X0N6ZoyRLRePNNQceR9
16+
2M/jZ878Rft2itTWE5SWvjexz2qK1mniyocEndvAWOh/4B4AV9jsXw2wxYJ6vH3l
17+
EfFhPd+06DN6MvcsPsNenv0a+uOl9nyTq7kGxynSRRYlO0/l3DyKvQPQtxz6MlnN
18+
ARcGd8jEg7SApA0=
19+
-----END CERTIFICATE-----

spec/files/cert2/key.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9tdmu6OYC/cD3
3+
+oz6ljf57qTy2jSfE0NHqk6X5CcNk5Pzbnzu/nvdsQlMyBa9ReaetYt0KDYpe0tR
4+
ddbOSbbgxIY1LKMolsreDRiWDsk5KHi3/DgLdf748qVS6PJamR7uZ/TGl1vQU+Bc
5+
g1Q3B/AaNlCmz+Njx3TjsZZZIWOIcrgv6M8aZ0+Z6ogui8G5buCHai0AOydrvuGR
6+
EkurWNTe7bxSb6w36d+khEgAYFdylYXLdkgFGZ8LDOJXCK8dgbdBTFOxa8K9y6T5
7+
e14Obc/dzD4w75UcDUrR6F5tmRr+iOsiAD20BIdLrfme3GwQFTmk5l1I85Nv7SKp
8+
8g48ocjrAgMBAAECggEAJ3HYrZwCOyv8w/LF/lJemCptBIunNk4ghpWcGsvW7OU6
9+
9XoLIvwp0An/14Wg6MDQdz5jHQdBX7WhjvHz9FdyXWCvUP4TfJyB2NKbQpQXdbl7
10+
BDI+iu+BUMzO4CLMRVciDcryo5oT/oh6FXI+/+Q4IZMaiNyfuH7fyHoDu0uMcPGh
11+
ncgPCoFh8+9wauvg/LrY1XBxk66nUvL4IivQN/7uDTIG2mo2BR8+ai2wg3EosvPj
12+
bn36leJsWnZ0ZWHzbfsSqGA1A6U5m1RBQKLij3YUJbkaGiQ1KfqHXso1JCnMhpwM
13+
NCD5qVXLZO4Fa6N4iNgRVSTrmi1ACLyiXFac3qi3uQKBgQDpGR9ri7uf2UI+bC1y
14+
8PNso3AD2pqXS/hvwHNBRqjoRRZeVG5SdLZXZhKyANhsOWZ7+9Co3TAhuzZ6PBty
15+
y6eJzDnqoURUAkMGPYPIX9Vhvh/O25MSw50jrKxfAoyS/RLI27akto262g98GC0E
16+
48jXz8rReCgYbgnmmm6qBKifWQKBgQDQWXB7rbLdKfqYrSSa/YCGIvu6qKIrTVsr
17+
ciSPsxKmC1dLuRf4p/InLGDL1GIuwqCR4xVuPMGI3jL0JV2fXZzh9CFiuaxfm6oM
18+
wwwWQNIh1XEXHWh4f2Of97GC32gpMwBOSfwzDknf8MB1vGYmSVdNrfNucyd54WIS
19+
m5bLYcXF4wKBgQC3kSRQUoOYl8T2WcTU/vIEvRUqw834lkh44Usivd2oxTefY8hZ
20+
wTYTz/urGMVXPUD7JM0nHsGX3tJBIvLOzZkMCLwXjZa8vedAk9MjSm1Fgy+TfRHu
21+
tgQbIxG/5McFvq07ZuQIBQfKfY2yQWu6rRPu+OIVYhXZX1cGttmtpOuSSQKBgQDJ
22+
ZywM4oQctw+/tt/D03oCMJ8WeR0KruSKwvQE1R4Z1Ky2Tl6VyAOVSpjncI7YlNuT
23+
Kuj0f1a2b9ThnZ07CMs2wT/kp4exhFCFtaZhfJekjSedKJhsovgzEsVNtZiC+wI4
24+
q9xXnmBbUec56Lz2Fb+HH7hJ9JccgnrDchP61rDP8QKBgGM0ydfyQEybl+oWhPCN
25+
kUGxon6cZ8GZXpZQ9ocvQo+4sqJtQ6cBE+oNE0oCXnaSMXHNhRdOyR3ALCXUO5tK
26+
mjAQA6JFKWyb3DUoiDH6jEyq8FB2Fqe7VAio/Gbfxb+eOlttCU4FA+hZDRd21OiM
27+
n61wVEHtyOKDrutOQbRuDtRw
28+
-----END PRIVATE KEY-----

spec/files/file.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
# frozen_string_literal: true
2-
31
hello
42
world

spec/persistent_connections_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@
88
WebMock.enable!
99
end
1010

11+
before { GC.start }
12+
13+
def read_file(path)
14+
File.new("#{__dir__}/files/#{path}").read
15+
end
16+
17+
def make_ssl_context(cert, key)
18+
OpenSSL::SSL::SSLContext.new.tap do |ssl_context|
19+
ssl_context.cert = OpenSSL::X509::Certificate.new(cert)
20+
ssl_context.key = OpenSSL::PKey.read(key)
21+
end
22+
end
23+
1124
it "removes connections that are timed out on each request" do
1225
client = EzClient.new(keep_alive: 1, timeout: 15)
1326

@@ -27,4 +40,27 @@
2740
connection_count = ObjectSpace.each_object(HTTP::Connection).count
2841
expect(connection_count).to eq(1)
2942
end
43+
44+
it "boots up separate http connections for different ssl contexts" do
45+
client = EzClient.new(keep_alive: 15)
46+
47+
cert1 = read_file("cert1/cert.pem")
48+
key1 = read_file("cert1/key.pem")
49+
cert2 = read_file("cert2/cert.pem")
50+
key2 = read_file("cert2/key.pem")
51+
52+
ssl_context1 = make_ssl_context(cert1, key1)
53+
ssl_context2 = make_ssl_context(cert2, key2)
54+
55+
2.times do
56+
client.perform!(:get, "https://ya.ru", ssl_context: ssl_context1)
57+
end
58+
59+
2.times do
60+
client.perform!(:get, "https://ya.ru", ssl_context: ssl_context2)
61+
end
62+
63+
connection_count = ObjectSpace.each_object(HTTP::Connection).count
64+
expect(connection_count).to eq(2)
65+
end
3066
end

0 commit comments

Comments
 (0)