summaryrefslogtreecommitdiff
path: root/lib/net/hippie/connection.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/net/hippie/connection.rb')
-rw-r--r--lib/net/hippie/connection.rb118
1 files changed, 116 insertions, 2 deletions
diff --git a/lib/net/hippie/connection.rb b/lib/net/hippie/connection.rb
index 83097ff..73b5d84 100644
--- a/lib/net/hippie/connection.rb
+++ b/lib/net/hippie/connection.rb
@@ -4,8 +4,45 @@ require_relative 'rust_backend'
module Net
module Hippie
- # A connection to a specific host
+ # Connection abstraction layer that supports both Ruby and Rust backends.
+ #
+ # The Connection class provides a unified interface for HTTP connections,
+ # automatically selecting between the Ruby implementation and the optional
+ # high-performance Rust backend based on availability and configuration.
+ #
+ # Backend selection logic:
+ # 1. If NET_HIPPIE_RUST=true and Rust extension available -> RustConnection
+ # 2. Otherwise -> RubyConnection (classic net/http implementation)
+ #
+ # @since 0.1.0
+ # @since 2.0.0 Added Rust backend support
+ #
+ # == Backend Switching
+ #
+ # # Enable Rust backend (requires compilation)
+ # ENV['NET_HIPPIE_RUST'] = 'true'
+ # connection = Net::Hippie::Connection.new('https', 'api.example.com', 443)
+ # # Uses RustConnection if available, falls back to RubyConnection
+ #
+ # @see RubyConnection The Ruby/net-http implementation
+ # @see RustConnection The optional Rust implementation
class Connection
+ # Creates a new connection with automatic backend selection.
+ #
+ # @param scheme [String] URL scheme ('http' or 'https')
+ # @param host [String] Target hostname
+ # @param port [Integer] Target port number
+ # @param options [Hash] Connection configuration options
+ # @option options [Integer] :read_timeout Socket read timeout in seconds
+ # @option options [Integer] :open_timeout Socket connection timeout in seconds
+ # @option options [Integer] :verify_mode SSL verification mode
+ # @option options [String] :certificate Client certificate for mutual TLS
+ # @option options [String] :key Private key for client certificate
+ # @option options [String] :passphrase Passphrase for encrypted private key
+ # @option options [Logger] :logger Logger for connection debugging
+ #
+ # @since 0.1.0
+ # @since 2.0.0 Added automatic backend selection
def initialize(scheme, host, port, options = {})
@scheme = scheme
@host = host
@@ -20,16 +57,35 @@ module Net
end
end
+ # Executes an HTTP request using the selected backend.
+ #
+ # @param request [Net::HTTPRequest] The HTTP request to execute
+ # @return [Net::HTTPResponse] The HTTP response
+ # @raise [Net::ReadTimeout, Net::OpenTimeout] When request times out
+ # @since 0.1.0
def run(request)
@backend.run(request)
end
+ # Builds a complete URL from a path, handling absolute and relative URLs.
+ #
+ # @param path [String] URL path (absolute or relative)
+ # @return [String] Complete URL
+ # @since 0.1.0
def build_url_for(path)
@backend.build_url_for(path)
end
private
+ # Creates the Ruby backend implementation.
+ #
+ # @param scheme [String] URL scheme
+ # @param host [String] Target hostname
+ # @param port [Integer] Target port
+ # @param options [Hash] Connection options
+ # @return [RubyConnection] Ruby backend instance
+ # @since 2.0.0
def create_ruby_backend(scheme, host, port, options)
# This is the original Ruby implementation wrapped in an object
# that matches the same interface as RustConnection
@@ -37,8 +93,31 @@ module Net
end
end
- # Wrapper for the original Ruby implementation
+ # Ruby implementation of HTTP connections using net/http.
+ #
+ # This class provides the traditional net/http-based HTTP client functionality
+ # that has been the backbone of Net::Hippie since its inception. It supports
+ # all standard HTTP features including SSL/TLS, client certificates, and
+ # comprehensive timeout configuration.
+ #
+ # @since 2.0.0 Extracted from Connection class
+ # @see Connection The main connection interface
class RubyConnection
+ # Creates a new Ruby HTTP connection using net/http.
+ #
+ # @param scheme [String] URL scheme ('http' or 'https')
+ # @param host [String] Target hostname
+ # @param port [Integer] Target port number
+ # @param options [Hash] Connection configuration options
+ # @option options [Integer] :read_timeout Socket read timeout (default: 10)
+ # @option options [Integer] :open_timeout Socket connection timeout (default: 10)
+ # @option options [Integer] :verify_mode SSL verification mode
+ # @option options [String] :certificate Client certificate for mutual TLS
+ # @option options [String] :key Private key for client certificate
+ # @option options [String] :passphrase Passphrase for encrypted private key
+ # @option options [Logger] :logger Logger for connection debugging
+ #
+ # @since 2.0.0
def initialize(scheme, host, port, options = {})
@scheme = scheme
@host = host
@@ -54,10 +133,30 @@ module Net
@http = http
end
+ # Executes an HTTP request using net/http.
+ #
+ # @param request [Net::HTTPRequest] The HTTP request to execute
+ # @return [Net::HTTPResponse] The HTTP response
+ # @raise [Net::ReadTimeout] When read timeout expires
+ # @raise [Net::OpenTimeout] When connection timeout expires
+ # @since 2.0.0
def run(request)
@http.request(request)
end
+ # Builds a complete URL from a path.
+ #
+ # @param path [String] URL path (absolute URLs returned as-is)
+ # @return [String] Complete URL with scheme, host, and path
+ # @since 2.0.0
+ #
+ # @example Relative path
+ # connection.build_url_for('/api/users')
+ # # => "https://api.example.com/api/users"
+ #
+ # @example Absolute URL
+ # connection.build_url_for('https://other.com/path')
+ # # => "https://other.com/path"
def build_url_for(path)
return path if path.start_with?('http')
@@ -66,6 +165,14 @@ module Net
private
+ # Applies client TLS certificate configuration to the HTTP connection.
+ #
+ # @param http [Net::HTTP] The HTTP connection object
+ # @param options [Hash] TLS configuration options
+ # @option options [String] :certificate Client certificate in PEM format
+ # @option options [String] :key Private key in PEM format
+ # @option options [String] :passphrase Optional passphrase for encrypted key
+ # @since 2.0.0
def apply_client_tls_to(http, options)
return if options[:certificate].nil? || options[:key].nil?
@@ -73,6 +180,13 @@ module Net
http.key = private_key(options[:key], options[:passphrase])
end
+ # Creates a private key object from PEM data.
+ #
+ # @param key [String] Private key in PEM format
+ # @param passphrase [String, nil] Optional passphrase for encrypted keys
+ # @param type [Class] OpenSSL key class (default: RSA)
+ # @return [OpenSSL::PKey] Private key object
+ # @since 2.0.0
def private_key(key, passphrase, type = OpenSSL::PKey::RSA)
passphrase ? type.new(key, passphrase) : type.new(key)
end