module NiceHttpManageRequest
Public Instance Methods
manage_request(*arguments)
click to toggle source
private method to manage Request
input: 3 args: path, data, headers 1 arg: Hash containg at least keys :path and :data In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data. output: path, data, headers
# File lib/nice_http/manage_request.rb, line 12 def manage_request(*arguments) require "json" @prev_request = Hash.new() if @prev_request.nil? @defaults_request = self.class.requests if @defaults_request.nil? and self.class.requests.is_a?(Hash) @request = Hash.new() if @request.nil? @defaults_request = Hash.new() unless @defaults_request.is_a?(Hash) begin content_type_included = false path = "" data = "" @response = Hash.new() headers_t = @headers.dup() headers_t.merge!(@defaults_request[:headers]) if @defaults_request.key?(:headers) cookies_to_set_str = "" if arguments.size == 3 path = arguments[0] elsif arguments.size == 1 and arguments[0].kind_of?(Hash) path = arguments[0][:path] elsif arguments.size == 1 and arguments[0].kind_of?(String) path = arguments[0].to_s() end path = (@prepath + path).gsub("//", "/") unless path.nil? or path.start_with?("http:") or path.start_with?("https:") @cookies.each { |cookie_path, cookies_hash| cookie_path = "" if cookie_path == "/" path_to_check = path if path == "/" or path[-1] != "/" path_to_check += "/" end if path_to_check.scan(/^#{cookie_path}\//).size > 0 cookies_hash.each { |key, value| cookies_to_set_str += "#{key}=#{value}; " } end } headers_t["Cookie"] = cookies_to_set_str method_s = caller[0].to_s().scan(/:in `(.*)'/).join if arguments.size == 3 data = arguments[1] if arguments[2].kind_of?(Hash) headers_t.merge!(arguments[2]) end elsif arguments.size == 1 and arguments[0].kind_of?(Hash) if arguments[0][:data].nil? if arguments[0].keys.include?(:data) data = "" elsif arguments[0].keys.include?(:data_examples) and arguments[0][:data_examples].kind_of?(Array) data = arguments[0][:data_examples][0] #the first example by default else data = "" end else data = arguments[0][:data] end if arguments[0].include?(:headers) headers_t.merge!(arguments[0][:headers]) end if headers_t["Content-Type"].to_s() == "" and headers_t["content-type"].to_s() == "" and headers_t[:"content-type"].to_s() == "" and headers_t[:"Content-Type"].to_s() == "" content_type_included = false elsif headers_t["content-type"].to_s() != "" content_type_included = true headers_t["Content-Type"] = headers_t["content-type"] elsif headers_t[:"content-type"].to_s() != "" content_type_included = true headers_t["Content-Type"] = headers_t[:"content-type"] headers_t.delete(:"content-type") elsif headers_t[:"Content-Type"].to_s() != "" content_type_included = true headers_t["Content-Type"] = headers_t[:"Content-Type"] headers_t.delete(:"Content-Type") elsif headers_t["Content-Type"].to_s() != "" content_type_included = true end if !content_type_included and (data.kind_of?(Hash) or data.kind_of?(Array)) headers_t["Content-Type"] = "application/json" content_type_included = true end # to be backwards compatible since before was :values if arguments[0].include?(:values) and !arguments[0].include?(:values_for) arguments[0][:values_for] = arguments[0][:values] end if @values_for.size > 0 if arguments[0][:values_for].nil? arguments[0][:values_for] = @values_for.dup else arguments[0][:values_for] = @values_for.merge(arguments[0][:values_for]) end end if content_type_included and (!headers_t["Content-Type"][/text\/xml/].nil? or !headers_t["Content-Type"]["application/soap+xml"].nil? or !headers_t["Content-Type"][/application\/jxml/].nil?) if arguments[0].include?(:values_for) arguments[0][:values_for].each { |key, value| #todo: implement set_nested data = NiceHttpUtils.set_value_xml_tag(key.to_s(), data, value.to_s(), true) } end elsif content_type_included and !headers_t["Content-Type"][/application\/json/].nil? and data.to_s() != "" require "json" if data.kind_of?(String) if arguments[0].include?(:values_for) arguments[0][:values_for].each { |key, value| #todo: implement set_nested data.gsub!(/"(#{key})":\s*"([^"]*)"/, '"\1": "' + value + '"') # "key":"value" data.gsub!(/(#{key}):\s*"([^"]*)"/, '\1: "' + value + '"') # key:"value" data.gsub!(/(#{key}):\s*'([^']*)'/, '\1: \'' + value + "'") # key:'value' data.gsub!(/"(#{key})":\s*(\w+)/, '"\1": ' + value) # "key":456 data.gsub!(/(#{key}):\s*(\w+)/, '\1: ' + value) # key:456 } end elsif data.kind_of?(Hash) data.merge!(@defaults_request[:data]) if @defaults_request.key?(:data) #lambdas on data only supports on root of the hash data.each do |k, v| if v.is_a?(Proc) data[k] = v.call end end if arguments[0].include?(:values_for) data = data.set_values(arguments[0][:values_for]) end data = data.to_json() elsif data.kind_of?(Array) #todo: implement set_nested data_arr = Array.new() data.each_with_index { |row, indx| if arguments[0].include?(:values_for) and (row.is_a?(Array) or row.is_a?(Hash)) if arguments[0][:values_for].is_a?(Array) data_n = row.set_values(arguments[0][:values_for][indx]) elsif arguments[0][:values_for].is_a?(Hash) data_n = row.set_values(arguments[0][:values_for]) else @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string. values_for needs to be an array or a hash.") return :error, :error, :error end else data_n = row end data_arr.push(data_n) } data = data_arr.to_json() else @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string") return :error, :error, :error end elsif content_type_included and arguments[0].include?(:values_for) if arguments[0][:values_for].kind_of?(Hash) and arguments[0][:values_for].keys.size > 0 if !headers_t.nil? and headers_t.kind_of?(Hash) and headers_t["Content-Type"] != "application/x-www-form-urlencoded" and headers_t["content-type"] != "application/x-www-form-urlencoded" @logger.warn(":values_for key given without a valid content-type or data for request. No values modified on the request") end end end elsif arguments.size == 1 and arguments[0].kind_of?(String) #path=arguments[0].to_s() data = "" else @logger.fatal("Invalid number of arguments or wrong arguments in #{method_s}") return :error, :error, :error end if headers_t.keys.include?("Content-Type") and !headers_t["Content-Type"]["multipart/form-data"].nil? and headers_t["Content-Type"] != ["multipart/form-data"] #only for the case raw multipart request encoding = "UTF-8" data_s = "" else encoding = data.to_s().scan(/encoding='(.*)'/i).join if encoding.to_s() == "" encoding = data.to_s().scan(/charset='(.*)'/i).join end if encoding.to_s() == "" and headers_t.include?("Content-Type") encoding = headers_t["Content-Type"].scan(/charset='?(.*)'?/i).join if encoding.to_s() == "" encoding = headers_t["Content-Type"].scan(/encoding='?(.*)'?/i).join end end begin data_s = JSON.pretty_generate(JSON.parse(data)) rescue data_s = data end data_s = data_s.to_s().gsub("<", "<") end if headers_t.keys.include?("Accept-Encoding") headers_t["Accept-Encoding"].gsub!("gzip", "") #removed so the response is in plain text end if data.to_s() != "" and encoding.to_s().upcase != "UTF-8" and encoding != "" data = data.to_s().encode(encoding, "UTF-8") end @request[:path] = path @request[:data] = data @request[:headers] = headers_t @request[:method] = method_s.upcase if arguments.size == 1 and arguments[0].kind_of?(Hash) and arguments[0].key?(:name) @request[:name] = arguments[0][:name] end self.class.request = @request headers_t.each do |k, v| # for lambdas if v.is_a?(Proc) headers_t[k] = v.call end end @request[:headers] = headers_t self.class.request = @request if @debug or @prev_request[:path] != path or @prev_request[:headers] != headers_t or @prev_request[:data] != data show_headers_data = true else show_headers_data = false end @prev_request[:path] = path @prev_request[:data] = data @prev_request[:headers] = headers_t @prev_request[:method] = method_s.upcase if arguments.size == 1 and arguments[0].kind_of?(Hash) and arguments[0].key?(:name) @prev_request[:name] = arguments[0][:name] end headers_ts = "" if @log_headers == :none @logger.info "No header values since option log_headers is set to :none" headers_t.each { |key, val| headers_ts += key.to_s + ":" + "''" + ", " } elsif @log_headers == :partial @logger.info "Just the last 10 characters on header values since option log_headers is set to :partial" headers_t.each { |key, val| if val.to_s.size>10 headers_ts += key.to_s + ": ..." + (val.to_s[-10..-1] || val.to_s) + ", " else headers_ts += key.to_s + ":" + (val.to_s[-10..-1] || val.to_s) + ", " end } else headers_t.each { |key, val| headers_ts += key.to_s + ":" + val.to_s() + ", " } end message = "\n\n#{"- " * 25}\n" if arguments.size == 1 and arguments[0].kind_of?(Hash) and arguments[0].key?(:name) message += "#{method_s.upcase} Request: #{arguments[0][:name]}" else message += "#{method_s.upcase} Request" end message += "\n path: " + path.to_s() + "\n" if show_headers_data message += " headers: {" + headers_ts.to_s() + "}\n" message += " data: " + data_s.to_s() + "\n" message = @message_server + "\n" + message else message += " Same#{" headers" if headers_t != {}}#{" and" if headers_t != {} and data.to_s != ""}#{" data" if data.to_s != ""} as in the previous request." end if path.to_s().scan(/^https?:\/\//).size > 0 and path.to_s().scan(/^https?:\/\/#{@host}/).size == 0 # the path is for another server than the current # todo: identify if it is better to log the request, or if it is done later else self.class.last_request = message @logger.info(message) end return path, data, headers_t rescue Exception => stack @logger.fatal(stack) @logger.fatal("manage_request Error on method #{method_s} . path:#{path.to_s()}. data:#{data.to_s()}. headers:#{headers_t.to_s()}") return :error end end