<commit_before># encoding: utf-8

require 'typhoeus'
require 'socket'

module Carto
  # Wrapper on top of Typhoeus
  class HttpClient


    def self.get(tag, extra_options = {})
      @@clients ||= {}
      @@clients[tag] ||= build_client(tag, extra_options)
    end

    def self.build_client(tag, extra_options)
      logger = build_logger(tag, extra_options)
      new(logger)
    end

    def self.build_logger(tag, extra_options)
      if extra_options[:log_requests] && ResponseLogger.enabled?
        ResponseLogger.new(tag, Socket.gethostname)
      else
        NullLogger.new()
      end
    end

    # Returns a wrapper to a typhoeus request object
    def request(url, options = {})
      Request.new(@logger, url, options)
    end

    def get(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :get))
      request.run
    end

    def post(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :post))
      request.run
    end

    def head(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :head))
      request.run
    end

    def put(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :put))
      request.run
    end

    def delete(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :delete))
      request.run
    end


    private

    def initialize(logger)
      @logger = logger
    end


    class Request

      def initialize(logger, url, options = {})
        @logger = logger
        @typhoeus_request = Typhoeus::Request.new(url, options)
      end

      def run
        response = @typhoeus_request.run
        @logger.log(response)
        response
      end

      def url
        @typhoeus_request.url
      end

      def options
        @typhoeus_request.options
      end

      def on_headers(&block)
        @typhoeus_request.on_headers(&block)
      end

      def on_body(&block)
        @typhoeus_request.on_body(&block)
      end

      def on_complete(&block)
        @typhoeus_request.on_complete(&block)
      end
    end


    class ResponseLogger

      def self.enabled?
        defined?(Rails) && Rails.respond_to?(:root) && Rails.root.present? && Cartodb.config[:http_client_logs]
      end

      def initialize(tag, hostname)
        @tag = tag
        @hostname = hostname
      end

      def log(response)
        payload = {
          tag: @tag,
          hostname: @hostname,
          method: response.request.options[:method].to_s,
          request_url: response.request.url,
          total_time: response.total_time,
          response_code: response.code,
          response_body_size: response.body.nil? ? 0 : response.body.size
        }
        logger.info(payload.to_json)
      end

      def logger
        @@logger ||= Logger.new("#{Rails.root}/log/http_client.log")
      end
    end

    class NullLogger
      def log(response); end<commit_msg>Account for missing/default request method #3778<commit_after># encoding: utf-8

require 'typhoeus'
require 'socket'

module Carto
  # Wrapper on top of Typhoeus
  class HttpClient


    def self.get(tag, extra_options = {})
      @@clients ||= {}
      @@clients[tag] ||= build_client(tag, extra_options)
    end

    def self.build_client(tag, extra_options)
      logger = build_logger(tag, extra_options)
      new(logger)
    end

    def self.build_logger(tag, extra_options)
      if extra_options[:log_requests] && ResponseLogger.enabled?
        ResponseLogger.new(tag, Socket.gethostname)
      else
        NullLogger.new()
      end
    end

    # Returns a wrapper to a typhoeus request object
    def request(url, options = {})
      Request.new(@logger, url, options)
    end

    def get(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :get))
      request.run
    end

    def post(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :post))
      request.run
    end

    def head(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :head))
      request.run
    end

    def put(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :put))
      request.run
    end

    def delete(url, options = {})
      request = Request.new(@logger, url, options.merge(method: :delete))
      request.run
    end


    private

    def initialize(logger)
      @logger = logger
    end


    class Request

      def initialize(logger, url, options = {})
        @logger = logger
        @typhoeus_request = Typhoeus::Request.new(url, options)
      end

      def run
        response = @typhoeus_request.run
        @logger.log(response)
        response
      end

      def url
        @typhoeus_request.url
      end

      def options
        @typhoeus_request.options
      end

      def on_headers(&block)
        @typhoeus_request.on_headers(&block)
      end

      def on_body(&block)
        @typhoeus_request.on_body(&block)
      end

      def on_complete(&block)
        @typhoeus_request.on_complete(&block)
      end
    end


    class ResponseLogger

      def self.enabled?
        defined?(Rails) && Rails.respond_to?(:root) && Rails.root.present? && Cartodb.config[:http_client_logs]
      end

      def initialize(tag, hostname)
        @tag = tag
        @hostname = hostname
      end

      def log(response)
        payload = {
          tag: @tag,
          hostname: @hostname,
          method: (response.request.options[:method] || :get).to_s, # the default typhoeus method is :get
          request_url: response.request.url,
          total_time: response.total_time,
          response_code: response.code,
          response_body_size: response.body.nil? ? 0 : response.body.size
        }
        logger.info(payload.to_json)
      end

      def logger
        @@logger ||= Logger.new("#{Rails.root}/log/http_client.log")
      end
    end

    class NullLogger
      def log(response); end
{'fraction_non_alphanumeric': 0.10706602680787689, 'fraction_numerical': 0.0013238457719675658, 'mean_word_length': 2.263498920086393, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '481615', 'n_tokens_mistral': 1886, 'n_tokens_neox': 1834, 'n_words': 419}