nice_http 1.8.10 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,122 @@
1
+ module NiceHttpHttpMethods
2
+
3
+ ######################################################
4
+ # Post data to path
5
+ # @param arguments [Hash] containing at least keys :data and :path.
6
+ # In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data.
7
+ # @param arguments [Array<path, data, additional_headers>]
8
+ # path (string).
9
+ # data (json data for example).
10
+ # additional_headers (Hash key=>value).
11
+ # @return [Hash] response
12
+ # Including at least the symbol keys:
13
+ # :data = the response data body.
14
+ # :message = plain text response.
15
+ # :code = code response (200=ok,500=wrong...).
16
+ # All keys in response are lowercase.
17
+ # data, message and code can also be accessed as attributes like .message .code .data.
18
+ # In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }
19
+ # @example
20
+ # resp = @http.post(Requests::Customer.update_customer)
21
+ # assert resp.code == 201
22
+ # @example
23
+ # resp = http.post( {
24
+ # path: "/api/users",
25
+ # data: {name: "morpheus", job: "leader"}
26
+ # } )
27
+ # pp resp.data.json
28
+ ######################################################
29
+ def post(*arguments)
30
+ begin
31
+ path, data, headers_t = manage_request(*arguments)
32
+ @start_time = Time.now if @start_time.nil?
33
+ if arguments.size > 0 and arguments[0].kind_of?(Hash)
34
+ arg = arguments[0]
35
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
36
+ data = ""
37
+ if arg[:mock_response].keys.include?(:data)
38
+ data = arg[:mock_response][:data]
39
+ if data.kind_of?(Hash) #to json
40
+ begin
41
+ require "json"
42
+ data = data.to_json
43
+ rescue
44
+ @logger.fatal "There was a problem converting to json: #{data}"
45
+ end
46
+ end
47
+ end
48
+ @logger.warn "Pay attention!!! This is a mock response:"
49
+ @start_time_net = Time.now if @start_time_net.nil?
50
+ manage_response(arg[:mock_response], data.to_s)
51
+ return @response
52
+ end
53
+ end
54
+
55
+ begin
56
+ @start_time_net = Time.now if @start_time_net.nil?
57
+ if headers_t["Content-Type"] == "multipart/form-data"
58
+ require "net/http/post/multipart"
59
+ headers_t.each { |key, value|
60
+ arguments[0][:data].add_field(key, value) #add to Headers
61
+ }
62
+ resp = @http.request(arguments[0][:data])
63
+ elsif headers_t["Content-Type"].to_s.include?("application/x-www-form-urlencoded")
64
+ encoded_form = URI.encode_www_form(arguments[0][:data])
65
+ resp = @http.request_post(path, encoded_form, headers_t)
66
+ data = resp.body
67
+ else
68
+ resp = @http.post(path, data, headers_t)
69
+ #todo: do it also for forms and multipart
70
+ if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
71
+ try = false
72
+ @headers_orig.each do |k, v|
73
+ if v.is_a?(Proc) and headers_t.key?(k)
74
+ try = true
75
+ headers_t[k] = v.call
76
+ end
77
+ end
78
+ if try
79
+ @logger.warn "Not authorized. Trying to generate a new token."
80
+ resp = @http.post(path, data, headers_t)
81
+ end
82
+ end
83
+ data = resp.body
84
+ end
85
+ rescue Exception => stack
86
+ @logger.warn stack
87
+ if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
88
+ @logger.warn "The connection seems to be closed in the host machine. Timeout."
89
+ return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
90
+ else
91
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
92
+ @http.finish()
93
+ @http.start()
94
+ @start_time_net = Time.now if @start_time_net.nil?
95
+ @headers_orig.each { |k, v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k) }
96
+ resp, data = @http.post(path, data, headers_t)
97
+ end
98
+ end
99
+ manage_response(resp, data)
100
+ if @auto_redirect and @response[:code].to_i >= 300 and @response[:code].to_i < 400 and @response.include?(:location)
101
+ if @num_redirects <= 30
102
+ @num_redirects += 1
103
+ current_server = "http"
104
+ current_server += "s" if @ssl == true
105
+ current_server += "://#{@host}"
106
+ location = @response[:location].gsub(current_server, "")
107
+ @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
108
+ get(location)
109
+ else
110
+ @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"
111
+ @num_redirects = 0
112
+ end
113
+ else
114
+ @num_redirects = 0
115
+ end
116
+ return @response
117
+ rescue Exception => stack
118
+ @logger.fatal stack
119
+ return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,87 @@
1
+ module NiceHttpHttpMethods
2
+
3
+ ######################################################
4
+ # Put data to path
5
+ # @param arguments [Hash] containing at least keys :data and :path.
6
+ # In case :data not supplied and :data_examples array supplied, it will be taken the first example as :data.
7
+ # @param arguments [Array<path, data, additional_headers>]
8
+ # path (string).
9
+ # data (json data for example).
10
+ # additional_headers (Hash key=>value).
11
+ # @return [Hash] response
12
+ # Including at least the symbol keys:
13
+ # :data = the response data body.
14
+ # :message = plain text response.
15
+ # :code = code response (200=ok,500=wrong...).
16
+ # All keys in response are lowercase.
17
+ # data, message and code can also be accessed as attributes like .message .code .data.
18
+ # In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }
19
+ # @example
20
+ # resp = @http.put(Requests::Customer.remove_phone)
21
+ ######################################################
22
+ def put(*arguments)
23
+ begin
24
+ path, data, headers_t = manage_request(*arguments)
25
+ @start_time = Time.now if @start_time.nil?
26
+ if arguments.size > 0 and arguments[0].kind_of?(Hash)
27
+ arg = arguments[0]
28
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response)
29
+ data = ""
30
+ if arg[:mock_response].keys.include?(:data)
31
+ data = arg[:mock_response][:data]
32
+ if data.kind_of?(Hash) #to json
33
+ begin
34
+ require "json"
35
+ data = data.to_json
36
+ rescue
37
+ @logger.fatal "There was a problem converting to json: #{data}"
38
+ end
39
+ end
40
+ end
41
+ @logger.warn "Pay attention!!! This is a mock response:"
42
+ @start_time_net = Time.now if @start_time_net.nil?
43
+ manage_response(arg[:mock_response], data.to_s)
44
+ return @response
45
+ end
46
+ end
47
+
48
+ begin
49
+ @start_time_net = Time.now if @start_time_net.nil?
50
+ resp = @http.send_request("PUT", path, data, headers_t)
51
+ if (resp.code == 401 or resp.code == 408) and @headers_orig.values.map(&:class).include?(Proc)
52
+ try = false
53
+ @headers_orig.each do |k, v|
54
+ if v.is_a?(Proc) and headers_t.key?(k)
55
+ try = true
56
+ headers_t[k] = v.call
57
+ end
58
+ end
59
+ if try
60
+ @logger.warn "Not authorized. Trying to generate a new token."
61
+ resp = @http.send_request("PUT", path, data, headers_t)
62
+ end
63
+ end
64
+ data = resp.body
65
+ rescue Exception => stack
66
+ @logger.warn stack
67
+ if !@timeout.nil? and (Time.now - @start_time_net) > @timeout
68
+ @logger.warn "The connection seems to be closed in the host machine. Timeout."
69
+ return { fatal_error: "Net::ReadTimeout", code: nil, message: nil, data: "" }
70
+ else
71
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
72
+ @http.finish()
73
+ @http.start()
74
+ @headers_orig.each { |k, v| headers_t[k] = v.call if v.is_a?(Proc) and headers_t.key?(k) }
75
+ @start_time_net = Time.now if @start_time_net.nil?
76
+ resp, data = @http.send_request("PUT", path, data, headers_t)
77
+ end
78
+ end
79
+ manage_response(resp, data)
80
+
81
+ return @response
82
+ rescue Exception => stack
83
+ @logger.fatal stack
84
+ return { fatal_error: stack.to_s, code: nil, message: nil, data: "" }
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,47 @@
1
+ module NiceHttpHttpMethods
2
+
3
+ ######################################################
4
+ # It will send the request depending on the :method declared on the request hash
5
+ # Take a look at https://github.com/MarioRuiz/Request-Hash
6
+ #
7
+ # @param request_hash [Hash] containing at least key :path and :method. The methods that are accepted are: :get, :head, :post, :put, :delete, :patch
8
+ #
9
+ # @return [Hash] response
10
+ # Including at least the symbol keys:
11
+ # :data = the response data body.
12
+ # :message = plain text response.
13
+ # :code = code response (200=ok,500=wrong...).
14
+ # All keys in response are lowercase.
15
+ # data, message and code can also be accessed as attributes like .message .code .data.
16
+ # In case of fatal error returns { fatal_error: "the error description", code: nil, message: nil, data: '' }
17
+ # @example
18
+ # resp = @http.send_request Requests::Customer.remove_session
19
+ # assert resp.code == 204
20
+ ######################################################
21
+ def send_request(request_hash)
22
+ unless request_hash.is_a?(Hash) and request_hash.key?(:method) and request_hash.key?(:path) and
23
+ request_hash[:method].is_a?(Symbol) and
24
+ [:get, :head, :post, :put, :delete, :patch].include?(request_hash[:method])
25
+ message = "send_request: it needs to be supplied a Request Hash that includes a :method and :path. "
26
+ message += "Supported methods: :get, :head, :post, :put, :delete, :patch"
27
+ @logger.fatal message
28
+ return { fatal_error: message, code: nil, message: nil }
29
+ else
30
+ case request_hash[:method]
31
+ when :get
32
+ resp = get request_hash
33
+ when :post
34
+ resp = post request_hash
35
+ when :head
36
+ resp = head request_hash
37
+ when :put
38
+ resp = put request_hash
39
+ when :delete
40
+ resp = delete request_hash
41
+ when :patch
42
+ resp = patch request_hash
43
+ end
44
+ return resp
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ class NiceHttp
2
+ ######################################################
3
+ # to reset to the original defaults
4
+ ######################################################
5
+ def self.reset!
6
+ @host = nil
7
+ @port = 80
8
+ @ssl = false
9
+ @timeout = nil
10
+ @headers = {}
11
+ @values_for = {}
12
+ @debug = false
13
+ @log = :fix_file
14
+ @log_path = ""
15
+ @log_headers = :all
16
+ @proxy_host = nil
17
+ @proxy_port = nil
18
+ @last_request = nil
19
+ @request = nil
20
+ @requests = nil
21
+ @last_response = nil
22
+ @request_id = ""
23
+ @use_mocks = false
24
+ @connections = []
25
+ @active = 0
26
+ @auto_redirect = true
27
+ @log_files = {}
28
+ @create_stats = false
29
+ @stats = {
30
+ all: {
31
+ num_requests: 0,
32
+ started: nil,
33
+ finished: nil,
34
+ real_time_elapsed: 0,
35
+ time_elapsed: {
36
+ total: 0,
37
+ maximum: 0,
38
+ minimum: 1000000,
39
+ average: 0,
40
+ },
41
+ method: {},
42
+ },
43
+ path: {},
44
+ name: {},
45
+ }
46
+ @capture = false
47
+ @captured = []
48
+ @async_wait_seconds = 0
49
+ @async_header = "location"
50
+ @async_completed = ""
51
+ @async_resource = ""
52
+ @async_status = ""
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ class NiceHttp
2
+ ######################################################
3
+ # It will save the NiceHttp.stats on different files, each key of the hash in a different file.
4
+ #
5
+ # @param file_name [String] path and file name to be used to store the stats.
6
+ # In case no one supplied it will be used the value in NiceHttp.log and it will be saved on YAML format.
7
+ # In case extension is .yaml will be saved on YAML format.
8
+ # In case extension is .json will be saved on JSON format.
9
+ #
10
+ # @example
11
+ # NiceHttp.save_stats
12
+ # NiceHttp.save_stats('./stats/my_stats.yaml')
13
+ # NiceHttp.save_stats('./stats/my_stats.json')
14
+ ######################################################
15
+ def self.save_stats(file_name = "")
16
+ if file_name == ""
17
+ if self.log.is_a?(String)
18
+ file_name = self.log
19
+ else
20
+ file_name = "./#{self.log_path}nice_http.log"
21
+ end
22
+ end
23
+ require "fileutils"
24
+ FileUtils.mkdir_p File.dirname(file_name)
25
+ if file_name.match?(/\.json$/)
26
+ require "json"
27
+ self.stats.keys.each do |key|
28
+ File.open("#{file_name.gsub(/.json$/, "_stats_")}#{key}.json", "w") { |file| file.write(self.stats[key].to_json) }
29
+ end
30
+ else
31
+ require "yaml"
32
+ self.stats.keys.each do |key|
33
+ File.open("#{file_name.gsub(/.\w+$/, "_stats_")}#{key}.yaml", "w") { |file| file.write(self.stats[key].to_yaml) }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+ module NiceHttpUtils
2
+ ##################################################
3
+ # returns the seed for Basic authentication
4
+ # @param user [String]
5
+ # @param password [String]
6
+ # @param strict [Boolean] (default: false) use strict_encode64 if true, if not encode64
7
+ # @return [String] seed string to be used on Authorization key header on a get request
8
+ ####################################################
9
+ def self.basic_authentication(user:, password:, strict: false)
10
+ require "base64"
11
+ if strict
12
+ seed = "Basic " + Base64.strict_encode64(user + ":" + password)
13
+ else
14
+ seed = "Basic " + Base64.encode64(user + ":" + password)
15
+ end
16
+ return seed
17
+ end
18
+ end
@@ -60,49 +60,4 @@ module NiceHttpUtils
60
60
  return ret
