module NiceHttpHttpMethods

Public Instance Methods

delete(argument) click to toggle source

Delete an existing resource @param argument [Hash, String] hash containing at least key :path or a string with the path

@return [Hash] response

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.delete(Requests::Customer.remove_session)
assert resp.code == 204
# File lib/nice_http/http_methods.rb, line 482
def delete(argument)
  begin
    if argument.kind_of?(String)
      argument = { :path => argument }
    end
    path, data, headers_t = manage_request(argument)
    @start_time = Time.now if @start_time.nil?
    if argument.kind_of?(Hash)
      arg = argument
      if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
        data = ""
        if arg[:mock_response].keys.include?(:data)
          data = arg[:mock_response][:data]
          if data.kind_of?(Hash) #to json
            begin
              require "json"
              data = data.to_json
            rescue
              @logger.fatal "There was a problem converting to json: #{data}"
            end
          end
        end
        @logger.warn "Pay attention!!! This is a mock response:"
        @start_time_net = Time.now if @start_time_net.nil?
        manage_response(arg[:mock_response], data.to_s)
        return @response
      end
    end

    begin
      @start_time_net = Time.now if @start_time_net.nil?
      if data.to_s == ""
        resp = @http.delete(path, headers_t)
        if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
          try = false
          @headers_orig.each do |k,v| 
            if v.is_a?(Proc) and headers_t.key?(k)
              try = true
              headers_t[k] = v.call 
            end
          end
          if try
            @logger.warn "Not authorized. Trying to generate a new token."
            resp = @http.delete(path, headers_t)
          end
        end
      else
        request = Net::HTTP::Delete.new(path, headers_t)
        request.body = data
        resp = @http.request(request)
        if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
          try = false
          @headers_orig.each do |k,v| 
            if v.is_a?(Proc) and headers_t.key?(k)
              try = true
              headers_t[k] = v.call 
            end
          end
          if try
            @logger.warn "Not authorized. Trying to generate a new token."
            request = Net::HTTP::Delete.new(path, headers_t)
            request.body = data
            resp = @http.request(request)
          end
        end
      end
      data = resp.body
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}        
        @start_time_net = Time.now if @start_time_net.nil?
        resp, data = @http.delete(path, headers_t)
      end          
    end
    manage_response(resp, data)

    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
  end
end
get(arg, save_data: '') click to toggle source

Get data from path

@param arg [Hash, String] hash containing at least key :path or a string with the path @param save_data [String] the path or path and file name where we want to save the response data

@return [Hash] response.

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.get(Requests::Customer.get_profile)
assert resp.code == 200

@example

resp = @http.get("/customers/1223")
assert resp.message == "OK"

@example

resp = @http.get("/assets/images/logo.png", save_data: './tmp/')

@example

