Skip to content

Commit abaaeb7

Browse files
committed
Use single global SSL context across HTTP Clients
The standard Crystal `HTTP::Client` creates a new SSL context for every client/reconnection. This is not ideal because creating a new SSL context is an incredibly slow operation. The standard practice instead is to cache or use a single SSL CTX throughout the lifetime of the application. The OpenSSL context has been designed with this in mind, and even explicitly recommends it. It even works concurrently across many threads. Reusing a single SSL context significantly speeds up the process of starting and restarting clients. Which is incredibly important in the case of the Invidious connection pool where new clients are often spun up. The only caveat is that a cached SSL context may become out of sync with the system ca store. But for an Invidious instance following the best practices of frequent restarts this is an non-issue. See crystal-lang/crystal#15419
1 parent 0270917 commit abaaeb7

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

src/invidious/connection/client.cr

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# SSL Contexts are designed to be reused and supports infinite connections.
2+
#
3+
# This *significantly* improves the performance of spinning up new clients/reconnections
4+
#
5+
# For more information see https://github.com/crystal-lang/crystal/issues/15419
6+
private GLOBAL_SSL_CONTEXT = OpenSSL::SSL::Context::Client.new
7+
18
module Invidious
29
class IVTCPSocket < TCPSocket
310
def initialize(host : String, port, dns_timeout = nil, connect_timeout = nil, blocking = false, family = Socket::Family::UNSPEC)
@@ -89,13 +96,19 @@ def make_client(
8996
use_http_proxy : Bool = true,
9097
allow_auto_reconnect : Bool = true,
9198
)
99+
tls = if url.scheme == "https"
100+
GLOBAL_SSL_CONTEXT
101+
else
102+
nil
103+
end
104+
92105
if CONFIG.http_proxy && use_http_proxy
93-
client = Invidious::HTTPClient.new(url)
106+
client = Invidious::HTTPClient.new(url, tls: tls)
94107
client.proxy = make_configured_http_proxy_client() if CONFIG.http_proxy && use_http_proxy
95108
elsif force_resolve
96-
client = Invidious::HTTPClient.new(url, force_resolve: CONFIG.force_resolve)
109+
client = Invidious::HTTPClient.new(url, tls: tls, force_resolve: CONFIG.force_resolve)
97110
else
98-
client = Invidious::HTTPClient.new(url, allow_auto_reconnect: allow_auto_reconnect)
111+
client = Invidious::HTTPClient.new(url, tls: tls, allow_auto_reconnect: allow_auto_reconnect)
99112
end
100113

101114
client.before_request { |r| add_yt_headers(r) } if url.host.try &.ends_with?("youtube.com") || force_youtube_headers

0 commit comments

Comments
 (0)