require "net/http/persistent" require "yajl" require "nokogiri" class Hugs Headers = { :json => "application/json", :xml => "application/xml", }.freeze Verbs = %w(get delete post put).freeze ## # Required options: # +host+: A String with the host to connect. # Optional: # +user+: A String containing the username for use in HTTP Basic auth. # +password+: A String containing the password for use in HTTP Basic auth. # +port+: An Integer containing the port to connect. # +scheme+: A String containing the HTTP scheme. def initialize options @user = options[:user] @password = options[:password] @host = options[:host] @port = options[:port] || 80 @scheme = options[:scheme] || "https" @type = options[:type] || :json end ## # Perform an HTTP get, delete, post, or put. # +path+: A String with the path to the HTTP resource. # +params+: A Hash with the following keys: # - +:query+: Query String in the format "foo=bar" # - +:body+: A sub Hash to be JSON encoded, and posted in # the message body. Verbs.each do |verb| define_method verb do |*args| path = args[0] params = args[1] || {} clazz = eval "Net::HTTP::#{verb.capitalize}" response = response_for(clazz, path, params) response.body = parse response.body response end end ## # :method: get ## # :method: delete ## # :method: post ## # :method: put private ## # Worker method to be called by #get, #delete, #post, #put. # Method arguments have been documented in the callers. def response_for request, path, params query = params[:query] && params.delete(:query) body = params[:body] && params.delete(:body) @http ||= Net::HTTP::Persistent.new @url ||= URI.parse "#{@scheme}://#{@host}:#{@port}" request = request.new [path, query].compact.join "?" request.body = encode(body) if body common_headers request @http.request(@url, request) end def common_headers request request.basic_auth(@user, @password) if requires_authentication? case request.class.to_s when Net::HTTP::Get.to_s, Net::HTTP::Delete.to_s request.add_field "accept", Headers[@type] when Net::HTTP::Post.to_s, Net::HTTP::Put.to_s request.add_field "accept", Headers[@type] request.add_field "content-type", Headers[@type] end end def parse data if is_json? Yajl::Parser.parse data elsif is_xml? Nokogiri::XML.parse data end end def encode body is_json? ? (Yajl::Encoder.encode body) : body end def requires_authentication? @user && @password end def is_xml? @type == :xml end def is_json? @type == :json end end