resp = @http.get("/assets/images/logo.png", save_data: './tmp/example.png')
# File lib/nice_http/http_methods.rb, line 29
def get(arg, save_data: '')
  begin
    path, data, headers_t = manage_request(arg)

    @start_time = Time.now if @start_time.nil?
    if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
      data = ""
      if arg[:mock_response].keys.include?(:data)
        data = arg[:mock_response][:data]
        if data.kind_of?(Hash) #to json
          begin
            require "json"
            data = data.to_json
          rescue
            @logger.fatal "There was a problem converting to json: #{data}"
          end
        end
      end
      @logger.warn "Pay attention!!! This is a mock response:"
      @start_time_net = Time.now if @start_time_net.nil?
      manage_response(arg[:mock_response], data.to_s)
      return @response
    end
    begin
      if path.start_with?("http:") or path.start_with?("https:") #server included on path problably because of a redirection to a different server
        require "uri"
        uri = URI.parse(path)
        ssl = false
        ssl = true if path.include?("https:")

        server = "http://"
        server = "https://" if path.start_with?("https:")
        if uri.port != 443
          server += "#{uri.host}:#{uri.port}"
        else
          server += "#{uri.host}"
        end

        http_redir = nil
        self.class.connections.each { |conn|
          if conn.host == uri.host and conn.port == uri.port
            http_redir = conn
            break
          end
        }

        if !http_redir.nil?
          path, data, headers_t = manage_request(arg)
          http_redir.cookies.merge!(@cookies)
          http_redir.headers.merge!(headers_t)
          #todo: remove only the server at the begining in case in query is the server it will be replaced when it should not be
          resp = http_redir.get(path.gsub(server, ""))
          @response = http_redir.response
        else
          @logger.warn "It seems like the http connection cannot redirect to #{server} because there is no active connection for that server. You need to create previously one."
        end
      else
        @start_time_net = Time.now if @start_time_net.nil?
        resp = @http.get(path, headers_t)
        if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
          try = false
          @headers_orig.each do |k,v| 
            if v.is_a?(Proc) and headers_t.key?(k)
              try = true
              headers_t[k] = v.call 
            end
          end
          if try
            @logger.warn "Not authorized. Trying to generate a new token."
            resp = @http.get(path, headers_t)
          end
        end
        data = resp.body
        manage_response(resp, data)
      end
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @start_time_net = Time.now if @start_time_net.nil?
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}
        resp = @http.get(path, headers_t)
        data = resp.body
        manage_response(resp, data)
      end
    end
    if @auto_redirect and @response[:code].to_i >= 300 and @response[:code].to_i < 400 and @response.include?(:location)
      if @num_redirects <= 30
        @num_redirects += 1
        current_server = "http"
        current_server += "s" if @ssl == true
        current_server += "://#{@host}"
        location = @response[:location].gsub(current_server, "")
        @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
        get(location)
      else
        @logger.fatal "(#{@num_redirects}) Maximum number of redirections for a single request reached. Be sure everything is correct, it seems there is a non ending loop"
        @num_redirects = 0
      end
    else
      @num_redirects = 0
    end
    if save_data!=''
      require 'pathname'
      pn_get = Pathname.new(path)

      if Dir.exist?(save_data)
        save = save_data + "/" + pn_get.basename.to_s
      elsif save_data[-1]=="/"
        save = save_data + pn_get.basename.to_s
      else
        save = save_data
      end
      if Dir.exist?(Pathname.new(save).dirname)
        File.open(save, 'wb') { |fp| fp.write(@response.data) }
      else
        @logger.fatal "The folder #{Pathname.new(save).dirname} doesn't exist"
      end
    end
    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
  end
end
head(argument) click to toggle source

Implementation of the http HEAD method.

Asks for the response identical to the one that would correspond to a GET request, but without the response body.

This is useful for retrieving meta-information written in response headers, without having to transport the entire content. @param argument [Hash, String] hash containing at least key :path or directly an string with the path

@return [Hash] response

Including at least the symbol keys:  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
message and code can also be accessed as attributes like .message .code.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil }
# File lib/nice_http/http_methods.rb, line 586
def head(argument)
  begin
    if argument.kind_of?(String)
      argument = { :path => argument }
    end
    path, data, headers_t = manage_request(argument)
    @start_time = Time.now if @start_time.nil?
    if argument.kind_of?(Hash)
      arg = argument
      if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
        @logger.warn "Pay attention!!! This is a mock response:"
        @start_time_net = Time.now if @start_time_net.nil?
        manage_response(arg[:mock_response], "")
        return @response
      end
    end

    begin
      @start_time_net = Time.now if @start_time_net.nil?
      resp = @http.head(path, headers_t)
      if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
        try = false
        @headers_orig.each do |k,v| 
          if v.is_a?(Proc) and headers_t.key?(k)
            try = true
            headers_t[k] = v.call 
          end
        end
        if try
          @logger.warn "Not authorized. Trying to generate a new token."
          resp = @http.head(path, headers_t)
        end
      end
      data = resp.body
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}        
        @start_time_net = Time.now if @start_time_net.nil?
        resp, data = @http.head(path, headers_t)
      end
    end
    manage_response(resp, data)
    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil }
  end
end
patch(*arguments) click to toggle source

Patch data to path

@param arguments [Hash] containing at least keys :data and :path.

In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data.

@param arguments [Array<path, data, additional_headers>]

path (string).  
data (json data for example).  
additional_headers (Hash key=>value).

