# File lib/chef/rest.rb, line 254
    def raw_http_request(method, url, headers, body)
      headers = build_headers(method, url, headers, body)
      retriable_rest_request(method, url, body, headers) do |rest_request|
        begin
          response = rest_request.call {|r| r.read_body}

          Chef::Log.debug("---- HTTP Status and Header Data: ----")
          Chef::Log.debug("HTTP #{response.http_version} #{response.code} #{response.msg}")

          response.each do |header, value|
            Chef::Log.debug("#{header}: #{value}")
          end
          Chef::Log.debug("---- End HTTP Status/Header Data ----")

          response_body = decompress_body(response)

          if response.kind_of?(Net::HTTPSuccess)
            if response['content-type'] =~ /json/
              Chef::JSONCompat.from_json(response_body.chomp)
            else
              Chef::Log.warn("Expected JSON response, but got content-type '#{response['content-type']}'")
              response_body
            end
          elsif redirect_location = redirected_to(response)
            follow_redirect {api_request(:GET, create_url(redirect_location))}
          else
            # have to decompress the body before making an exception for it. But the body could be nil.
            response.body.replace(decompress_body(response)) if response.body.respond_to?(:replace)

            if response['content-type'] =~ /json/
              exception = Chef::JSONCompat.from_json(response_body)
              msg = "HTTP Request Returned #{response.code} #{response.message}: "
              msg << (exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"].to_s)
              Chef::Log.info(msg)
            end
            response.error!
          end
        rescue Exception => e
          if e.respond_to?(:chef_rest_request=)
            e.chef_rest_request = rest_request
          end
          raise
        end
      end
    end