module ChefFS module RawRequest def self.raw_json(chef_rest, api_path) api_request(chef_rest, :GET, chef_rest.create_url(api_path), {}, nil, :parse_json => true) end def self.raw_request(chef_rest, api_path) api_request(chef_rest, :GET, chef_rest.create_url(api_path)) end def self.api_request(chef_rest, method, url, headers={}, data=nil, options = {}) json_body = data || nil # json_body = data ? Chef::JSONCompat.to_json(data) : nil # Force encoding to binary to fix SSL related EOFErrors # cf. http://tickets.opscode.com/browse/CHEF-2363 # http://redmine.ruby-lang.org/issues/5233 # json_body.force_encoding(Encoding::BINARY) if json_body.respond_to?(:force_encoding) headers = build_headers(chef_rest, method, url, headers, json_body) chef_rest.retriable_rest_request(method, url, json_body, headers) do |rest_request| response = rest_request.call {|r| r.read_body} response_body = chef_rest.decompress_body(response) if response.kind_of?(Net::HTTPSuccess) if options[:parse_json] && response['content-type'] =~ /json/ JSON.parse(response_body, :create_additions => false) else response_body end elsif redirect_location = redirected_to(response) if [:GET, :HEAD].include?(method) chef_rest.follow_redirect do api_request(chef_rest, method, chef_rest.create_url(redirect_location), headers, nil, options) end else raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects." end else # have to decompress the body before making an exception for it. But the body could be nil. response.body.replace(chef_rest.decompress_body(response)) if response.body.respond_to?(:replace) if response['content-type'] =~ /json/ exception = 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 end end private # Copied so that it does not automatically inflate an object # This is also used by knife raw_essentials ACCEPT_ENCODING = "Accept-Encoding".freeze ENCODING_GZIP_DEFLATE = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3".freeze def self.redirected_to(response) return nil unless response.kind_of?(Net::HTTPRedirection) # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this return nil if response.kind_of?(Net::HTTPNotModified) response['location'] end def self.build_headers(chef_rest, method, url, headers={}, json_body=nil, raw=nil) # headers = @default_headers.merge(headers) #headers['Accept'] = "application/json" unless raw headers['Accept'] = "application/json" unless raw headers['Content-Type'] = 'application/json' if json_body headers['Content-Length'] = json_body.bytesize.to_s if json_body headers[Chef::REST::RESTRequest::ACCEPT_ENCODING] = Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE headers.merge!(chef_rest.authentication_headers(method, url, json_body)) if chef_rest.sign_requests? headers.merge!(Chef::Config[:custom_http_headers]) if Chef::Config[:custom_http_headers] headers end end end