@return [Hash] response

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.patch(Requests::Customer.unrelease_account)
# File lib/nice_http/http_methods.rb, line 385
def patch(*arguments)
  begin
    path, data, headers_t = manage_request(*arguments)
    @start_time = Time.now if @start_time.nil?
    if arguments.size > 0 and arguments[0].kind_of?(Hash)
      arg = arguments[0]
      if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
        data = ""
        if arg[:mock_response].keys.include?(:data)
          data = arg[:mock_response][:data]
          if data.kind_of?(Hash) #to json
            begin
              require "json"
              data = data.to_json
            rescue
              @logger.fatal "There was a problem converting to json: #{data}"
            end
          end
        end
        @logger.warn "Pay attention!!! This is a mock response:"
        @start_time_net = Time.now if @start_time_net.nil?
        manage_response(arg[:mock_response], data.to_s)
        return @response
      end
    end

    begin
      @start_time_net = Time.now if @start_time_net.nil?
      resp = @http.patch(path, data, headers_t)
      if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
        try = false
        @headers_orig.each do |k,v| 
          if v.is_a?(Proc) and headers_t.key?(k)
            try = true
            headers_t[k] = v.call 
          end
        end
        if try
          @logger.warn "Not authorized. Trying to generate a new token."
          resp = @http.patch(path, data, headers_t)
        end
      end
      data = resp.body
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}        
        @start_time_net = Time.now if @start_time_net.nil?
        resp, data = @http.patch(path, data, headers_t)
      end
    end
    manage_response(resp, data)
    if @auto_redirect and @response[:code].to_i >= 300 and @response[:code].to_i < 400 and @response.include?(:location)
      if @num_redirects <= 30
        @num_redirects += 1
        current_server = "http"
        current_server += "s" if @ssl == true
        current_server += "://#{@host}"
        location = @response[:location].gsub(current_server, "")
        @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
        get(location)
      else
        @logger.fatal "(#{@num_redirects}) Maximum number of redirections for a single request reached. Be sure everything is correct, it seems there is a non ending loop"
        @num_redirects = 0
      end
    else
      @num_redirects = 0
    end
    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
  end
end
post(*arguments) click to toggle source

Post data to path @param arguments [Hash] containing at least keys :data and :path.

In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data.

@param arguments [Array<path, data, additional_headers>]

path (string).  
data (json data for example).  
additional_headers (Hash key=>value).

@return [Hash] response

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.post(Requests::Customer.update_customer)
assert resp.code == 201

@example

resp = http.post( {
                    path: "/api/users",
                    data: {name: "morpheus", job: "leader"}
                   } )
pp resp.data.json
# File lib/nice_http/http_methods.rb, line 186
def post(*arguments)
  begin
    path, data, headers_t = manage_request(*arguments)
    @start_time = Time.now if @start_time.nil?
    if arguments.size > 0 and arguments[0].kind_of?(Hash)
      arg = arguments[0]
      if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
        data = ""
        if arg[:mock_response].keys.include?(:data)
          data = arg[:mock_response][:data]
          if data.kind_of?(Hash) #to json
            begin
              require "json"
              data = data.to_json
            rescue
              @logger.fatal "There was a problem converting to json: #{data}"
            end
          end
        end
        @logger.warn "Pay attention!!! This is a mock response:"
        @start_time_net = Time.now if @start_time_net.nil?
        manage_response(arg[:mock_response], data.to_s)
        return @response
      end
    end

    begin
      @start_time_net = Time.now if @start_time_net.nil?
      if headers_t["Content-Type"] == "multipart/form-data"
        require "net/http/post/multipart"
        headers_t.each { |key, value|
          arguments[0][:data].add_field(key, value) #add to Headers
        }
        resp = @http.request(arguments[0][:data])
      elsif headers_t["Content-Type"].to_s.include?("application/x-www-form-urlencoded")
        encoded_form = URI.encode_www_form(arguments[0][:data])
        resp = @http.request_post(path, encoded_form, headers_t)
        data = resp.body
      else
        resp = @http.post(path, data, headers_t)
        #todo: do it also for forms and multipart
        if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
          try = false
          @headers_orig.each do |k,v| 
            if v.is_a?(Proc) and headers_t.key?(k)
              try = true
              headers_t[k] = v.call 
            end
          end
          if try
            @logger.warn "Not authorized. Trying to generate a new token."
            resp = @http.post(path, data, headers_t)
          end
        end
        data = resp.body
      end
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @start_time_net = Time.now if @start_time_net.nil?
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}
        resp, data = @http.post(path, data, headers_t)
      end
    end
    manage_response(resp, data)
    if @auto_redirect and @response[:code].to_i >= 300 and @response[:code].to_i < 400 and @response.include?(:location)
      if @num_redirects <= 30
        @num_redirects += 1
        current_server = "http"
        current_server += "s" if @ssl == true
        current_server += "://#{@host}"
        location = @response[:location].gsub(current_server, "")
        @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
        get(location)
      else
        @logger.fatal "(#{@num_redirects}) Maximum number of redirections for a single request reached. Be sure everything is correct, it seems there is a non ending loop"
        @num_redirects = 0
      end
    else
      @num_redirects = 0
    end
    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
  end
