def request(api, args)
      uri = api == :uploading ? UPLOAD_URI : API_URI
      args[:method] = "smugmug.#{api}" unless api == :uploading

      http = ::Net::HTTP.new(uri.host, uri.port, @http_proxy_host, @http_proxy_port, @http_proxy_user, @http_proxy_pass)
      http.set_debug_output(@config[:debug_output]) if @config[:debug_output]

      # Configure HTTPS if needed
      if uri.scheme == "https"
        http.use_ssl = true

        if @config[:http] and @config[:http][:verify_mode]
          http.verify_mode = @config[:http][:verify_mode]
          http.ca_file = @config[:http][:ca_file]
          http.ca_path = @config[:http][:ca_path]
        else
          http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        end
      end

      # Upload request, which requires special handling
      if api == :uploading
        postdata = args.delete(:content)
        headers = @headers.merge("Content-Length" => postdata.length.to_s, "Content-MD5" => Digest::MD5.hexdigest(postdata), "X-Smug-Version" => "1.3.0", "X-Smug-ResponseType" => "JSON")

        UPLOAD_HEADERS.each do |key|
          next unless args[key] and args[key] != ""
          headers["X-Smug-#{key}"] = args[key].to_s
        end

        oauth = self.sign_request("POST", uri, nil)
        headers["Authorization"] = "OAuth oauth_consumer_key=\"#{oauth["oauth_consumer_key"]}\", oauth_nonce=\"#{oauth["oauth_nonce"]}\", oauth_signature_method=\"#{oauth["oauth_signature_method"]}\", oauth_signature=\"#{oauth["oauth_signature"]}\", oauth_timestamp=\"#{oauth["oauth_timestamp"]}\", oauth_version=\"#{oauth["oauth_version"]}\", oauth_token=\"#{oauth["oauth_token"]}\""

      # Normal API method
      else
        postdata = self.sign_request("POST", uri, args)
        headers = @headers
      end

      response = http.request_post(uri.request_uri, postdata, headers)
      if response.code == "204"
        return nil
      elsif response.code != "200"
        raise SmugMug::HTTPError.new("HTTP #{response.code}, #{response.message}", response.code, response.message)
      end

      # Check for GZIP encoding
      if response.header["content-encoding"] == "gzip"
        begin
          body = Zlib::GzipReader.new(StringIO.new(response.body)).read
        rescue Zlib::GzipFile::Error
          raise
        end
      else
        body = response.body
      end

      return nil if body == ""

      data = JSON.parse(body)

      if data["stat"] == "fail"
        # Special casing for SmugMug being in Read only mode
        if data["code"] == 99
          raise SmugMug::ReadonlyModeError.new("SmugMug is currently in read only mode, try again later")
        end

        klass = OAUTH_ERRORS[data["code"]] ? SmugMug::OAuthError : SmugMug::RequestError
        raise klass.new("Error ##{data["code"]}, #{data["message"]}", data["code"], data["message"])
      end

      data.delete("stat")
      data.delete("method")

      # smugmug.albums.changeSettings at the least doesn't return any data
      return nil if data.length == 0

      # It seems all smugmug APIs only return one hash of data, so this should be fine and not cause issues
      data.each do |_, value|
        return value
      end
    end
def request(api, args)
      uri = api == :uploading ? UPLOAD_URI : API_URI
      args[:method] = "smugmug.#{api}" unless api == :uploading

      http = ::Net::HTTP.new(uri.host, uri.port, @http_proxy_host, @http_proxy_port, @http_proxy_user, @http_proxy_pass)
      http.set_debug_output(@config[:debug_output]) if @config[:debug_output]

      # Configure HTTPS if needed
      if uri.scheme == "https"
        http.use_ssl = true

        if @config[:http] and @config[:http][:verify_mode]
          http.verify_mode = @config[:http][:verify_mode]
          http.ca_file = @config[:http][:ca_file]
          http.ca_path = @config[:http][:ca_path]
        else
          http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        end
      end

      # Upload request, which requires special handling
      if api == :uploading
        postdata = args.delete(:content)
        headers = @headers.merge("Content-Length" => postdata.length.to_s, "Content-MD5" => Digest::MD5.hexdigest(postdata), "X-Smug-Version" => "1.3.0", "X-Smug-ResponseType" => "JSON")

        UPLOAD_HEADERS.each do |key|
          next unless args[key] and args[key] != ""
          headers["X-Smug-#{key}"] = args[key].to_s
        end

        oauth = self.sign_request("POST", uri, nil)
        headers["Authorization"] = "OAuth oauth_consumer_key=\"#{oauth["oauth_consumer_key"]}\", oauth_nonce=\"#{oauth["oauth_nonce"]}\", oauth_signature_method=\"#{oauth["oauth_signature_method"]}\", oauth_signature=\"#{oauth["oauth_signature"]}\", oauth_timestamp=\"#{oauth["oauth_timestamp"]}\", oauth_version=\"#{oauth["oauth_version"]}\", oauth_token=\"#{oauth["oauth_token"]}\""

      # Normal API method
      else
        postdata = self.sign_request("POST", uri, args)
        headers = @headers
      end

      response = http.request_post(uri.request_uri, postdata, headers)
      if response.code == "204"
        return nil
      elsif response.code != "200"
        raise SmugMug::HTTPError.new("HTTP #{response.code}, #{response.message}", response.code, response.message)
      end

      # Check for GZIP encoding
      if response.header["content-encoding"] == "gzip"
        begin
          body = Zlib::GzipReader.new(StringIO.new(response.body)).read
        rescue Zlib::GzipFile::Error
          raise
        end
      else
        body = response.body
      end

      return nil if body == ""

      data = JSON.parse(body)

      if data["stat"] == "fail"
        # Special casing for SmugMug being in Read only mode
        if data["code"] == 99
          raise SmugMug::ReadonlyModeError.new("SmugMug is currently in read only mode, try again later")
        end

        klass = OAUTH_ERRORS[data["code"]] ? SmugMug::OAuthError : SmugMug::RequestError
        raise klass.new("Error ##{data["code"]}, #{data["message"]}", data["code"], data["message"])
      end

      data.delete("stat")
      data.delete("method")

      # smugmug.albums.changeSettings at the least doesn't return any data
      return nil if data.length == 0

      # It seems all smugmug APIs only return one hash of data, so this should be fine and not cause issues
      data.each do |_, value|
        return value
      end
    end
Creates a new HTTP wrapper to handle the network portions of the API requests
 @param [Hash] args Same as [SmugMug::HTTP]