summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamantaz Fox <coding@samantaz.fr>2021-08-03 23:44:47 +0200
committerGitHub <noreply@github.com>2021-08-03 23:44:47 +0200
commit4b46313e19f06f2739ee522eb4fbfe8dbcbee630 (patch)
treed45624d19b9b94dbb65bce18a8ff35df230c6204 /src
parente9add69e267c143925ba51d54c03deaba2e0e85a (diff)
downloadinvidious-4b46313e19f06f2739ee522eb4fbfe8dbcbee630.tar.gz
invidious-4b46313e19f06f2739ee522eb4fbfe8dbcbee630.tar.bz2
invidious-4b46313e19f06f2739ee522eb4fbfe8dbcbee630.zip
Fix crystal overrides (#2295)
* Move Crystal stdlib classes overrides to a separate file * Document known crystal overrides * Update crystal overrides for HTTP::Client socket * Update shard.yml to restrict crystal versions * Fix compilation error in Crystal 1.1.x (See https://github.com/crystal-lang/crystal/issues/10965 for more details about this issue).
Diffstat (limited to 'src')
-rw-r--r--src/invidious/helpers/crystal_class_overrides.cr70
-rw-r--r--src/invidious/helpers/helpers.cr50
2 files changed, 70 insertions, 50 deletions
diff --git a/src/invidious/helpers/crystal_class_overrides.cr b/src/invidious/helpers/crystal_class_overrides.cr
new file mode 100644
index 00000000..28afd5b5
--- /dev/null
+++ b/src/invidious/helpers/crystal_class_overrides.cr
@@ -0,0 +1,70 @@
+# Override of the TCPSocket and HTTP::Client classes in oder to allow an
+# IP family to be selected for domains that resolve to both IPv4 and
+# IPv6 addresses.
+#
+class TCPSocket
+ def initialize(host : String, port, dns_timeout = nil, connect_timeout = nil, family = Socket::Family::UNSPEC)
+ Addrinfo.tcp(host, port, timeout: dns_timeout, family: family) do |addrinfo|
+ super(addrinfo.family, addrinfo.type, addrinfo.protocol)
+ connect(addrinfo, timeout: connect_timeout) do |error|
+ close
+ error
+ end
+ end
+ end
+end
+
+# :ditto:
+class HTTP::Client
+ property family : Socket::Family = Socket::Family::UNSPEC
+
+ private def io
+ io = @io
+ return io if io
+ unless @reconnect
+ raise "This HTTP::Client cannot be reconnected"
+ end
+
+ hostname = @host.starts_with?('[') && @host.ends_with?(']') ? @host[1..-2] : @host
+ io = TCPSocket.new hostname, @port, @dns_timeout, @connect_timeout, @family
+ io.read_timeout = @read_timeout if @read_timeout
+ io.write_timeout = @write_timeout if @write_timeout
+ io.sync = false
+
+ {% if !flag?(:without_openssl) %}
+ if tls = @tls
+ tcp_socket = io
+ begin
+ io = OpenSSL::SSL::Socket::Client.new(tcp_socket, context: tls, sync_close: true, hostname: @host)
+ rescue exc
+ # don't leak the TCP socket when the SSL connection failed
+ tcp_socket.close
+ raise exc
+ end
+ end
+ {% end %}
+
+ @io = io
+ end
+end
+
+# Mute the ClientError exception raised when a connection is flushed.
+# This happends when the connection is unexpectedly closed by the client.
+#
+class HTTP::Server::Response
+ class Output
+ private def unbuffered_flush
+ @io.flush
+ rescue ex : IO::Error
+ unbuffered_close
+ end
+ end
+end
+
+# TODO: Document this override
+#
+class PG::ResultSet
+ def field(index = @column_index)
+ @fields.not_nil![index]
+ end
+end
diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr
index fb7b19e6..99d7f440 100644
--- a/src/invidious/helpers/helpers.cr
+++ b/src/invidious/helpers/helpers.cr
@@ -509,12 +509,6 @@ def check_table(db, table_name, struct_type = nil)
end
end
-class PG::ResultSet
- def field(index = @column_index)
- @fields.not_nil![index]
- end
-end
-
def get_column_array(db, table_name)
column_array = [] of String
db.query("SELECT * FROM #{table_name} LIMIT 0") do |rs|
@@ -699,47 +693,3 @@ def proxy_file(response, env)
IO.copy response.body_io, env.response
end
end
-
-class HTTP::Server::Response
- class Output
- private def unbuffered_flush
- @io.flush
- rescue ex : IO::Error
- unbuffered_close
- end
- end
-end
-
-class HTTP::Client
- property family : Socket::Family = Socket::Family::UNSPEC
-
- private def socket
- socket = @socket
- return socket if socket
-
- hostname = @host.starts_with?('[') && @host.ends_with?(']') ? @host[1..-2] : @host
- socket = TCPSocket.new hostname, @port, @dns_timeout, @connect_timeout, @family
- socket.read_timeout = @read_timeout if @read_timeout
- socket.sync = false
-
- {% if !flag?(:without_openssl) %}
- if tls = @tls
- socket = OpenSSL::SSL::Socket::Client.new(socket, context: tls, sync_close: true, hostname: @host)
- end
- {% end %}
-
- @socket = socket
- end
-end
-
-class TCPSocket
- def initialize(host, port, dns_timeout = nil, connect_timeout = nil, family = Socket::Family::UNSPEC)
- Addrinfo.tcp(host, port, timeout: dns_timeout, family: family) do |addrinfo|
- super(addrinfo.family, addrinfo.type, addrinfo.protocol)
- connect(addrinfo, timeout: connect_timeout) do |error|
- close
- error
- end
- end
- end
-end