nbulaj/proxy_fetcher

View on GitHub
lib/proxy_fetcher/utils/http_client.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true
 
module ProxyFetcher
# Default ProxyFetcher HTTP client used to fetch proxy lists from
# the different providers. Uses ProxyFetcher configuration options
# for sending HTTP requests to providers URLs.
class HTTPClient
# @!attribute [r] url
# @return [String] URL
attr_reader :url
 
# @!attribute [r] HTTP method
# @return [String] HTTP method verb
attr_reader :method
 
# @!attribute [r] HTTP params
# @return [Hash] params
attr_reader :params
 
# @!attribute [r] HTTP headers
# @return [Hash] headers
attr_reader :headers
 
# @!attribute [r] http
# @return [Net::HTTP] HTTP client
attr_reader :http
 
# @!attribute [r] ssl_ctx
# @return [OpenSSL::SSL::SSLContext] SSL context
attr_reader :ssl_ctx
 
# @!attribute [r] timeout
# @return [Integer] Request timeout
attr_reader :timeout
 
# Fetches resource content by sending HTTP request to it.
# Synthetic sugar to simplify URIes fetching.
#
# @param url [String] URL
#
# @return [String]
# resource content
#
def self.fetch(*args, **kwargs, &block)
new(*args, **kwargs, &block).fetch
end
 
# Initialize HTTP client instance
#
# @return [HTTPClient]
#
def initialize(url, method: :get, params: {}, headers: {})
@url = url.to_s
@method = method.to_sym
@params = params
@headers = headers
 
unless HTTP::Request::METHODS.include?(@method)
raise ArgumentError, "'#{@method}' is a wrong HTTP method name"
end
 
@timeout = ProxyFetcher.config.provider_proxies_load_timeout
@http = build_http_engine
@ssl_ctx = build_ssl_context
end
 
# Fetches resource content by sending HTTP request to it.
#
# @return [String]
# response body
#
def fetch(**options)
response = perform_http_request
return response if options.fetch(:raw, false)
 
response.body.to_s
rescue StandardError => e
ProxyFetcher.config.logger.warn("Failed to process request to #{url} (#{e.message})")
""
end
 
protected
 
def build_ssl_context
OpenSSL::SSL::SSLContext.new.tap do |context|
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end
 
def build_http_engine
HTTP.headers(default_headers.merge(headers)).timeout(connect: timeout, read: timeout)
end
 
def perform_http_request(http_method: method, http_params: params)
http.public_send(
http_method,
url,
form: http_params,
ssl_context: ssl_ctx
)
end
 
# Default HTTP client headers
#
# @return [Hash]
# hash of HTTP headers
#
def default_headers
{
"User-Agent" => ProxyFetcher.config.user_agent
}
end
end
end