# File lib/puppet/indirector/resource/puppetdb.rb, line 9
  def search(request)
    profile("resource#search",
            [:puppetdb, :resource, :search, request.key]) do
      type   = request.key
      host   = request.options[:host]
      filter = request.options[:filter]
      scope  = request.options[:scope]

      # At minimum, we want to filter to the right type of exported resources.
      expr = ['and',
               ['=', 'type', type],
               ['=', 'exported', true],
               ['not',
                 ['=', 'certname', host]]]

      filter_expr = build_expression(filter)
      expr << filter_expr if filter_expr

      query_param = CGI.escape(expr.to_json)

      begin
        url = Puppet::Util::Puppetdb.url_path("/v3/resources?query=#{query_param}")
        response = profile("Resources query: #{URI.unescape(url)}",
                           [:puppetdb, :resource, :search, :query, request.key]) do
          http_get(request, url, headers)
        end
        log_x_deprecation_header(response)

        unless response.is_a? Net::HTTPSuccess
          # 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, "Could not retrieve resources from the PuppetDB at #{self.class.server}:#{self.class.port}: #{e}"
      end

      resources = profile("Parse resource query response (size: #{response.body.size})",
                          [:puppetdb, :resource, :search, :parse_query_response, request.key]) do
        JSON.load(response.body)
      end

      profile("Build up collected resource objects (count: #{resources.count})",
              [:puppetdb, :resource, :search, :build_up_collected_objects, request.key]) do
        resources.map do |res|
          params = res['parameters'] || {}
          params = params.map do |name,value|
            Puppet::Parser::Resource::Param.new(:name => name, :value => value)
          end
          attrs = {:parameters => params, :scope => scope}
          result = Puppet::Parser::Resource.new(res['type'], res['title'], attrs)
          result.collector_id = "#{res['certname']}|#{res['type']}|#{res['title']}"
          result
        end
      end
    end
  end