61
61
  end
62
62
  end
63
-
64
- ##################################################
65
- # set a value on xml tag
66
- # @param tag_name [String]
67
- # @param xml_string [String]
68
- # @param value [String]
69
- # @param take_off_prefix [Boolean] (optional). true, false(default)
70
- # @return [String] with the new value
71
- ####################################################
72
- def self.set_value_xml_tag(tag_name, xml_string, value, take_off_prefix = false)
73
- tag_name = tag_name.to_s
74
- if take_off_prefix
75
- i = tag_name.index(":")
76
- tag_name = tag_name[i + 1..tag_name.length] unless i.nil?
77
- end
78
- if xml_string.to_s != ""
79
- if take_off_prefix
80
- old_value = NiceHttpUtils.get_value_xml_tag(tag_name, xml_string.dup, true)
81
- xml_string.gsub!(/:#{tag_name}>#{Regexp.escape(old_value)}<\//i, ":" + tag_name + ">" + value + "</")
82
- xml_string.gsub!(/<#{tag_name}>#{Regexp.escape(old_value)}<\//i, "<" + tag_name + ">" + value + "</")
83
- else
84
- xml_string.gsub!(/<#{tag_name}>.*<\/#{tag_name}>/i, "<" + tag_name + ">" + value + "</" + tag_name + ">")
85
- end
86
- return xml_string
87
- else
88
- return ""
89
- end
90
- end
91
-
92
- ##################################################
93
- # returns the seed for Basic authentication
94
- # @param user [String]
95
- # @param password [String]
96
- # @param strict [Boolean] (default: false) use strict_encode64 if true, if not encode64
97
- # @return [String] seed string to be used on Authorization key header on a get request
98
- ####################################################
99
- def self.basic_authentication(user:, password:, strict: false)
100
- require "base64"
101
- if strict
102
- seed = "Basic " + Base64.strict_encode64(user + ":" + password)
103
- else
104
- seed = "Basic " + Base64.encode64(user + ":" + password)
105
- end
106
- return seed
107
- end
108
63
  end
@@ -0,0 +1,30 @@
1
+ module NiceHttpUtils
2
+
3
+ ##################################################
4
+ # set a value on xml tag
5
+ # @param tag_name [String]
6
+ # @param xml_string [String]
7
+ # @param value [String]
8
+ # @param take_off_prefix [Boolean] (optional). true, false(default)
9
+ # @return [String] with the new value
10
+ ####################################################
11
+ def self.set_value_xml_tag(tag_name, xml_string, value, take_off_prefix = false)
12
+ tag_name = tag_name.to_s
13
+ if take_off_prefix
14
+ i = tag_name.index(":")
15
+ tag_name = tag_name[i + 1..tag_name.length] unless i.nil?
16
+ end
17
+ if xml_string.to_s != ""
18
+ if take_off_prefix
19
+ old_value = NiceHttpUtils.get_value_xml_tag(tag_name, xml_string.dup, true)
20
+ xml_string.gsub!(/:#{tag_name}>#{Regexp.escape(old_value)}<\//i, ":" + tag_name + ">" + value + "</")
21
+ xml_string.gsub!(/<#{tag_name}>#{Regexp.escape(old_value)}<\//i, "<" + tag_name + ">" + value + "</")
22
+ else
23
+ xml_string.gsub!(/<#{tag_name}>.*<\/#{tag_name}>/i, "<" + tag_name + ">" + value + "</" + tag_name + ">")
24
+ end
25
+ return xml_string
26
+ else
27
+ return ""
28
+ end
29
+ end
30
+ end