nice_http 1.7.3 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +607 -607
- data/lib/nice_http.rb +428 -414
- data/lib/nice_http/http_methods.rb +526 -526
- data/lib/nice_http/manage_request.rb +237 -237
- data/lib/nice_http/manage_response.rb +279 -280
- data/lib/nice_http/utils.rb +109 -109
- metadata +4 -4
data/lib/nice_http.rb
CHANGED
@@ -1,414 +1,428 @@
|
|
1
|
-
require "logger"
|
2
|
-
require "nice_hash"
|
3
|
-
require_relative "nice_http/utils"
|
4
|
-
require_relative "nice_http/manage_request"
|
5
|
-
require_relative "nice_http/manage_response"
|
6
|
-
require_relative "nice_http/http_methods"
|
7
|
-
|
8
|
-
######################################################
|
9
|
-
# Attributes you can access using NiceHttp.the_attribute:
|
10
|
-
# :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
|
11
|
-
# :last_request, :last_response, :request_id, :use_mocks, :connections,
|
12
|
-
# :active, :auto_redirect, :values_for, :create_stats, :stats
|
13
|
-
#
|
14
|
-
# @attr [String] host The host to be accessed
|
15
|
-
# @attr [Integer] port The port number
|
16
|
-
# @attr [Boolean] ssl If you use ssl or not
|
17
|
-
# @attr [Hash] headers Contains the headers you will be using on your connection
|
18
|
-
# @attr [Boolean] debug In case true shows all the details of the communication with the host
|
19
|
-
# @attr [String, Symbol] log :fix_file, :no, :screen, :file, "path and file name".
|
20
|
-
# :fix_file, will log the communication on nice_http.log. (default).
|
21
|
-
# :no, will not generate any logs.
|
22
|
-
# :screen, will print the logs on the screen.
|
23
|
-
# :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.
|
24
|
-
# :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log
|
25
|
-
# String the path and file name where the logs will be stored.
|
26
|
-
# @attr [String] proxy_host the proxy host to be used
|
27
|
-
# @attr [Integer] proxy_port the proxy port to be used
|
28
|
-
# @attr [String] last_request The last request with all the content sent
|
29
|
-
# @attr [String] last_response Only in case :debug is true, the last response with all the content
|
30
|
-
# @attr [String] request_id If the response includes a requestId, will be stored here
|
31
|
-
# @attr [Boolean] use_mocks If true, in case the request hash includes a :mock_response key, it will be used as the response instead
|
32
|
-
# @attr [Array] connections It will include all the active connections (NiceHttp instances)
|
33
|
-
# @attr [Integer] active Number of active connections
|
34
|
-
# @attr [Boolean] auto_redirect If true, NiceHttp will take care of the auto redirections when required by the responses
|
35
|
-
# @attr [Hash] response Contains the full response hash
|
36
|
-
# @attr [Integer] num_redirects Number of consecutive redirections managed
|
37
|
-
# @attr [Hash] headers The updated headers of the communication
|
38
|
-
# @attr [Hash] cookies Cookies set. The key is the path (String) where cookies are set and the value a Hash with pairs of cookie keys and values, example:
|
39
|
-
# { '/' => { "cfid" => "d95adfas2550255", "amddom.settings" => "doom" } }
|
40
|
-
# @attr [Logger] logger An instance of the Logger class where logs will be stored. You can access on anytime to store specific data, for example:
|
41
|
-
# my_http.logger.info "add this to the log file"
|
42
|
-
# @see https://ruby-doc.org/stdlib-2.5.0/libdoc/logger/rdoc/Logger.html
|
43
|
-
# @attr [Hash] values_for The default values to set on the data in case not specified others
|
44
|
-
# @attr [Boolean] create_stats If true, NiceHttp will create stats of the http communication and store them on NiceHttp.stats hash
|
45
|
-
# @attr [Hash] stats It contains detailed stats of the http communication
|
46
|
-
######################################################
|
47
|
-
class NiceHttp
|
48
|
-
include NiceHttpManageRequest
|
49
|
-
include NiceHttpManageResponse
|
50
|
-
include NiceHttpHttpMethods
|
51
|
-
|
52
|
-
Error = Class.new StandardError
|
53
|
-
|
54
|
-
InfoMissing = Class.new Error do
|
55
|
-
attr_reader :attribute
|
56
|
-
|
57
|
-
def initialize(attribute)
|
58
|
-
@attribute = attribute
|
59
|
-
message
|
60
|
-
message += "Wrong #{attribute}
|
61
|
-
message += "http
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@
|
87
|
-
@
|
88
|
-
@
|
89
|
-
@
|
90
|
-
@
|
91
|
-
@
|
92
|
-
@
|
93
|
-
@
|
94
|
-
@
|
95
|
-
@
|
96
|
-
@
|
97
|
-
@
|
98
|
-
@
|
99
|
-
@
|
100
|
-
@
|
101
|
-
@
|
102
|
-
@
|
103
|
-
@
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
#
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
@
|
138
|
-
@
|
139
|
-
@
|
140
|
-
@
|
141
|
-
@
|
142
|
-
@
|
143
|
-
@
|
144
|
-
@
|
145
|
-
@
|
146
|
-
@
|
147
|
-
@
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
# @param
|
156
|
-
# @param
|
157
|
-
# @param
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
self.stats[:specific]
|
172
|
-
self.stats[:specific][name]
|
173
|
-
|
174
|
-
time_elapsed[:
|
175
|
-
time_elapsed[:
|
176
|
-
time_elapsed[:
|
177
|
-
time_elapsed[:
|
178
|
-
|
179
|
-
|
180
|
-
self.stats[:specific][name][state]
|
181
|
-
|
182
|
-
time_elapsed[:
|
183
|
-
time_elapsed[:
|
184
|
-
time_elapsed[:
|
185
|
-
time_elapsed[:
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
######################################################
|
190
|
-
# Creates a new http connection.
|
191
|
-
#
|
192
|
-
# @param args [] If no parameter supplied, by default will access how is setup on defaults
|
193
|
-
# @example
|
194
|
-
# http = NiceHttp.new()
|
195
|
-
# @param args [String]. The url to create the connection.
|
196
|
-
# @example
|
197
|
-
# http = NiceHttp.new("https://www.example.com")
|
198
|
-
# @example
|
199
|
-
# http = NiceHttp.new("example.com:8999")
|
200
|
-
# @example
|
201
|
-
# http = NiceHttp.new("localhost:8322")
|
202
|
-
# @param args [Hash] containing these possible keys:
|
203
|
-
#
|
204
|
-
# host -- example.com. (default blank screen)
|
205
|
-
#
|
206
|
-
# port -- port for the connection. 80 (default)
|
207
|
-
#
|
208
|
-
# ssl -- true, false (default)
|
209
|
-
#
|
210
|
-
# headers -- hash with the headers
|
211
|
-
#
|
212
|
-
# values_for -- hash with the values_for
|
213
|
-
#
|
214
|
-
# debug -- true, false (default)
|
215
|
-
#
|
216
|
-
# log -- :no, :screen, :file, :fix_file (default).
|
217
|
-
#
|
218
|
-
# A string with a path can be supplied.
|
219
|
-
#
|
220
|
-
# If :fix_file: nice_http.log
|
221
|
-
#
|
222
|
-
# In case :file it will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log
|
223
|
-
#
|
224
|
-
# proxy_host
|
225
|
-
#
|
226
|
-
# proxy_port
|
227
|
-
# @example
|
228
|
-
# http2 = NiceHttp.new( host: "reqres.in", port: 443, ssl: true )
|
229
|
-
# @example
|
230
|
-
# my_server = {host: "example.com",
|
231
|
-
# port: 80,
|
232
|
-
# headers: {"api-key": "zdDDdjkck"}
|
233
|
-
# }
|
234
|
-
# http3 = NiceHttp.new my_server
|
235
|
-
######################################################
|
236
|
-
def initialize(args = {})
|
237
|
-
require "net/http"
|
238
|
-
require "net/https"
|
239
|
-
@host = self.class.host
|
240
|
-
@port = self.class.port
|
241
|
-
@prepath = ""
|
242
|
-
@ssl = self.class.ssl
|
243
|
-
@headers = self.class.headers.dup
|
244
|
-
@values_for = self.class.values_for.dup
|
245
|
-
@debug = self.class.debug
|
246
|
-
@log = self.class.log
|
247
|
-
@proxy_host = self.class.proxy_host
|
248
|
-
@proxy_port = self.class.proxy_port
|
249
|
-
@use_mocks = self.class.use_mocks
|
250
|
-
@auto_redirect = false #set it up at the end of initialize
|
251
|
-
auto_redirect = self.class.auto_redirect
|
252
|
-
@num_redirects = 0
|
253
|
-
@create_stats = self.class.create_stats
|
254
|
-
|
255
|
-
#todo: set only the cookies for the current domain
|
256
|
-
#key: path, value: hash with key is the name of the cookie and value the value
|
257
|
-
# we set the default value for non existing keys to empty Hash {} so in case of merge there is no problem
|
258
|
-
@cookies = Hash.new { |h, k| h[k] = {} }
|
259
|
-
|
260
|
-
if args.is_a?(String)
|
261
|
-
uri = URI.parse(args)
|
262
|
-
@host = uri.host unless uri.host.nil?
|
263
|
-
@port = uri.port unless uri.port.nil?
|
264
|
-
@ssl = true if !uri.scheme.nil? && (uri.scheme == "https")
|
265
|
-
@prepath = uri.path unless uri.path == "/"
|
266
|
-
elsif args.is_a?(Hash) && !args.keys.empty?
|
267
|
-
@host = args[:host] if args.keys.include?(:host)
|
268
|
-
@port = args[:port] if args.keys.include?(:port)
|
269
|
-
@ssl = args[:ssl] if args.keys.include?(:ssl)
|
270
|
-
@headers = args[:headers].dup if args.keys.include?(:headers)
|
271
|
-
@values_for = args[:values_for].dup if args.keys.include?(:values_for)
|
272
|
-
@debug = args[:debug] if args.keys.include?(:debug)
|
273
|
-
@log = args[:log] if args.keys.include?(:log)
|
274
|
-
@proxy_host = args[:proxy_host] if args.keys.include?(:proxy_host)
|
275
|
-
@proxy_port = args[:proxy_port] if args.keys.include?(:proxy_port)
|
276
|
-
@use_mocks = args[:use_mocks] if args.keys.include?(:use_mocks)
|
277
|
-
auto_redirect = args[:auto_redirect] if args.keys.include?(:auto_redirect)
|
278
|
-
end
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
if @log.kind_of?(String)
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
if
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
@
|
356
|
-
|
357
|
-
@
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
#
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
self.class.connections.
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
end
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
end
|
407
|
-
|
408
|
-
@
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
1
|
+
require "logger"
|
2
|
+
require "nice_hash"
|
3
|
+
require_relative "nice_http/utils"
|
4
|
+
require_relative "nice_http/manage_request"
|
5
|
+
require_relative "nice_http/manage_response"
|
6
|
+
require_relative "nice_http/http_methods"
|
7
|
+
|
8
|
+
######################################################
|
9
|
+
# Attributes you can access using NiceHttp.the_attribute:
|
10
|
+
# :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
|
11
|
+
# :last_request, :last_response, :request_id, :use_mocks, :connections,
|
12
|
+
# :active, :auto_redirect, :values_for, :create_stats, :stats
|
13
|
+
#
|
14
|
+
# @attr [String] host The host to be accessed
|
15
|
+
# @attr [Integer] port The port number
|
16
|
+
# @attr [Boolean] ssl If you use ssl or not
|
17
|
+
# @attr [Hash] headers Contains the headers you will be using on your connection
|
18
|
+
# @attr [Boolean] debug In case true shows all the details of the communication with the host
|
19
|
+
# @attr [String, Symbol] log :fix_file, :no, :screen, :file, "path and file name".
|
20
|
+
# :fix_file, will log the communication on nice_http.log. (default).
|
21
|
+
# :no, will not generate any logs.
|
22
|
+
# :screen, will print the logs on the screen.
|
23
|
+
# :file, will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log.
|
24
|
+
# :file_run, will generate a log file with the name where the object was created and extension .log, fex: myfile.rb.log
|
25
|
+
# String the path and file name where the logs will be stored.
|
26
|
+
# @attr [String] proxy_host the proxy host to be used
|
27
|
+
# @attr [Integer] proxy_port the proxy port to be used
|
28
|
+
# @attr [String] last_request The last request with all the content sent
|
29
|
+
# @attr [String] last_response Only in case :debug is true, the last response with all the content
|
30
|
+
# @attr [String] request_id If the response includes a requestId, will be stored here
|
31
|
+
# @attr [Boolean] use_mocks If true, in case the request hash includes a :mock_response key, it will be used as the response instead
|
32
|
+
# @attr [Array] connections It will include all the active connections (NiceHttp instances)
|
33
|
+
# @attr [Integer] active Number of active connections
|
34
|
+
# @attr [Boolean] auto_redirect If true, NiceHttp will take care of the auto redirections when required by the responses
|
35
|
+
# @attr [Hash] response Contains the full response hash
|
36
|
+
# @attr [Integer] num_redirects Number of consecutive redirections managed
|
37
|
+
# @attr [Hash] headers The updated headers of the communication
|
38
|
+
# @attr [Hash] cookies Cookies set. The key is the path (String) where cookies are set and the value a Hash with pairs of cookie keys and values, example:
|
39
|
+
# { '/' => { "cfid" => "d95adfas2550255", "amddom.settings" => "doom" } }
|
40
|
+
# @attr [Logger] logger An instance of the Logger class where logs will be stored. You can access on anytime to store specific data, for example:
|
41
|
+
# my_http.logger.info "add this to the log file"
|
42
|
+
# @see https://ruby-doc.org/stdlib-2.5.0/libdoc/logger/rdoc/Logger.html
|
43
|
+
# @attr [Hash] values_for The default values to set on the data in case not specified others
|
44
|
+
# @attr [Boolean] create_stats If true, NiceHttp will create stats of the http communication and store them on NiceHttp.stats hash
|
45
|
+
# @attr [Hash] stats It contains detailed stats of the http communication
|
46
|
+
######################################################
|
47
|
+
class NiceHttp
|
48
|
+
include NiceHttpManageRequest
|
49
|
+
include NiceHttpManageResponse
|
50
|
+
include NiceHttpHttpMethods
|
51
|
+
|
52
|
+
Error = Class.new StandardError
|
53
|
+
|
54
|
+
InfoMissing = Class.new Error do
|
55
|
+
attr_reader :attribute
|
56
|
+
|
57
|
+
def initialize(attribute, message = "")
|
58
|
+
@attribute = attribute
|
59
|
+
message += "It was not possible to create the http connection!!!\n"
|
60
|
+
message += "Wrong #{attribute}. "
|
61
|
+
message += "Remember to supply http:// or https:// in case you specify an url to create the http connection, for example:\n"
|
62
|
+
message += "http = NiceHttp.new('http://example.com')"
|
63
|
+
super message
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class << self
|
68
|
+
attr_accessor :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
|
69
|
+
:last_request, :last_response, :request_id, :use_mocks, :connections,
|
70
|
+
:active, :auto_redirect, :log_files, :values_for, :create_stats, :stats
|
71
|
+
end
|
72
|
+
|
73
|
+
at_exit do
|
74
|
+
if self.create_stats
|
75
|
+
require "yaml"
|
76
|
+
self.stats.keys.each do |key|
|
77
|
+
File.open("./nice_http_stats_#{key}.yaml", "w") { |file| file.write(self.stats[key].to_yaml) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
######################################################
|
83
|
+
# to reset to the original defaults
|
84
|
+
######################################################
|
85
|
+
def self.reset!
|
86
|
+
@host = nil
|
87
|
+
@port = 80
|
88
|
+
@ssl = false
|
89
|
+
@headers = {}
|
90
|
+
@values_for = {}
|
91
|
+
@debug = false
|
92
|
+
@log = :fix_file
|
93
|
+
@proxy_host = nil
|
94
|
+
@proxy_port = nil
|
95
|
+
@last_request = nil
|
96
|
+
@last_response = nil
|
97
|
+
@request_id = ""
|
98
|
+
@use_mocks = false
|
99
|
+
@connections = []
|
100
|
+
@active = 0
|
101
|
+
@auto_redirect = true
|
102
|
+
@log_files = {}
|
103
|
+
@create_stats = false
|
104
|
+
@stats = {
|
105
|
+
all: {
|
106
|
+
num_requests: 0,
|
107
|
+
time_elapsed: {
|
108
|
+
total: 0,
|
109
|
+
maximum: 0,
|
110
|
+
minimum: 100000,
|
111
|
+
average: 0,
|
112
|
+
},
|
113
|
+
method: {},
|
114
|
+
},
|
115
|
+
path: {},
|
116
|
+
name: {},
|
117
|
+
}
|
118
|
+
end
|
119
|
+
reset!
|
120
|
+
|
121
|
+
######################################################
|
122
|
+
# If inheriting from NiceHttp class
|
123
|
+
######################################################
|
124
|
+
def self.inherited(subclass)
|
125
|
+
subclass.reset!
|
126
|
+
end
|
127
|
+
|
128
|
+
attr_reader :host, :port, :ssl, :debug, :log, :proxy_host, :proxy_port, :response, :num_redirects
|
129
|
+
attr_accessor :headers, :cookies, :use_mocks, :auto_redirect, :logger, :values_for
|
130
|
+
|
131
|
+
######################################################
|
132
|
+
# Change the default values for NiceHttp supplying a Hash
|
133
|
+
#
|
134
|
+
# @param par [Hash] keys: :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port, :use_mocks, :auto_redirect, :values_for, :create_stats
|
135
|
+
######################################################
|
136
|
+
def self.defaults=(par = {})
|
137
|
+
@host = par[:host] if par.key?(:host)
|
138
|
+
@port = par[:port] if par.key?(:port)
|
139
|
+
@ssl = par[:ssl] if par.key?(:ssl)
|
140
|
+
@headers = par[:headers].dup if par.key?(:headers)
|
141
|
+
@values_for = par[:values_for].dup if par.key?(:values_for)
|
142
|
+
@debug = par[:debug] if par.key?(:debug)
|
143
|
+
@log = par[:log] if par.key?(:log)
|
144
|
+
@proxy_host = par[:proxy_host] if par.key?(:proxy_host)
|
145
|
+
@proxy_port = par[:proxy_port] if par.key?(:proxy_port)
|
146
|
+
@use_mocks = par[:use_mocks] if par.key?(:use_mocks)
|
147
|
+
@auto_redirect = par[:auto_redirect] if par.key?(:auto_redirect)
|
148
|
+
@create_stats = par[:create_stats] if par.key?(:create_stats)
|
149
|
+
end
|
150
|
+
|
151
|
+
######################################################
|
152
|
+
# To add specific stats
|
153
|
+
# The stats will be added to NiceHttp.stats[:specific]
|
154
|
+
#
|
155
|
+
# @param name [Symbol] name to group your specific stats
|
156
|
+
# @param state [Symbol] state of the name supplied to group your specific stats
|
157
|
+
# @param started [Time] when the process you want the stats started
|
158
|
+
# @param finished [Time] when the process you want the stats finished
|
159
|
+
#
|
160
|
+
# @example
|
161
|
+
# started = Time.now
|
162
|
+
# @http.send_request Requests::Customer.add_customer
|
163
|
+
# 30.times do
|
164
|
+
# resp = @http.get(Requests::Customer.get_customer)
|
165
|
+
# break if resp.code == 200
|
166
|
+
# sleep 0.5
|
167
|
+
# end
|
168
|
+
# NiceHttp.add_stats(:customer, :create, started, Time.now)
|
169
|
+
######################################################
|
170
|
+
def self.add_stats(name, state, started, finished)
|
171
|
+
self.stats[:specific] ||= {}
|
172
|
+
self.stats[:specific][name] ||= { num: 0, time_elapsed: { total: 0, maximum: 0, minimum: 1000, average: 0 } }
|
173
|
+
self.stats[:specific][name][:num] += 1
|
174
|
+
time_elapsed = self.stats[:specific][name][:time_elapsed]
|
175
|
+
time_elapsed[:total] += finished - started
|
176
|
+
time_elapsed[:maximum] = (finished - started) if time_elapsed[:maximum] < (finished - started)
|
177
|
+
time_elapsed[:minimum] = (finished - started) if time_elapsed[:minimum] > (finished - started)
|
178
|
+
time_elapsed[:average] = time_elapsed[:total] / self.stats[:specific][name][:num]
|
179
|
+
|
180
|
+
self.stats[:specific][name][state] ||= { num: 0, time_elapsed: { total: 0, maximum: 0, minimum: 1000, average: 0 } }
|
181
|
+
self.stats[:specific][name][state][:num] += 1
|
182
|
+
time_elapsed = self.stats[:specific][name][state][:time_elapsed]
|
183
|
+
time_elapsed[:total] += finished - started
|
184
|
+
time_elapsed[:maximum] = (finished - started) if time_elapsed[:maximum] < (finished - started)
|
185
|
+
time_elapsed[:minimum] = (finished - started) if time_elapsed[:minimum] > (finished - started)
|
186
|
+
time_elapsed[:average] = time_elapsed[:total] / self.stats[:specific][name][state][:num]
|
187
|
+
end
|
188
|
+
|
189
|
+
######################################################
|
190
|
+
# Creates a new http connection.
|
191
|
+
#
|
192
|
+
# @param args [] If no parameter supplied, by default will access how is setup on defaults
|
193
|
+
# @example
|
194
|
+
# http = NiceHttp.new()
|
195
|
+
# @param args [String]. The url to create the connection.
|
196
|
+
# @example
|
197
|
+
# http = NiceHttp.new("https://www.example.com")
|
198
|
+
# @example
|
199
|
+
# http = NiceHttp.new("example.com:8999")
|
200
|
+
# @example
|
201
|
+
# http = NiceHttp.new("localhost:8322")
|
202
|
+
# @param args [Hash] containing these possible keys:
|
203
|
+
#
|
204
|
+
# host -- example.com. (default blank screen)
|
205
|
+
#
|
206
|
+
# port -- port for the connection. 80 (default)
|
207
|
+
#
|
208
|
+
# ssl -- true, false (default)
|
209
|
+
#
|
210
|
+
# headers -- hash with the headers
|
211
|
+
#
|
212
|
+
# values_for -- hash with the values_for
|
213
|
+
#
|
214
|
+
# debug -- true, false (default)
|
215
|
+
#
|
216
|
+
# log -- :no, :screen, :file, :fix_file (default).
|
217
|
+
#
|
218
|
+
# A string with a path can be supplied.
|
219
|
+
#
|
220
|
+
# If :fix_file: nice_http.log
|
221
|
+
#
|
222
|
+
# In case :file it will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log
|
223
|
+
#
|
224
|
+
# proxy_host
|
225
|
+
#
|
226
|
+
# proxy_port
|
227
|
+
# @example
|
228
|
+
# http2 = NiceHttp.new( host: "reqres.in", port: 443, ssl: true )
|
229
|
+
# @example
|
230
|
+
# my_server = {host: "example.com",
|
231
|
+
# port: 80,
|
232
|
+
# headers: {"api-key": "zdDDdjkck"}
|
233
|
+
# }
|
234
|
+
# http3 = NiceHttp.new my_server
|
235
|
+
######################################################
|
236
|
+
def initialize(args = {})
|
237
|
+
require "net/http"
|
238
|
+
require "net/https"
|
239
|
+
@host = self.class.host
|
240
|
+
@port = self.class.port
|
241
|
+
@prepath = ""
|
242
|
+
@ssl = self.class.ssl
|
243
|
+
@headers = self.class.headers.dup
|
244
|
+
@values_for = self.class.values_for.dup
|
245
|
+
@debug = self.class.debug
|
246
|
+
@log = self.class.log
|
247
|
+
@proxy_host = self.class.proxy_host
|
248
|
+
@proxy_port = self.class.proxy_port
|
249
|
+
@use_mocks = self.class.use_mocks
|
250
|
+
@auto_redirect = false #set it up at the end of initialize
|
251
|
+
auto_redirect = self.class.auto_redirect
|
252
|
+
@num_redirects = 0
|
253
|
+
@create_stats = self.class.create_stats
|
254
|
+
|
255
|
+
#todo: set only the cookies for the current domain
|
256
|
+
#key: path, value: hash with key is the name of the cookie and value the value
|
257
|
+
# we set the default value for non existing keys to empty Hash {} so in case of merge there is no problem
|
258
|
+
@cookies = Hash.new { |h, k| h[k] = {} }
|
259
|
+
|
260
|
+
if args.is_a?(String)
|
261
|
+
uri = URI.parse(args)
|
262
|
+
@host = uri.host unless uri.host.nil?
|
263
|
+
@port = uri.port unless uri.port.nil?
|
264
|
+
@ssl = true if !uri.scheme.nil? && (uri.scheme == "https")
|
265
|
+
@prepath = uri.path unless uri.path == "/"
|
266
|
+
elsif args.is_a?(Hash) && !args.keys.empty?
|
267
|
+
@host = args[:host] if args.keys.include?(:host)
|
268
|
+
@port = args[:port] if args.keys.include?(:port)
|
269
|
+
@ssl = args[:ssl] if args.keys.include?(:ssl)
|
270
|
+
@headers = args[:headers].dup if args.keys.include?(:headers)
|
271
|
+
@values_for = args[:values_for].dup if args.keys.include?(:values_for)
|
272
|
+
@debug = args[:debug] if args.keys.include?(:debug)
|
273
|
+
@log = args[:log] if args.keys.include?(:log)
|
274
|
+
@proxy_host = args[:proxy_host] if args.keys.include?(:proxy_host)
|
275
|
+
@proxy_port = args[:proxy_port] if args.keys.include?(:proxy_port)
|
276
|
+
@use_mocks = args[:use_mocks] if args.keys.include?(:use_mocks)
|
277
|
+
auto_redirect = args[:auto_redirect] if args.keys.include?(:auto_redirect)
|
278
|
+
end
|
279
|
+
|
280
|
+
log_filename = ""
|
281
|
+
if @log.kind_of?(String) or @log == :fix_file or @log == :file or @log == :file_run
|
282
|
+
if @log.kind_of?(String)
|
283
|
+
log_filename = @log.dup
|
284
|
+
|
285
|
+
unless log_filename.start_with?(".")
|
286
|
+
if caller.first.start_with?(Dir.pwd)
|
287
|
+
folder = File.dirname(caller.first[/[^:]+/])
|
288
|
+
else
|
289
|
+
folder = File.dirname("#{Dir.pwd}/#{caller.first[/[^:]+/]}")
|
290
|
+
end
|
291
|
+
folder += "/" unless log_filename.start_with?("/")
|
292
|
+
log_filename = folder + log_filename
|
293
|
+
end
|
294
|
+
unless Dir.exist?(File.dirname(log_filename))
|
295
|
+
@logger = Logger.new nil
|
296
|
+
raise InfoMissing, :log, "Wrong directory specified for logs.\n"
|
297
|
+
end
|
298
|
+
elsif @log == :fix_file
|
299
|
+
log_filename = "nice_http.log"
|
300
|
+
elsif @log == :file
|
301
|
+
log_filename = "nice_http_#{Time.now.strftime("%Y-%m-%d-%H%M%S")}.log"
|
302
|
+
elsif @log == :file_run
|
303
|
+
log_filename = "#{caller.first[/[^:]+/]}.log"
|
304
|
+
end
|
305
|
+
if Thread.current.name.to_s != ""
|
306
|
+
log_filename.gsub!(/\.log$/, "_#{Thread.current.name}.log")
|
307
|
+
end
|
308
|
+
if self.class.log_files.key?(log_filename)
|
309
|
+
@logger = self.class.log_files[log_filename]
|
310
|
+
else
|
311
|
+
begin
|
312
|
+
f = File.new(log_filename, "w")
|
313
|
+
f.sync = true
|
314
|
+
@logger = Logger.new f
|
315
|
+
rescue Exception => stack
|
316
|
+
@logger = Logger.new nil
|
317
|
+
raise InfoMissing, :log
|
318
|
+
end
|
319
|
+
self.class.log_files[log_filename] = @logger
|
320
|
+
end
|
321
|
+
elsif @log == :screen
|
322
|
+
@logger = Logger.new STDOUT
|
323
|
+
elsif @log == :no
|
324
|
+
@logger = Logger.new nil
|
325
|
+
else
|
326
|
+
raise InfoMissing, :log
|
327
|
+
end
|
328
|
+
@logger.level = Logger::INFO
|
329
|
+
|
330
|
+
if @host.to_s != "" and (@host.start_with?("http:") or @host.start_with?("https:"))
|
331
|
+
uri = URI.parse(@host)
|
332
|
+
@host = uri.host unless uri.host.nil?
|
333
|
+
@port = uri.port unless uri.port.nil?
|
334
|
+
@ssl = true if !uri.scheme.nil? && (uri.scheme == "https")
|
335
|
+
@prepath = uri.path unless uri.path == "/"
|
336
|
+
end
|
337
|
+
|
338
|
+
raise InfoMissing, :port if @port.to_s == ""
|
339
|
+
raise InfoMissing, :host if @host.to_s == ""
|
340
|
+
raise InfoMissing, :ssl unless @ssl.is_a?(TrueClass) or @ssl.is_a?(FalseClass)
|
341
|
+
raise InfoMissing, :debug unless @debug.is_a?(TrueClass) or @debug.is_a?(FalseClass)
|
342
|
+
raise InfoMissing, :auto_redirect unless auto_redirect.is_a?(TrueClass) or auto_redirect.is_a?(FalseClass)
|
343
|
+
raise InfoMissing, :use_mocks unless @use_mocks.is_a?(TrueClass) or @use_mocks.is_a?(FalseClass)
|
344
|
+
raise InfoMissing, :headers unless @headers.is_a?(Hash)
|
345
|
+
raise InfoMissing, :values_for unless @values_for.is_a?(Hash)
|
346
|
+
|
347
|
+
begin
|
348
|
+
if !@proxy_host.nil? && !@proxy_port.nil?
|
349
|
+
@http = Net::HTTP::Proxy(@proxy_host, @proxy_port).new(@host, @port)
|
350
|
+
@http.use_ssl = @ssl
|
351
|
+
@http.set_debug_output $stderr if @debug
|
352
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
353
|
+
@http.start
|
354
|
+
else
|
355
|
+
@http = Net::HTTP.new(@host, @port)
|
356
|
+
@http.use_ssl = @ssl
|
357
|
+
@http.set_debug_output $stderr if @debug
|
358
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
359
|
+
@http.start
|
360
|
+
end
|
361
|
+
|
362
|
+
@message_server = "(#{self.object_id}):"
|
363
|
+
|
364
|
+
log_message = "(#{self.object_id}): Http connection created. host:#{@host}, port:#{@port}, ssl:#{@ssl}, mode:#{@mode}, proxy_host: #{@proxy_host.to_s()}, proxy_port: #{@proxy_port.to_s()} "
|
365
|
+
|
366
|
+
@logger.info(log_message)
|
367
|
+
@message_server += " Http connection: "
|
368
|
+
if @ssl
|
369
|
+
@message_server += "https://"
|
370
|
+
else
|
371
|
+
@message_server += "http://"
|
372
|
+
end
|
373
|
+
@message_server += "#{@host}:#{@port}"
|
374
|
+
if @proxy_host.to_s != ""
|
375
|
+
@message_server += " proxy:#{@proxy_host}:#{@proxy_port}"
|
376
|
+
end
|
377
|
+
@auto_redirect = auto_redirect
|
378
|
+
# for the case we have headers following nice_hash implementation
|
379
|
+
@headers = @headers.generate
|
380
|
+
|
381
|
+
self.class.active += 1
|
382
|
+
self.class.connections.push(self)
|
383
|
+
rescue Exception => stack
|
384
|
+
puts stack
|
385
|
+
@logger.fatal stack
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
######################################################
|
390
|
+
# Close HTTP connection
|
391
|
+
######################################################
|
392
|
+
def close
|
393
|
+
begin
|
394
|
+
pos = 0
|
395
|
+
found = false
|
396
|
+
self.class.connections.each { |conn|
|
397
|
+
if conn.object_id == self.object_id
|
398
|
+
found = true
|
399
|
+
break
|
400
|
+
else
|
401
|
+
pos += 1
|
402
|
+
end
|
403
|
+
}
|
404
|
+
if found
|
405
|
+
self.class.connections.delete_at(pos)
|
406
|
+
end
|
407
|
+
|
408
|
+
unless @closed
|
409
|
+
if !@http.nil?
|
410
|
+
@http.finish()
|
411
|
+
@http = nil
|
412
|
+
@logger.info "the HTTP connection was closed: #{@message_server}"
|
413
|
+
else
|
414
|
+
@http = nil
|
415
|
+
@logger.fatal "It was not possible to close the HTTP connection: #{@message_server}"
|
416
|
+
end
|
417
|
+
@closed = true
|
418
|
+
else
|
419
|
+
@logger.warn "It was not possible to close the HTTP connection, already closed: #{@message_server}"
|
420
|
+
end
|
421
|
+
rescue Exception => stack
|
422
|
+
@logger.fatal stack
|
423
|
+
end
|
424
|
+
self.class.active -= 1
|
425
|
+
end
|
426
|
+
|
427
|
+
private :manage_request, :manage_response
|
428
|
+
end
|