diff options
Diffstat (limited to 'lib/net/hippie/connection.rb')
| -rw-r--r-- | lib/net/hippie/connection.rb | 118 |
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 |
