# encoding: utf-8
# This file is distributed under New Relic's license terms.
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.

require 'new_relic/agent/http_clients/uri_util'

module NewRelic
  module Agent
    class Transaction
      class RequestAttributes
        attr_reader :request_path, :referer, :accept, :content_length, :host,
                    :port, :user_agent, :request_method

        HTTP_ACCEPT_HEADER_KEY = "HTTP_ACCEPT".freeze

        def initialize request
          @request_path = path_from_request request
          @referer = referer_from_request request
          @accept = attribute_from_env request, HTTP_ACCEPT_HEADER_KEY
          @content_length = content_length_from_request request
          @host = attribute_from_request request, :host
          @port = port_from_request request
          @user_agent = attribute_from_request request, :user_agent
          @request_method = attribute_from_request request, :request_method
        end

        def assign_agent_attributes txn
         default_destinations = AttributeFilter::DST_TRANSACTION_TRACER|
                                AttributeFilter::DST_TRANSACTION_EVENTS|
                                AttributeFilter::DST_ERROR_COLLECTOR

          if referer
            txn.add_agent_attribute :'request.headers.referer', referer, AttributeFilter::DST_ERROR_COLLECTOR
          end

          if accept
            txn.add_agent_attribute :'request.headers.accept', accept, default_destinations
          end

          if content_length
            txn.add_agent_attribute :'request.headers.contentLength', content_length, default_destinations
          end

          if host
            txn.add_agent_attribute :'request.headers.host', host, default_destinations
          end

          if user_agent
            txn.add_agent_attribute :'request.headers.userAgent', user_agent, default_destinations
          end

          if request_method
            txn.add_agent_attribute :'request.method', request_method, default_destinations
          end
        end

        private

        # Make a safe attempt to get the referer from a request object, generally successful when
        # it's a Rack request.

        def referer_from_request request
          if referer = attribute_from_request(request, :referer)
            HTTPClients::URIUtil.strip_query_string referer.to_s
          end
        end

        # In practice we expect req to be a Rack::Request or ActionController::AbstractRequest
        # (for older Rails versions).  But anything that responds to path can be passed to
        # perform_action_with_newrelic_trace.
        #
        # We don't expect the path to include a query string, however older test helpers for
        # rails construct the PATH_INFO enviroment variable improperly and we're generally
        # being defensive.

        ROOT_PATH = "/".freeze

        def path_from_request request
          path = attribute_from_request(request, :path) || ''
          path = HTTPClients::URIUtil.strip_query_string(path)
          path.empty? ? ROOT_PATH : path
        end

        def content_length_from_request request
          if content_length = attribute_from_request(request, :content_length)
            content_length.to_i
          end
        end

        def port_from_request request
          if port = attribute_from_request(request, :port)
            port.to_i
          end
        end

        def attribute_from_request request, attribute_method
          if request.respond_to? attribute_method
            request.send(attribute_method)
          end
        end

        def attribute_from_env request, key
          if env = attribute_from_request(request, :env)
            env[key]
          end
        end
      end
    end
  end
end
