diff options
Diffstat (limited to 'lib/chef/http/http_request.rb')
-rw-r--r-- | lib/chef/http/http_request.rb | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/lib/chef/http/http_request.rb b/lib/chef/http/http_request.rb new file mode 100644 index 0000000000..ec837f13f2 --- /dev/null +++ b/lib/chef/http/http_request.rb @@ -0,0 +1,172 @@ +#-- +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Thom May (<thom@clearairturbulence.org>) +# Author:: Nuo Yan (<nuo@opscode.com>) +# Author:: Christopher Brown (<cb@opscode.com>) +# Author:: Christopher Walters (<cw@opscode.com>) +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +require 'uri' +require 'net/http' + +# To load faster, we only want ohai's version string. +# However, in ohai before 0.6.0, the version is defined +# in ohai, not ohai/version +begin + require 'ohai/version' #used in user agent string. +rescue LoadError + require 'ohai' +end + +require 'chef/version' + +class Chef + class HTTP + class HTTPRequest + + engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby" + + UA_COMMON = "/#{::Chef::VERSION} (#{engine}-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}; ohai-#{Ohai::VERSION}; #{RUBY_PLATFORM}; +http://opscode.com)" + DEFAULT_UA = "Chef Client" << UA_COMMON + + USER_AGENT = "User-Agent".freeze + + ACCEPT_ENCODING = "Accept-Encoding".freeze + ENCODING_GZIP_DEFLATE = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3".freeze + + GET = "get".freeze + PUT = "put".freeze + POST = "post".freeze + DELETE = "delete".freeze + HEAD = "head".freeze + + HTTPS = "https".freeze + + SLASH = "/".freeze + + def self.user_agent=(ua) + @user_agent = ua + end + + def self.user_agent + @user_agent ||= DEFAULT_UA + end + + attr_reader :method, :url, :headers, :http_client, :http_request + + def initialize(method, url, req_body, base_headers={}) + @method, @url = method, url + @request_body = nil + build_headers(base_headers) + configure_http_request(req_body) + end + + def host + @url.host + end + + def port + @url.port + end + + def query + @url.query + end + + def path + @url.path.empty? ? SLASH : @url.path + end + + # DEPRECATED. Call request on an HTTP client object instead. + def call + hide_net_http_bug do + http_client.request(http_request) do |response| + yield response if block_given? + response + end + end + end + + def config + Chef::Config + end + + # DEPRECATED. Call request on an HTTP client object instead. + def http_client + @http_client ||= BasicClient.new(url).http_client + end + + private + + def hide_net_http_bug + yield + rescue NoMethodError => e + # http://redmine.ruby-lang.org/issues/show/2708 + # http://redmine.ruby-lang.org/issues/show/2758 + if e.to_s =~ /#{Regexp.escape(%q|undefined method `closed?' for nil:NilClass|)}/ + Chef::Log.debug("Rescued error in http connect, re-raising as Errno::ECONNREFUSED to hide bug in net/http") + Chef::Log.debug("#{e.class.name}: #{e.to_s}") + Chef::Log.debug(e.backtrace.join("\n")) + raise Errno::ECONNREFUSED, "Connection refused attempting to contact #{url.scheme}://#{host}:#{port}" + else + raise + end + end + + def build_headers(headers) + @headers = headers.dup + # No response compression unless we asked for it explicitly: + @headers[HTTPRequest::ACCEPT_ENCODING] ||= "identity" + @headers['X-Chef-Version'] = ::Chef::VERSION + @headers + end + + + def configure_http_request(request_body=nil) + req_path = "#{path}" + req_path << "?#{query}" if query + + @http_request = case method.to_s.downcase + when GET + Net::HTTP::Get.new(req_path, headers) + when POST + Net::HTTP::Post.new(req_path, headers) + when PUT + Net::HTTP::Put.new(req_path, headers) + when DELETE + Net::HTTP::Delete.new(req_path, headers) + when HEAD + Net::HTTP::Head.new(req_path, headers) + else + raise ArgumentError, "You must provide :GET, :PUT, :POST, :DELETE or :HEAD as the method" + end + + @http_request.body = request_body if (request_body && @http_request.request_body_permitted?) + # Optionally handle HTTP Basic Authentication + if url.user + user = URI.unescape(url.user) + password = URI.unescape(url.password) if url.password + @http_request.basic_auth(user, password) + end + + # Overwrite default UA + @http_request[USER_AGENT] = self.class.user_agent + end + + end + end +end |