end
put(*arguments) click to toggle source

Put data to path @param arguments [Hash] containing at least keys :data and :path.

In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data.

@param arguments [Array<path, data, additional_headers>]

path (string).  
data (json data for example).  
additional_headers (Hash key=>value).

@return [Hash] response

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.put(Requests::Customer.remove_phone)
# File lib/nice_http/http_methods.rb, line 299
def put(*arguments)
  begin
    path, data, headers_t = manage_request(*arguments)
    @start_time = Time.now if @start_time.nil?
    if arguments.size > 0 and arguments[0].kind_of?(Hash)
      arg = arguments[0]
      if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
        data = ""
        if arg[:mock_response].keys.include?(:data)
          data = arg[:mock_response][:data]
          if data.kind_of?(Hash) #to json
            begin
              require "json"
              data = data.to_json
            rescue
              @logger.fatal "There was a problem converting to json: #{data}"
            end
          end
        end
        @logger.warn "Pay attention!!! This is a mock response:"
        @start_time_net = Time.now if @start_time_net.nil?
        manage_response(arg[:mock_response], data.to_s)
        return @response
      end
    end

    begin
      @start_time_net = Time.now if @start_time_net.nil?
      resp = @http.send_request("PUT", path, data, headers_t)
      if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
        try = false
        @headers_orig.each do |k,v| 
          if v.is_a?(Proc) and headers_t.key?(k)
            try = true
            headers_t[k] = v.call 
          end
        end
        if try
          @logger.warn "Not authorized. Trying to generate a new token."
          resp = @http.send_request("PUT", path, data, headers_t)
        end
      end
      data = resp.body
    rescue Exception => stack
      @logger.warn stack
      if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
        @logger.warn "The connection seems to be closed in the host machine. Timeout."
        return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
      else
        @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
        @http.finish()
        @http.start()
        @headers_orig.each {|k,v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k)}
        @start_time_net = Time.now if @start_time_net.nil?
        resp, data = @http.send_request("PUT", path, data, headers_t)
      end
    end
    manage_response(resp, data)

    return @response
  rescue Exception => stack
    @logger.fatal stack
    return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
  end
end
send_request(request_hash) click to toggle source

It will send the request depending on the :method declared on the request hash

Take a look at github.com/MarioRuiz/Request-Hash

@param request_hash [Hash] containing at least key :path and :method. The methods that are accepted are: :get, :head, :post, :put, :delete, :patch

@return [Hash] response

Including at least the symbol keys:  
  :data = the response data body.  
  :message = plain text response.  
  :code = code response (200=ok,500=wrong...).  
All keys in response are lowercase.  
data, message and code can also be accessed as attributes like .message .code .data.  
In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }

@example

resp = @http.send_request Requests::Customer.remove_session
assert resp.code == 204
# File lib/nice_http/http_methods.rb, line 660
def send_request(request_hash)
  unless request_hash.is_a?(Hash) and request_hash.key?(:method) and request_hash.key?(:path) and
         request_hash[:method].is_a?(Symbol) and
         [:get, :head, :post, :put, :delete, :patch].include?(request_hash[:method])
    message = "send_request: it needs to be supplied a Request Hash that includes a :method and :path. "
    message += "Supported methods: :get, :head, :post, :put, :delete, :patch"
    @logger.fatal message
    return { fatal_error: message, code: nil, message: nil }
  else
    case request_hash[:method]
    when :get
      resp = get request_hash
    when :post
      resp = post request_hash
    when :head
      resp = head request_hash
    when :put
      resp = put request_hash
    when :delete
      resp = delete request_hash
    when :patch
      resp = patch request_hash
    end
    return resp
  end
end