# File lib/puppet/indirector/facts/puppetdb.rb, line 44
  def find(request)
    profile("facts#find", [:puppetdb, :facts, :find, request.key]) do
      begin
        url = Puppet::Util::Puppetdb.url_path("/v3/nodes/#{CGI.escape(request.key)}/facts")
        response = profile("Query for nodes facts: #{url}",
                           [:puppetdb, :facts, :find, :query_nodes, request.key]) do
          http_get(request, url, headers)
        end
        log_x_deprecation_header(response)

        if response.is_a? Net::HTTPSuccess
          profile("Parse fact query response (size: #{response.body.size})",
                  [:puppetdb, :facts, :find, :parse_response, request.key]) do
            result = JSON.parse(response.body)
            # Note: the Inventory Service API appears to expect us to return nil here
            # if the node isn't found.  However, PuppetDB returns an empty array in
            # this case; for now we will just look for that condition and assume that
            # it means that the node wasn't found, so we will return nil.  In the
            # future we may want to improve the logic such that we can distinguish
            # between the "node not found" and the "no facts for this node" cases.
            if result.empty?
              return nil
            end
            facts = result.inject({}) do |a,h|
              a.merge(h['name'] => h['value'])
            end
            Puppet::Node::Facts.new(request.key, facts)
          end
        else
          # Newline characters cause an HTTP error, so strip them
          raise "[#{response.code} #{response.message}] #{response.body.gsub(/[\r\n]/, '')}"
        end
      rescue => e
        raise Puppet::Error, "Failed to find facts from PuppetDB at #{self.class.server}:#{self.class.port}: #{e}"
      end
    end
  end