class Down::Http
Public Class Methods
new(options = {}, &block)
click to toggle source
# File lib/down/http.rb, line 15 def initialize(options = {}, &block) if options.is_a?(HTTP::Client) warn "[Down] Passing an HTTP::Client object to Down::Http#initialize is deprecated and won't be supported in Down 5. Use the block initialization instead." options = options.default_options.to_hash end @method = options.delete(:method) || :get @client = HTTP .headers("User-Agent" => "Down/#{Down::VERSION}") .follow(max_hops: 2) .timeout(connect: 30, write: 30, read: 30) @client = HTTP::Client.new(@client.default_options.merge(options)) if options.any? @client = block.call(@client) if block end
Public Instance Methods
download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, **options, &block)
click to toggle source
# File lib/down/http.rb, line 31 def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, **options, &block) response = request(url, **options, &block) content_length_proc.call(response.content_length) if content_length_proc && response.content_length if max_size && response.content_length && response.content_length > max_size raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)" end extname = File.extname(response.uri.path) tempfile = Tempfile.new(["down-http", extname], binmode: true) stream_body(response) do |chunk| tempfile.write(chunk) chunk.clear # deallocate string progress_proc.call(tempfile.size) if progress_proc if max_size && tempfile.size > max_size raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)" end end tempfile.open # flush written content tempfile.extend Down::Http::DownloadedFile tempfile.url = response.uri.to_s tempfile.headers = response.headers.to_h download_result(tempfile, destination) rescue tempfile.close! if tempfile raise end
open(url, rewindable: true, **options, &block)
click to toggle source
# File lib/down/http.rb, line 66 def open(url, rewindable: true, **options, &block) response = request(url, **options, &block) Down::ChunkedIO.new( chunks: enum_for(:stream_body, response), size: response.content_length, encoding: response.content_type.charset, rewindable: rewindable, data: { status: response.code, headers: response.headers.to_h, response: response }, ) end
Private Instance Methods
process_url(url, options)
click to toggle source
# File lib/down/http.rb, line 105 def process_url(url, options) uri = HTTP::URI.parse(url) if uri.user || uri.password user, pass = uri.user, uri.password authorization = "Basic #{Base64.strict_encode64("#{user}:#{pass}")}" options[:headers] ||= {} options[:headers].merge!("Authorization" => authorization) uri.user = uri.password = nil end uri.to_s end
request(url, method: @method, **options, &block)
click to toggle source
# File lib/down/http.rb, line 80 def request(url, method: @method, **options, &block) response = send_request(method, url, **options, &block) response_error!(response) unless response.status.success? response end
request_error!(exception)
click to toggle source
# File lib/down/http.rb, line 129 def request_error!(exception) case exception when HTTP::Request::UnsupportedSchemeError, Addressable::URI::InvalidURIError raise Down::InvalidUrl, exception.message when HTTP::ConnectionError raise Down::ConnectionError, exception.message when HTTP::TimeoutError raise Down::TimeoutError, exception.message when HTTP::Redirector::TooManyRedirectsError raise Down::TooManyRedirects, exception.message when OpenSSL::SSL::SSLError raise Down::SSLError, exception.message else raise exception end end
response_error!(response)
click to toggle source
# File lib/down/http.rb, line 119 def response_error!(response) args = [response.status.to_s, response: response] case response.code when 400..499 then raise Down::ClientError.new(*args) when 500..599 then raise Down::ServerError.new(*args) else raise Down::ResponseError.new(*args) end end
send_request(method, url, **options, &block)
click to toggle source
# File lib/down/http.rb, line 86 def send_request(method, url, **options, &block) url = process_url(url, options) client = @client client = block.call(client) if block client.request(method, url, options) rescue => exception request_error!(exception) end
stream_body(response, &block)
click to toggle source
# File lib/down/http.rb, line 97 def stream_body(response, &block) response.body.each(&block) rescue => exception request_error!(exception) ensure response.connection.close unless @client.persistent? end