nice_http 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nice_http.rb +1098 -1098
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 231751412f91ccd16d4ac7d701b3385afacfa4805bab102b50e2cff2cb572c1a
4
- data.tar.gz: 1b69935d11c7298b22b4040d556467323b6fbb2d537eaf124c6a1acce8a510a8
3
+ metadata.gz: d94d6ba065b13e963583cfbed6501a6e458fad1106e7b833a87a468a7ff65941
4
+ data.tar.gz: 59008a785b4e774beb5e3ecfb80e79ddd8cb072a79519e1cf0589039246b4047
5
5
  SHA512:
6
- metadata.gz: 38460eae904950f28d135ab06d294ce2c905d49cf373e4defc30a34303826c09720756807a46bfd551ca69a79f834c1acc0bd92e6fe7946bcaaa44ff5354e0e8
7
- data.tar.gz: 7790e3affbae979ee63e79a712fb1d0f645733376bf98eb9253890c23c9fb57c6ed8913b3e43e62a56483e4d4e8bd6993cdfdcb29eba52fa524bce057123e794
6
+ metadata.gz: 48494568e34e0c51274520b0f4917d2c7c6d196efb9328816f39c4fb41eb30bc2c63000e040b855c31111e49b82433fbd0885eb8848c481763b442f2b45f3dc2
7
+ data.tar.gz: d9862a9a07645239443d5cefbbf8a28e61d4f9611757a529d06fccf91356ee76500a0512fa03f38dc915e206de4f0eedc6f00c89fa041888a3eec22e77b311fa
@@ -1,1098 +1,1098 @@
1
- require 'logger'
2
- require 'nice_hash'
3
- require 'nice_http_utils'
4
-
5
- class NiceHttp
6
- class << self
7
- attr_accessor :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
8
- :last_request, :last_response, :request_id, :use_mocks, :connections,
9
- :active, :auto_redirect
10
- end
11
- @host = nil
12
- @port = 80
13
- @ssl = false
14
- @headers = {}
15
- @debug = false
16
- @log = :fix_file
17
- @proxy_host = nil
18
- @proxy_port = nil
19
- @last_request=nil
20
- @last_response=nil
21
- @request_id=""
22
- @use_mocks = false
23
- @connections = []
24
- @active=0
25
- @auto_redirect = true
26
-
27
- attr_reader :host, :port, :ssl, :debug, :log, :proxy_host, :proxy_port, :response, :num_redirects
28
- attr_accessor :headers, :cookies, :use_mocks, :auto_redirect, :logger
29
-
30
- def self.defaults=(par = {})
31
- @host = par[:host] if par.key?(:host)
32
- @port = par[:port] if par.key?(:port)
33
- @ssl = par[:ssl] if par.key?(:ssl)
34
- @headers = par[:headers] if par.key?(:headers)
35
- @debug = par[:debug] if par.key?(:debug)
36
- @log = par[:log] if par.key?(:log)
37
- @proxy_host = par[:proxy_host] if par.key?(:proxy_host)
38
- @proxy_port = par[:proxy_port] if par.key?(:proxy_port)
39
- @proxy_port = par[:use_mocks] if par.key?(:use_mocks)
40
- @auto_redirect = par[:auto_redirect] if par.key?(:auto_redirect)
41
- end
42
-
43
- ######################################################
44
- # input:
45
- # no parameters:
46
- # By default will access how is setup on defaults
47
- # one parameter:
48
- # String
49
- # "https://www.example.com"
50
- # "example.com:8999"
51
- # "localhost:8322"
52
- # Hash containing these possible keys
53
- # host -- example.com. (default blank screen)
54
- # port -- port for the connection. 80 (default)
55
- # ssl -- true, false (default)
56
- # headers -- hash with the header key:values
57
- # debug -- true, false (default)
58
- # log -- :no, :screen, :file, :fix_file (default).
59
- # A string with a path can be supplied.
60
- # If :fix_file: nice_http.log
61
- # In case :file it will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log
62
- # proxy_host
63
- # proxy_port
64
- ######################################################
65
- def initialize(args = {})
66
- require 'net/http'
67
- require 'net/https'
68
- @host = NiceHttp.host
69
- @port = NiceHttp.port
70
- @ssl = NiceHttp.ssl
71
- @headers = NiceHttp.headers
72
- @debug = NiceHttp.debug
73
- @log = NiceHttp.log
74
- @proxy_host = NiceHttp.proxy_host
75
- @proxy_port = NiceHttp.proxy_port
76
- @use_mocks = NiceHttp.use_mocks
77
- @auto_redirect=false #set it up at the end of initialize
78
- auto_redirect = NiceHttp.auto_redirect
79
- @num_redirects=0
80
-
81
- #todo: set only the cookies for the current domain
82
- #key: path, value: hash with key is the name of the cookie and value the value
83
- # we set the default value for non existing keys to empty Hash {} so in case of merge there is no problem
84
- @cookies=Hash.new {|h, k| h[k] = {}}
85
-
86
- begin
87
- if args.is_a?(String)
88
- uri = URI.parse(args)
89
- @host = uri.host unless uri.host.nil?
90
- @port = uri.port unless uri.port.nil?
91
- @ssl = true if !uri.scheme.nil? && (uri.scheme == 'https')
92
- elsif args.is_a?(Hash) && !args.keys.empty?
93
- @host = args[:host] if args.keys.include?(:host)
94
- @port = args[:port] if args.keys.include?(:port)
95
- @ssl = args[:ssl] if args.keys.include?(:ssl)
96
- @headers = args[:headers] if args.keys.include?(:headers)
97
- @debug = args[:debug] if args.keys.include?(:debug)
98
- @log = args[:log] if args.keys.include?(:log)
99
- @proxy_host = args[:proxy_host] if args.keys.include?(:proxy_host)
100
- @proxy_port = args[:proxy_port] if args.keys.include?(:proxy_port)
101
- @use_mocks = args[:use_mocks] if args.keys.include?(:use_mocks)
102
- @auto_redirect = args[:auto_redirect] if args.keys.include?(:auto_redirect)
103
- end
104
-
105
- if @host.to_s!="" and (@host.include?("http:") or @host.include?("https:"))
106
- uri = URI.parse(@host)
107
- @host = uri.host unless uri.host.nil?
108
- @port = uri.port unless uri.port.nil?
109
- @ssl = true if !uri.scheme.nil? && (uri.scheme == 'https')
110
- end
111
-
112
- if @host.nil? or @host.to_s=="" or @port.nil? or @port.to_s==""
113
- message = "It was not possible to create the http connection!!!\n"
114
- message += "Wrong host or port, remember to supply http:// or https:// in case you specify an url to create the http connection, for example:\n"
115
- message += "http = NiceHttp.new('http://example.com')"
116
- raise message
117
- end
118
-
119
- if !@proxy_host.nil? && !@proxy_port.nil?
120
- @http = Net::HTTP::Proxy(@proxy_host, @proxy_port).new(@host, @port)
121
- @http.use_ssl = @ssl
122
- @http.set_debug_output $stderr if @debug
123
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
124
- @http.start
125
- else
126
- @http = Net::HTTP.new(@host, @port)
127
- @http.use_ssl = @ssl
128
- @http.set_debug_output $stderr if @debug
129
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
130
- @http.start
131
- end
132
-
133
- if @log.kind_of?(String)
134
- @logger = Logger.new File.new(@log, "w")
135
- elsif @log==:fix_file
136
- @logger = Logger.new File.new("nice_http.log", "w")
137
- elsif @log==:file
138
- @logger = Logger.new File.new("nice_http_#{Time.now.strftime('%Y-%m-%d-%H%M%S')}.log", 'w')
139
- elsif @log==:screen
140
- @logger = Logger.new STDOUT
141
- elsif @log==:no
142
- @logger = Logger.new nil
143
- end
144
- @logger.level = Logger::INFO
145
-
146
- @message_server="(#{self.object_id}):"
147
-
148
- 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()} "
149
-
150
- @logger.info(log_message)
151
- @message_server+=" Http connection: "
152
- if @ssl then
153
- @message_server+="https://"
154
- else
155
- @message_server+="http://"
156
- end
157
- @message_server+="#{@host}:#{@port}"
158
- if @proxy_host.to_s!="" then
159
- @message_server+=" proxy:#{@proxy_host}:#{@proxy_port}"
160
- end
161
- @auto_redirect = auto_redirect
162
- rescue Exception => stack
163
- if @logger.nil?
164
- puts stack
165
- @logger = Logger.new nil
166
- else
167
- @logger.fatal stack
168
- end
169
- end
170
-
171
- NiceHttp.active+=1
172
- NiceHttp.connections.push(self)
173
-
174
- end
175
-
176
- ######################################################
177
- # Get data from path
178
- # input:
179
- # 1 argument
180
- # Hash containing at least key :path
181
- # 1 argument
182
- # path (string)
183
- # output:
184
- # response -> Hash including at least the symbol keys:
185
- # :data = the response data body
186
- # :message = plain text response
187
- # :code = code response (200=ok,500=wrong...)
188
- # *All keys in response are lowercase
189
- # data, message and code can also be accessed as attributes like .message .code .data, for example:
190
- # resp=@http.get(Requests::Customer.get_profile)
191
- # assert resp.code==200
192
- ######################################################
193
- def get(arg)
194
- begin
195
- path, data, headers_t=manage_request(arg)
196
- @start_time = Time.now if @start_time.nil?
197
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
198
- data=""
199
- if arg[:mock_response].keys.include?(:data) then
200
- data=arg[:mock_response][:data]
201
- if data.kind_of?(Hash) #to json
202
- begin
203
- require 'json'
204
- data=data.to_json
205
- rescue
206
- @logger.fatal "There was a problem converting to json: #{data}"
207
- end
208
- end
209
- end
210
- @logger.warn "Pay attention!!! This is a mock response:"
211
- @start_time_net = Time.now if @start_time_net.nil?
212
- manage_response(arg[:mock_response], data.to_s)
213
- return @response
214
- end
215
- begin
216
- if path.start_with?("http:") or path.start_with?("https:") then #server included on path problably because of a redirection to a different server
217
- require 'uri'
218
- uri = URI.parse(path)
219
- ssl=false
220
- ssl=true if path.include?("https:")
221
-
222
-
223
- server="http://"
224
- server="https://" if path.include?("https:")
225
- if uri.port!=443 then
226
- server+="#{uri.host}:#{uri.port}"
227
- else
228
- server+="#{uri.host}"
229
- end
230
-
231
- http_redir=nil
232
- NiceHttp.connections.each {|conn|
233
- if conn.host == uri.host and conn.port==uri.port then
234
- http_redir=conn
235
- break
236
- end
237
- }
238
-
239
- if !http_redir.nil?
240
- path, data, headers_t=manage_request(arg)
241
- http_redir.cookies.merge!(@cookies)
242
- http_redir.headers.merge!(headers_t)
243
- resp=http_redir.get(path.gsub(server, "")) #todo: remove only the server at the begining in case in query is the server it will be replaced when it should not be
244
- @response=http_redir.response
245
- else
246
- @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."
247
- end
248
-
249
- else
250
- @start_time_net = Time.now if @start_time_net.nil?
251
- resp=@http.get(path, headers_t)
252
- data=resp.body
253
- manage_response(resp, data)
254
- end
255
- rescue Exception => stack
256
- @logger.warn stack
257
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
258
- @http.finish()
259
- @http.start()
260
- @start_time_net = Time.now if @start_time_net.nil?
261
- resp=@http.get(path)
262
- data=resp.body
263
- manage_response(resp, data)
264
- end
265
- if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
266
- if @num_redirects<=30 then
267
- @num_redirects+=1
268
- current_server="http"
269
- current_server+="s" if @ssl==true
270
- current_server+="://#{@host}"
271
- location=@response[:location].gsub(current_server, "")
272
- @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
273
- get(location)
274
- else
275
- @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"
276
- @num_redirects=0
277
- end
278
- else
279
- @num_redirects=0
280
- end
281
- return @response
282
- rescue Exception => stack
283
- @logger.fatal stack
284
- return :error
285
- end
286
- end
287
-
288
- ######################################################
289
- # Post data to path
290
- # input:
291
- # 1 argument
292
- # Hash containing at least keys :data, :path
293
- # 3 arguments
294
- # path (string)
295
- # data (json data for example)
296
- # additional_headers (Hash key=>value)
297
- # output:
298
- # response -> Hash including at least the symbol keys:
299
- # :data = the response data body
300
- # :message = plain text response
301
- # :code = code response (200=ok,500=wrong...)
302
- # *All keys in response are lowercase
303
- # data, message and code can also be accessed as attributes like .message .code .data, for example:
304
- # resp=@http.post(Requests::Customer.update_customer)
305
- # assert resp.code==201
306
- ######################################################
307
- def post(*arguments)
308
- begin
309
- path, data, headers_t=manage_request(*arguments)
310
- @start_time = Time.now if @start_time.nil?
311
- if arguments.size>0 and arguments[0].kind_of?(Hash) then
312
- arg=arguments[0]
313
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
314
- data=""
315
- if arg[:mock_response].keys.include?(:data) then
316
- data=arg[:mock_response][:data]
317
- if data.kind_of?(Hash) #to json
318
- begin
319
- require 'json'
320
- data=data.to_json
321
- rescue
322
- @logger.fatal "There was a problem converting to json: #{data}"
323
- end
324
- end
325
- end
326
- @logger.warn "Pay attention!!! This is a mock response:"
327
- @start_time_net = Time.now if @start_time_net.nil?
328
- manage_response(arg[:mock_response], data.to_s)
329
- return @response
330
- end
331
- end
332
-
333
- begin
334
- @start_time_net = Time.now if @start_time_net.nil?
335
- if headers_t["Content-Type"] == "multipart/form-data" then
336
- require 'net/http/post/multipart'
337
- headers_t.each {|key, value|
338
- arguments[0][:data].add_field(key, value) #add to Headers
339
- }
340
- resp=@http.request(arguments[0][:data])
341
- else
342
- resp=@http.post(path, data, headers_t)
343
- data=resp.body
344
- end
345
- rescue Exception => stack
346
- @logger.warn stack
347
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
348
- @http.finish()
349
- @http.start()
350
- @start_time_net = Time.now if @start_time_net.nil?
351
- resp, data=@http.post(path, data, headers_t)
352
- end
353
- manage_response(resp, data)
354
- if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
355
- if @num_redirects<=30 then
356
- @num_redirects+=1
357
- current_server="http"
358
- current_server+="s" if @ssl==true
359
- current_server+="://#{@host}"
360
- location=@response[:location].gsub(current_server, "")
361
- @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
362
- get(location)
363
- else
364
- @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"
365
- @num_redirects=0
366
- end
367
- else
368
- @num_redirects=0
369
- end
370
- return @response
371
- rescue Exception => stack
372
- @logger.warn stack
373
- return :error
374
- end
375
-
376
- end
377
-
378
-
379
- ######################################################
380
- # Put data to path
381
- # input:
382
- # 1 argument
383
- # Hash containing at least keys :data, :path
384
- # 3 arguments
385
- # path (string)
386
- # data (json data for example)
387
- # additional_headers (Hash key=>value)
388
- # output:
389
- # response -> Hash including at least the symbol keys:
390
- # :data = the response data body
391
- # :message = plain text response
392
- # :code = code response (200=ok,500=wrong...)
393
- # *All keys in response are lowercase
394
- # data, message and code can also be accessed as attributes like .message .code .data, for example:
395
- # resp=@http.put(Requests::Customer.remove_phone)
396
- # assert resp.code==200
397
- ######################################################
398
- def put(*arguments)
399
- begin
400
- path, data, headers_t=manage_request(*arguments)
401
- @start_time = Time.now if @start_time.nil?
402
- if arguments.size>0 and arguments[0].kind_of?(Hash) then
403
- arg=arguments[0]
404
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
405
- data=""
406
- if arg[:mock_response].keys.include?(:data) then
407
- data=arg[:mock_response][:data]
408
- if data.kind_of?(Hash) #to json
409
- begin
410
- require 'json'
411
- data=data.to_json
412
- rescue
413
- @logger.fatal "There was a problem converting to json: #{data}"
414
- end
415
- end
416
- end
417
- @logger.warn "Pay attention!!! This is a mock response:"
418
- @start_time_net = Time.now if @start_time_net.nil?
419
- manage_response(arg[:mock_response], data.to_s)
420
- return @response
421
- end
422
- end
423
-
424
- begin
425
- @start_time_net = Time.now if @start_time_net.nil?
426
- resp=@http.send_request("PUT", path, data, headers_t)
427
- data=resp.body
428
- rescue Exception => stack
429
- @logger.warn stack
430
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
431
- @http.finish()
432
- @http.start()
433
- @start_time_net = Time.now if @start_time_net.nil?
434
- resp, data=@http.send_request("PUT", path, data, headers_t)
435
- end
436
- manage_response(resp, data)
437
-
438
- return @response
439
- rescue Exception => stack
440
- @logger.fatal stack, self
441
- return :error
442
- end
443
-
444
- end
445
-
446
-
447
- ######################################################
448
- # Patch data to path
449
- # input:
450
- # 1 argument
451
- # Hash containing at least keys :data, :path
452
- # 3 arguments
453
- # path (string)
454
- # data (json data for example)
455
- # additional_headers (Hash key=>value)
456
- # output:
457
- # response -> Hash including at least the symbol keys:
458
- # :data = the response data body
459
- # :message = plain text response
460
- # :code = code response (200=ok,500=wrong...)
461
- # *All keys in response are lowercase
462
- # data, message and code can also be accessed as attributes like .message .code .data, for example:
463
- # resp=@http.patch(Requests::Customer.unrelease_account)
464
- # assert resp.code==200
465
- ######################################################
466
- def patch(*arguments)
467
- begin
468
- path, data, headers_t=manage_request(*arguments)
469
- @start_time = Time.now if @start_time.nil?
470
- if arguments.size>0 and arguments[0].kind_of?(Hash) then
471
- arg=arguments[0]
472
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
473
- data=""
474
- if arg[:mock_response].keys.include?(:data) then
475
- data=arg[:mock_response][:data]
476
- if data.kind_of?(Hash) #to json
477
- begin
478
- require 'json'
479
- data=data.to_json
480
- rescue
481
- @logger.fatal "There was a problem converting to json: #{data}"
482
- end
483
- end
484
- end
485
- @logger.warn "Pay attention!!! This is a mock response:"
486
- @start_time_net = Time.now if @start_time_net.nil?
487
- manage_response(arg[:mock_response], data.to_s)
488
- return @response
489
- end
490
- end
491
-
492
- begin
493
- @start_time_net = Time.now if @start_time_net.nil?
494
- resp=@http.patch(path, data, headers_t)
495
- data=resp.body
496
- rescue Exception => stack
497
- @logger.warn stack
498
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
499
- @http.finish()
500
- @http.start()
501
- @start_time_net = Time.now if @start_time_net.nil?
502
- resp, data=@http.patch(path, data, headers_t)
503
- end
504
- manage_response(resp, data)
505
- if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
506
- if @num_redirects<=30 then
507
- @num_redirects+=1
508
- current_server="http"
509
- current_server+="s" if @ssl==true
510
- current_server+="://#{@host}"
511
- location=@response[:location].gsub(current_server, "")
512
- @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
513
- get(location)
514
- else
515
- @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"
516
- @num_redirects=0
517
- end
518
- else
519
- @num_redirects=0
520
- end
521
- return @response
522
- rescue Exception => stack
523
- @logger.fatal stack
524
- return :error
525
- end
526
-
527
- end
528
-
529
-
530
- ######################################################
531
- # Delete an existing resource
532
- # input:
533
- # 1 argument
534
- # Hash containing at least key :path
535
- # 1 argument
536
- # String giving the path
537
- # output:
538
- # response -> Hash including at least the symbol keys:
539
- # :data = the response data body
540
- # :message = plain text response
541
- # :code = code response (200=ok,500=wrong...)
542
- # *All keys in response are lowercase
543
- # data, message and code can also be accessed as attributes like .message .code .data, for example:
544
- # resp=@http.delete(Requests::Customer.remove_session)
545
- # assert resp.code==204
546
- ######################################################
547
- def delete(argument)
548
- begin
549
- if argument.kind_of?(String) then
550
- argument={:path => argument}
551
- end
552
- path, data, headers_t=manage_request(argument)
553
- @start_time = Time.now if @start_time.nil?
554
- if argument.kind_of?(Hash) then
555
- arg=argument
556
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
557
- data=""
558
- if arg[:mock_response].keys.include?(:data) then
559
- data=arg[:mock_response][:data]
560
- if data.kind_of?(Hash) #to json
561
- begin
562
- require 'json'
563
- data=data.to_json
564
- rescue
565
- @logger.fatal "There was a problem converting to json: #{data}"
566
- end
567
- end
568
- end
569
- @logger.warn "Pay attention!!! This is a mock response:"
570
- @start_time_net = Time.now if @start_time_net.nil?
571
- manage_response(arg[:mock_response], data.to_s)
572
- return @response
573
- end
574
- end
575
-
576
- begin
577
- @start_time_net = Time.now if @start_time_net.nil?
578
- resp=@http.delete(path, headers_t)
579
- data=resp.body
580
- rescue Exception => stack
581
- @logger.warn stack
582
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
583
- @http.finish()
584
- @http.start()
585
- @start_time_net = Time.now if @start_time_net.nil?
586
- resp, data=@http.delete(path)
587
- end
588
- manage_response(resp, data)
589
-
590
- return @response
591
- rescue Exception => stack
592
- @logger.fatal stack
593
- return :error
594
- end
595
-
596
- end
597
-
598
- ######################################################
599
- # Implementation of the http HEAD method.
600
- # Asks for the response identical to the one that would correspond to a GET request, but without the response body.
601
- # This is useful for retrieving meta-information written in response headers, without having to transport the entire content.
602
- # input:
603
- # 1 argument
604
- # Hash containing at least key :path
605
- # 1 argument
606
- # String giving the path
607
- # output:
608
- # response -> Hash including the symbol keys:
609
- # :message = plain text response
610
- # :code = code response (200=ok,500=wrong...)
611
- # *All keys in response are lowercase
612
- ######################################################
613
- def head(argument)
614
- begin
615
- if argument.kind_of?(String) then
616
- argument={:path => argument}
617
- end
618
- path, data, headers_t=manage_request(argument)
619
- @start_time = Time.now if @start_time.nil?
620
- if argument.kind_of?(Hash) then
621
- arg=argument
622
- if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
623
- data=""
624
- if arg[:mock_response].keys.include?(:data) then
625
- data=arg[:mock_response][:data]
626
- if data.kind_of?(Hash) #to json
627
- begin
628
- require 'json'
629
- data=data.to_json
630
- rescue
631
- @logger.fatal "There was a problem converting to json: #{data}"
632
- end
633
- end
634
- end
635
- @logger.warn "Pay attention!!! This is a mock response:"
636
- @start_time_net = Time.now if @start_time_net.nil?
637
- manage_response(arg[:mock_response], data.to_s)
638
- return @response
639
- end
640
- end
641
-
642
- begin
643
- @start_time_net = Time.now if @start_time_net.nil?
644
- resp=@http.head(path, headers_t)
645
- data=resp.body
646
- rescue Exception => stack
647
- @logger.warn stack
648
- @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
649
- @http.finish()
650
- @http.start()
651
- @start_time_net = Time.now if @start_time_net.nil?
652
- resp, data=@http.head(path)
653
- end
654
- manage_response(resp, data)
655
- return @response
656
- rescue Exception => stack
657
- @logger.fatal stack
658
- return :error
659
- end
660
- end
661
-
662
-
663
- ######################################################
664
- # Close HTTP connection
665
- ######################################################
666
- def close
667
- begin
668
- pos=0
669
- found=false
670
- NiceHttp.connections.each {|conn|
671
- if conn.object_id == self.object_id then
672
- found=true
673
- break
674
- end
675
- pos+=1
676
- }
677
- if found
678
- NiceHttp.connections.delete_at(pos)
679
- end
680
-
681
- unless @closed
682
- if !@http.nil? then
683
- @http.finish()
684
- @http=nil
685
- @logger.info "the HTTP connection was closed: #{@message_server}"
686
- else
687
- @http=nil
688
- @logger.fatal "It was not possible to close the HTTP connection: #{@message_server}"
689
- end
690
- @closed=true
691
- else
692
- @logger.warn "It was not possible to close the HTTP connection, already closed: #{@message_server}"
693
- end
694
- rescue Exception => stack
695
- @logger.fatal stack
696
- end
697
- NiceHttp.active-=1
698
- end
699
-
700
-
701
- ######################################################
702
- # private method to manage Request
703
- # input:
704
- # 3 args: path, data, headers
705
- # 1 arg: Hash containg at least keys :path and :data
706
- # output:
707
- # path, data, headers
708
- ######################################################
709
- def manage_request(*arguments)
710
- require 'json'
711
- begin
712
- content_type_included=false
713
- path=""
714
- data=""
715
-
716
- @response=Hash.new()
717
- headers_t=@headers.dup()
718
- cookies_to_set_str=""
719
- if arguments.size==3 then
720
- path=arguments[0]
721
- elsif arguments.size==1 and arguments[0].kind_of?(Hash) then
722
- path=arguments[0][:path]
723
- elsif arguments.size==1 and arguments[0].kind_of?(String) then
724
- path=arguments[0].to_s()
725
- end
726
- @cookies.each {|cookie_path, cookies_hash|
727
- cookie_path="" if cookie_path=="/"
728
- path_to_check=path
729
- if path=="/" or path[-1]!="/" then
730
- path_to_check+="/"
731
- end
732
- if path_to_check.scan(/^#{cookie_path}\//).size>0 then
733
- cookies_hash.each {|key, value|
734
- cookies_to_set_str+="#{key}=#{value}; "
735
- }
736
- end
737
- }
738
- headers_t["Cookie"]=cookies_to_set_str
739
-
740
- method_s=caller[0].to_s().scan(/:in `(.*)'/).join
741
-
742
- if arguments.size==3 then
743
- data=arguments[1]
744
- if arguments[2].kind_of?(Hash) then
745
- headers_t.merge!(arguments[2])
746
- end
747
- elsif arguments.size==1 and arguments[0].kind_of?(Hash) then
748
- if arguments[0][:data].nil? then
749
- if arguments[0].keys.include?(:data) then
750
- data=""
751
- elsif arguments[0].keys.include?(:data_examples) and
752
- arguments[0][:data_examples].kind_of?(Array) then
753
- data=arguments[0][:data_examples][0] #the first example by default
754
- else
755
- data=""
756
- end
757
-
758
- else
759
- data=arguments[0][:data]
760
- end
761
- if arguments[0].include?(:headers) then
762
- headers_t.merge!(arguments[0][:headers])
763
- end
764
-
765
- if headers_t["Content-Type"].to_s()=="" and headers_t["content-type"].to_s()=="" and
766
- headers_t[:"content-type"].to_s()=="" and headers_t[:"Content-Type"].to_s()=="" then
767
- content_type_included=false
768
- elsif headers_t["content-type"].to_s()!="" then
769
- content_type_included=true
770
- headers_t["Content-Type"]=headers_t["content-type"]
771
- elsif headers_t[:"content-type"].to_s()!="" then
772
- content_type_included=true
773
- headers_t["Content-Type"]=headers_t[:"content-type"]
774
- headers_t.delete(:"content-type")
775
- elsif headers_t[:"Content-Type"].to_s()!="" then
776
- content_type_included=true
777
- headers_t["Content-Type"]=headers_t[:"Content-Type"]
778
- headers_t.delete(:"Content-Type")
779
- elsif headers_t["Content-Type"].to_s()!="" then
780
- content_type_included=true
781
- end
782
-
783
- if !content_type_included and data.kind_of?(Hash)
784
- headers_t['Content-Type'] = 'application/json'
785
- content_type_included=true
786
- end
787
-
788
- if content_type_included and (!headers_t["Content-Type"][/text\/xml/].nil? or
789
- !headers_t["Content-Type"]["application/soap+xml"].nil? or
790
- !headers_t["Content-Type"][/application\/jxml/].nil?) then
791
- if arguments[0].include?(:values) then
792
- arguments[0][:values].each {|key, value|
793
- data=NiceHttpUtils.set_value_xml_tag(key.to_s(), data, value.to_s(), true)
794
- }
795
- end
796
- elsif content_type_included and !headers_t["Content-Type"][/application\/json/].nil? and data.to_s()!="" then
797
- require 'json'
798
- if data.kind_of?(String) then
799
- if arguments[0].include?(:values) then
800
- arguments[0][:values].each {|key, value|
801
- data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *")(.*)(" *, *$)/, '\1' + value+ '\4') # "key":"value", or key:"value",
802
- data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *")(.*)(" *$)/, '\1' + value+ '\4') # "key":"value" or key:"value"
803
- data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *[^"])([^"].*)([^"] *, *$)/, '\1' + value+ '\4') # "key":456, or key:456,
804
- data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *[^"])([^"].*)([^"] * *$)/, '\1' + value+ '\4') # "key":456 or key:456
805
- }
806
- end
807
- elsif data.kind_of?(Hash) then
808
- data_n=Hash.new()
809
- data.each {|key, value|
810
- data_n[key.to_s()]=value
811
- }
812
- if arguments[0].include?(:values) then
813
- #req[:values][:loginName] or req[:values]["loginName"]
814
- new_values_hash=Hash.new()
815
- arguments[0][:values].each {|kv, vv|
816
- if data_n.keys.include?(kv.to_s()) then
817
- new_values_hash[kv.to_s()]=vv
818
- end
819
- }
820
- data_n.merge!(new_values_hash)
821
- end
822
- data=data_n.to_json()
823
- elsif data.kind_of?(Array) then
824
- data_arr=Array.new()
825
- data.each_with_index {|row, indx|
826
- unless row.kind_of?(Hash) then
827
- @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string")
828
- return :error, :error, :error
829
- end
830
- data_n=Hash.new()
831
- row.each {|key, value|
832
- data_n[key.to_s()]=value
833
- }
834
- if arguments[0].include?(:values) then
835
- #req[:values][:loginName] or req[:values]["loginName"]
836
- new_values_hash=Hash.new()
837
- if arguments[0][:values].kind_of?(Hash) then #values[:mykey][3]
838
- arguments[0][:values].each {|kv, vv|
839
- if data_n.keys.include?(kv.to_s()) and !vv[indx].nil? then
840
- new_values_hash[kv.to_s()]=vv[indx]
841
- end
842
- }
843
- elsif arguments[0][:values].kind_of?(Array) then #values[5][:mykey]
844
- if !arguments[0][:values][indx].nil? then
845
- arguments[0][:values][indx].each {|kv, vv|
846
- if data_n.keys.include?(kv.to_s()) then
847
- new_values_hash[kv.to_s()]=vv
848
- end
849
- }
850
- end
851
- else
852
- @logger.fatal("Wrong format on request application/json when supplying values, the data is an array of Hashes but the values supplied are not")
853
- return :error, :error, :error
854
- end
855
- data_n.merge!(new_values_hash)
856
- end
857
- data_arr.push(data_n)
858
- }
859
- data=data_arr.to_json()
860
- else
861
- @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string")
862
- return :error, :error, :error
863
- end
864
- elsif content_type_included and arguments[0].include?(:values) then
865
- if arguments[0][:values].kind_of?(Hash) and arguments[0][:values].keys.size>0 then
866
- 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" then
867
- @logger.warn(":values key given without a valid content-type or data for request. No values modified on the request")
868
- end
869
- end
870
- end
871
- elsif arguments.size==1 and arguments[0].kind_of?(String) then
872
- #path=arguments[0].to_s()
873
- data=""
874
- else
875
- @logger.fatal("Invalid number of arguments or wrong arguments in #{method_s}")
876
- return :error, :error, :error
877
- end
878
- if headers_t.keys.include?("Content-Type") and !headers_t["Content-Type"]["multipart/form-data"].nil? and headers_t["Content-Type"]!=["multipart/form-data"] then #only for the case raw multipart request
879
- encoding="UTF-8"
880
- data_s=""
881
- else
882
- encoding=data.to_s().scan(/encoding='(.*)'/i).join
883
- if encoding.to_s()=="" then
884
- encoding=data.to_s().scan(/charset='(.*)'/i).join
885
- end
886
- if encoding.to_s()=="" and headers_t.include?("Content-Type") then
887
- encoding=headers_t["Content-Type"].scan(/charset='?(.*)'?/i).join
888
- if encoding.to_s()=="" then
889
- encoding=headers_t["Content-Type"].scan(/encoding='?(.*)'?/i).join
890
- end
891
- end
892
-
893
- begin
894
- data_s=JSON.pretty_generate(JSON.parse(data))
895
- rescue
896
- data_s=data
897
- end
898
- data_s=data_s.to_s().gsub("<", "&lt;")
899
- end
900
- if headers_t.keys.include?("Accept-Encoding")
901
- headers_t["Accept-Encoding"].gsub!("gzip","")#removed so the response is in plain text
902
- end
903
-
904
- headers_ts=""
905
- headers_t.each {|key, val| headers_ts+=key.to_s + ":" + val.to_s() + ", "}
906
- message="#{method_s} REQUEST: \npath= " + path.to_s() + "\n"
907
- message+="headers= " + headers_ts.to_s() + "\n"
908
- message+="data= " + data_s.to_s() + "\n"
909
- message=@message_server+"\n"+message
910
- if path.to_s().scan(/^https?:\/\//).size>0 and path.to_s().scan(/^https?:\/\/#{@host}/).size==0 then
911
- # the path is for another server than the current
912
- else
913
- NiceHttp.last_request=message
914
- @logger.info(message)
915
- end
916
-
917
- if data.to_s()!="" and encoding.to_s().upcase!="UTF-8" and encoding!="" then
918
- data=data.to_s().encode(encoding, "UTF-8")
919
- end
920
- return path, data, headers_t
921
- rescue Exception => stack
922
- @logger.fatal(stack)
923
- @logger.fatal("manage_request Error on method #{method_s} . path:#{path.to_s()}. data:#{data.to_s()}. headers:#{headers_t.to_s()}")
924
- return :error
925
- end
926
- end
927
-
928
- ######################################################
929
- # private method to manage Response
930
- # input:
931
- # resp
932
- # data
933
- # output:
934
- # @response updated
935
- ######################################################
936
- def manage_response(resp, data)
937
- require 'json'
938
- begin
939
- if @start_time.kind_of?(Time)
940
- @response[:time_elapsed_total]=Time.now-@start_time
941
- @start_time = nil
942
- else
943
- @response[:time_elapsed_total]=nil
944
- end
945
- if @start_time_net.kind_of?(Time)
946
- @response[:time_elapsed]=Time.now-@start_time_net
947
- @start_time_net = nil
948
- else
949
- @response[:time_elapsed]=nil
950
- end
951
- begin
952
- # this is to be able to access all keys as symbols
953
- new_resp=Hash.new()
954
- resp.each {|key, value|
955
- if key.kind_of?(String) then
956
- new_resp[key.to_sym]=value
957
- end
958
- }
959
- new_resp.each {|key, value|
960
- resp[key]=value
961
- }
962
- rescue
963
- end
964
- #for mock_responses to be able to add outside of the header like content-type for example
965
- if resp.kind_of?(Hash) and !resp.has_key?(:header) then
966
- resp[:header]={}
967
- end
968
- if resp.kind_of?(Hash)
969
- resp.each {|k, v|
970
- if k!=:code and k!=:message and k!=:data and k!=:'set-cookie' and k!=:header
971
- resp[:header][k]=v
972
- end
973
- }
974
- resp[:header].each {|k, v|
975
- resp.delete(k) if resp.has_key?(k)
976
- }
977
- end
978
-
979
- method_s=caller[0].to_s().scan(/:in `(.*)'/).join
980
- if resp.header.kind_of?(Hash) and (resp.header["content-type"].to_s()=="application/x-deflate" or resp.header[:"content-type"].to_s()=="application/x-deflate") then
981
- data=Zlib::Inflate.inflate(data)
982
- end
983
- encoding_response=""
984
- if resp.header.kind_of?(Hash) and (resp.header["content-type"].to_s()!="" or resp.header[:"content-type"].to_s()!="") then
985
- encoding_response=resp.header["content-type"].scan(/;charset=(.*)/i).join if resp.header.has_key?("content-type")
986
- encoding_response=resp.header[:"content-type"].scan(/;charset=(.*)/i).join if resp.header.has_key?(:"content-type")
987
- end
988
- if encoding_response.to_s()=="" then
989
- encoding_response="UTF-8"
990
- end
991
-
992
- if encoding_response.to_s()!="" and encoding_response.to_s().upcase!="UTF-8" then
993
- data.encode!("UTF-8", encoding_response.to_s())
994
- end
995
- if encoding_response!="" and encoding_response.to_s().upcase!="UTF-8" then
996
- @response[:message]=resp.message.to_s().encode("UTF-8", encoding_response.to_s())
997
- #todo: response data in here for example is convert into string, verify if that is correct or needs to maintain the original data type (hash, array...)
998
- resp.each {|key, val| @response[key]=val.to_s().encode("UTF-8", encoding_response.to_s())}
999
- else
1000
- @response[:message]=resp.message
1001
- resp.each {|key, val| @response[key]=val}
1002
- end
1003
- if !defined?(Net::HTTP::Post::Multipart) or (defined?(Net::HTTP::Post::Multipart) and !data.kind_of?(Net::HTTP::Post::Multipart))
1004
- @response[:data]=data
1005
- else
1006
- @response[:data]=""
1007
- end
1008
-
1009
- @response[:code]=resp.code
1010
-
1011
- unless @response.nil? then
1012
- message="\nRESPONSE: \n" + @response[:code].to_s()+ ":" + @response[:message].to_s()
1013
- if @debug then
1014
- NiceHttp.last_response=message
1015
- @response.each {|key, value|
1016
- if value.to_s()!="" then
1017
- value_orig=value
1018
- if key.kind_of?(Symbol) then
1019
- if key==:code or key==:data or key==:header or key==:message then
1020
- if key==:data then
1021
- begin
1022
- JSON.parse(value_orig)
1023
- data_s=JSON.pretty_generate(JSON.parse(value_orig))
1024
- rescue
1025
- data_s=value_orig
1026
- end
1027
- NiceHttp.last_response+="\nresponse." + key.to_s() + " = '" + data_s.gsub("<", "&lt;") + "'\n"
1028
- if value_orig != value then
1029
- message+="\nresponse." + key.to_s() + " = '" + value.gsub("<", "&lt;") + "'\n"
1030
- else
1031
- message+="\nresponse." + key.to_s() + " = '" + data_s.gsub("<", "&lt;") + "'\n"
1032
- end
1033
- else
1034
- NiceHttp.last_response+="\nresponse." + key.to_s() + " = '" + value.to_s().gsub("<", "&lt;") + "'"
1035
- message+="\nresponse." + key.to_s() + " = '" + value.to_s().gsub("<", "&lt;") + "'"
1036
- end
1037
- else
1038
- NiceHttp.last_response+="\nresponse[:" + key.to_s() + "] = '" + value.to_s().gsub("<", "&lt;") + "'"
1039
- message+="\nresponse[:" + key.to_s() + "] = '" + value.to_s().gsub("<", "&lt;") + "'"
1040
- end
1041
- elsif !@response.include?(key.to_sym)
1042
- NiceHttp.last_response+="\nresponse['" + key.to_s() + "'] = '" + value.to_s().gsub("<", "&lt;") + "'"
1043
- message+="\nresponse['" + key.to_s() + "'] = '" + value.to_s().gsub("<", "&lt;") + "'"
1044
- end
1045
- end
1046
- }
1047
-
1048
- end
1049
- @logger.info message
1050
- if @response.kind_of?(Hash) then
1051
- if @response.keys.include?(:requestid) then
1052
- @headers["requestId"]=@response[:requestid]
1053
- NiceHttp.request_id=@response[:requestid]
1054
- @logger.info "requestId was found on the response header and it has been added to the headers for the next request"
1055
- end
1056
- end
1057
- end
1058
-
1059
- if resp[:'set-cookie'].to_s()!="" then
1060
- if resp.kind_of?(Hash) then #mock_response
1061
- cookies_to_set=resp[:'set-cookie'].to_s().split(", ")
1062
- else #Net::Http
1063
- cookies_to_set=resp.get_fields('set-cookie')
1064
- end
1065
- cookies_to_set.each {|cookie|
1066
- cookie_pair=cookie.split('; ')[0].split("=")
1067
- cookie_path=cookie.scan(/; path=([^;]+)/i).join
1068
- @cookies[cookie_path]=Hash.new() unless @cookies.keys.include?(cookie_path)
1069
- @cookies[cookie_path][cookie_pair[0]]=cookie_pair[1]
1070
- }
1071
-
1072
- @logger.info "set-cookie added to Cookie header as required"
1073
-
1074
- if @headers.has_key?("X-CSRFToken") then
1075
- csrftoken=resp[:"set-cookie"].to_s().scan(/csrftoken=([\da-z]+);/).join
1076
- if csrftoken.to_s()!="" then
1077
- @headers["X-CSRFToken"]=csrftoken
1078
- @logger.info "X-CSRFToken exists on headers and has been overwritten"
1079
- end
1080
- else
1081
- csrftoken=resp[:"set-cookie"].to_s().scan(/csrftoken=([\da-z]+);/).join
1082
- if csrftoken.to_s()!="" then
1083
- @headers["X-CSRFToken"]=csrftoken
1084
- @logger.info "X-CSRFToken added to header as required"
1085
- end
1086
-
1087
- end
1088
- end
1089
-
1090
- rescue Exception => stack
1091
- @logger.fatal stack
1092
- @logger.fatal "manage_response Error on method #{method_s} "
1093
- end
1094
- end
1095
-
1096
- private :manage_request, :manage_response
1097
- end
1098
-
1
+ require 'logger'
2
+ require 'nice_hash'
3
+ require 'nice_http_utils'
4
+
5
+ class NiceHttp
6
+ class << self
7
+ attr_accessor :host, :port, :ssl, :headers, :debug, :log, :proxy_host, :proxy_port,
8
+ :last_request, :last_response, :request_id, :use_mocks, :connections,
9
+ :active, :auto_redirect
10
+ end
11
+ @host = nil
12
+ @port = 80
13
+ @ssl = false
14
+ @headers = {}
15
+ @debug = false
16
+ @log = :fix_file
17
+ @proxy_host = nil
18
+ @proxy_port = nil
19
+ @last_request=nil
20
+ @last_response=nil
21
+ @request_id=""
22
+ @use_mocks = false
23
+ @connections = []
24
+ @active=0
25
+ @auto_redirect = true
26
+
27
+ attr_reader :host, :port, :ssl, :debug, :log, :proxy_host, :proxy_port, :response, :num_redirects
28
+ attr_accessor :headers, :cookies, :use_mocks, :auto_redirect, :logger
29
+
30
+ def self.defaults=(par = {})
31
+ @host = par[:host] if par.key?(:host)
32
+ @port = par[:port] if par.key?(:port)
33
+ @ssl = par[:ssl] if par.key?(:ssl)
34
+ @headers = par[:headers] if par.key?(:headers)
35
+ @debug = par[:debug] if par.key?(:debug)
36
+ @log = par[:log] if par.key?(:log)
37
+ @proxy_host = par[:proxy_host] if par.key?(:proxy_host)
38
+ @proxy_port = par[:proxy_port] if par.key?(:proxy_port)
39
+ @proxy_port = par[:use_mocks] if par.key?(:use_mocks)
40
+ @auto_redirect = par[:auto_redirect] if par.key?(:auto_redirect)
41
+ end
42
+
43
+ ######################################################
44
+ # input:
45
+ # no parameters:
46
+ # By default will access how is setup on defaults
47
+ # one parameter:
48
+ # String
49
+ # "https://www.example.com"
50
+ # "example.com:8999"
51
+ # "localhost:8322"
52
+ # Hash containing these possible keys
53
+ # host -- example.com. (default blank screen)
54
+ # port -- port for the connection. 80 (default)
55
+ # ssl -- true, false (default)
56
+ # headers -- hash with the header key:values
57
+ # debug -- true, false (default)
58
+ # log -- :no, :screen, :file, :fix_file (default).
59
+ # A string with a path can be supplied.
60
+ # If :fix_file: nice_http.log
61
+ # In case :file it will be generated a log file with name: nice_http_YY-mm-dd-HHMMSS.log
62
+ # proxy_host
63
+ # proxy_port
64
+ ######################################################
65
+ def initialize(args = {})
66
+ require 'net/http'
67
+ require 'net/https'
68
+ @host = NiceHttp.host
69
+ @port = NiceHttp.port
70
+ @ssl = NiceHttp.ssl
71
+ @headers = NiceHttp.headers
72
+ @debug = NiceHttp.debug
73
+ @log = NiceHttp.log
74
+ @proxy_host = NiceHttp.proxy_host
75
+ @proxy_port = NiceHttp.proxy_port
76
+ @use_mocks = NiceHttp.use_mocks
77
+ @auto_redirect=false #set it up at the end of initialize
78
+ auto_redirect = NiceHttp.auto_redirect
79
+ @num_redirects=0
80
+
81
+ #todo: set only the cookies for the current domain
82
+ #key: path, value: hash with key is the name of the cookie and value the value
83
+ # we set the default value for non existing keys to empty Hash {} so in case of merge there is no problem
84
+ @cookies=Hash.new {|h, k| h[k] = {}}
85
+
86
+ begin
87
+ if args.is_a?(String)
88
+ uri = URI.parse(args)
89
+ @host = uri.host unless uri.host.nil?
90
+ @port = uri.port unless uri.port.nil?
91
+ @ssl = true if !uri.scheme.nil? && (uri.scheme == 'https')
92
+ elsif args.is_a?(Hash) && !args.keys.empty?
93
+ @host = args[:host] if args.keys.include?(:host)
94
+ @port = args[:port] if args.keys.include?(:port)
95
+ @ssl = args[:ssl] if args.keys.include?(:ssl)
96
+ @headers = args[:headers] if args.keys.include?(:headers)
97
+ @debug = args[:debug] if args.keys.include?(:debug)
98
+ @log = args[:log] if args.keys.include?(:log)
99
+ @proxy_host = args[:proxy_host] if args.keys.include?(:proxy_host)
100
+ @proxy_port = args[:proxy_port] if args.keys.include?(:proxy_port)
101
+ @use_mocks = args[:use_mocks] if args.keys.include?(:use_mocks)
102
+ @auto_redirect = args[:auto_redirect] if args.keys.include?(:auto_redirect)
103
+ end
104
+
105
+ if @host.to_s!="" and (@host.include?("http:") or @host.include?("https:"))
106
+ uri = URI.parse(@host)
107
+ @host = uri.host unless uri.host.nil?
108
+ @port = uri.port unless uri.port.nil?
109
+ @ssl = true if !uri.scheme.nil? && (uri.scheme == 'https')
110
+ end
111
+
112
+ if @host.nil? or @host.to_s=="" or @port.nil? or @port.to_s==""
113
+ message = "It was not possible to create the http connection!!!\n"
114
+ message += "Wrong host or port, remember to supply http:// or https:// in case you specify an url to create the http connection, for example:\n"
115
+ message += "http = NiceHttp.new('http://example.com')"
116
+ raise message
117
+ end
118
+
119
+ if !@proxy_host.nil? && !@proxy_port.nil?
120
+ @http = Net::HTTP::Proxy(@proxy_host, @proxy_port).new(@host, @port)
121
+ @http.use_ssl = @ssl
122
+ @http.set_debug_output $stderr if @debug
123
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
124
+ @http.start
125
+ else
126
+ @http = Net::HTTP.new(@host, @port)
127
+ @http.use_ssl = @ssl
128
+ @http.set_debug_output $stderr if @debug
129
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
130
+ @http.start
131
+ end
132
+
133
+ if @log.kind_of?(String)
134
+ @logger = Logger.new File.new(@log, "w")
135
+ elsif @log==:fix_file
136
+ @logger = Logger.new File.new("nice_http.log", "w")
137
+ elsif @log==:file
138
+ @logger = Logger.new File.new("nice_http_#{Time.now.strftime('%Y-%m-%d-%H%M%S')}.log", 'w')
139
+ elsif @log==:screen
140
+ @logger = Logger.new STDOUT
141
+ elsif @log==:no
142
+ @logger = Logger.new nil
143
+ end
144
+ @logger.level = Logger::INFO
145
+
146
+ @message_server="(#{self.object_id}):"
147
+
148
+ 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()} "
149
+
150
+ @logger.info(log_message)
151
+ @message_server+=" Http connection: "
152
+ if @ssl then
153
+ @message_server+="https://"
154
+ else
155
+ @message_server+="http://"
156
+ end
157
+ @message_server+="#{@host}:#{@port}"
158
+ if @proxy_host.to_s!="" then
159
+ @message_server+=" proxy:#{@proxy_host}:#{@proxy_port}"
160
+ end
161
+ @auto_redirect = auto_redirect
162
+ rescue Exception => stack
163
+ if @logger.nil?
164
+ puts stack
165
+ @logger = Logger.new nil
166
+ else
167
+ @logger.fatal stack
168
+ end
169
+ end
170
+
171
+ NiceHttp.active+=1
172
+ NiceHttp.connections.push(self)
173
+
174
+ end
175
+
176
+ ######################################################
177
+ # Get data from path
178
+ # input:
179
+ # 1 argument
180
+ # Hash containing at least key :path
181
+ # 1 argument
182
+ # path (string)
183
+ # output:
184
+ # response -> Hash including at least the symbol keys:
185
+ # :data = the response data body
186
+ # :message = plain text response
187
+ # :code = code response (200=ok,500=wrong...)
188
+ # *All keys in response are lowercase
189
+ # data, message and code can also be accessed as attributes like .message .code .data, for example:
190
+ # resp=@http.get(Requests::Customer.get_profile)
191
+ # assert resp.code==200
192
+ ######################################################
193
+ def get(arg)
194
+ begin
195
+ path, data, headers_t=manage_request(arg)
196
+ @start_time = Time.now if @start_time.nil?
197
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
198
+ data=""
199
+ if arg[:mock_response].keys.include?(:data) then
200
+ data=arg[:mock_response][:data]
201
+ if data.kind_of?(Hash) #to json
202
+ begin
203
+ require 'json'
204
+ data=data.to_json
205
+ rescue
206
+ @logger.fatal "There was a problem converting to json: #{data}"
207
+ end
208
+ end
209
+ end
210
+ @logger.warn "Pay attention!!! This is a mock response:"
211
+ @start_time_net = Time.now if @start_time_net.nil?
212
+ manage_response(arg[:mock_response], data.to_s)
213
+ return @response
214
+ end
215
+ begin
216
+ if path.start_with?("http:") or path.start_with?("https:") then #server included on path problably because of a redirection to a different server
217
+ require 'uri'
218
+ uri = URI.parse(path)
219
+ ssl=false
220
+ ssl=true if path.include?("https:")
221
+
222
+
223
+ server="http://"
224
+ server="https://" if path.include?("https:")
225
+ if uri.port!=443 then
226
+ server+="#{uri.host}:#{uri.port}"
227
+ else
228
+ server+="#{uri.host}"
229
+ end
230
+
231
+ http_redir=nil
232
+ NiceHttp.connections.each {|conn|
233
+ if conn.host == uri.host and conn.port==uri.port then
234
+ http_redir=conn
235
+ break
236
+ end
237
+ }
238
+
239
+ if !http_redir.nil?
240
+ path, data, headers_t=manage_request(arg)
241
+ http_redir.cookies.merge!(@cookies)
242
+ http_redir.headers.merge!(headers_t)
243
+ resp=http_redir.get(path.gsub(server, "")) #todo: remove only the server at the begining in case in query is the server it will be replaced when it should not be
244
+ @response=http_redir.response
245
+ else
246
+ @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."
247
+ end
248
+
249
+ else
250
+ @start_time_net = Time.now if @start_time_net.nil?
251
+ resp=@http.get(path, headers_t)
252
+ data=resp.body
253
+ manage_response(resp, data)
254
+ end
255
+ rescue Exception => stack
256
+ @logger.warn stack
257
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
258
+ @http.finish()
259
+ @http.start()
260
+ @start_time_net = Time.now if @start_time_net.nil?
261
+ resp=@http.get(path)
262
+ data=resp.body
263
+ manage_response(resp, data)
264
+ end
265
+ if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
266
+ if @num_redirects<=30 then
267
+ @num_redirects+=1
268
+ current_server="http"
269
+ current_server+="s" if @ssl==true
270
+ current_server+="://#{@host}"
271
+ location=@response[:location].gsub(current_server, "")
272
+ @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
273
+ get(location)
274
+ else
275
+ @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"
276
+ @num_redirects=0
277
+ end
278
+ else
279
+ @num_redirects=0
280
+ end
281
+ return @response
282
+ rescue Exception => stack
283
+ @logger.fatal stack
284
+ return :error
285
+ end
286
+ end
287
+
288
+ ######################################################
289
+ # Post data to path
290
+ # input:
291
+ # 1 argument
292
+ # Hash containing at least keys :data, :path
293
+ # 3 arguments
294
+ # path (string)
295
+ # data (json data for example)
296
+ # additional_headers (Hash key=>value)
297
+ # output:
298
+ # response -> Hash including at least the symbol keys:
299
+ # :data = the response data body
300
+ # :message = plain text response
301
+ # :code = code response (200=ok,500=wrong...)
302
+ # *All keys in response are lowercase
303
+ # data, message and code can also be accessed as attributes like .message .code .data, for example:
304
+ # resp=@http.post(Requests::Customer.update_customer)
305
+ # assert resp.code==201
306
+ ######################################################
307
+ def post(*arguments)
308
+ begin
309
+ path, data, headers_t=manage_request(*arguments)
310
+ @start_time = Time.now if @start_time.nil?
311
+ if arguments.size>0 and arguments[0].kind_of?(Hash) then
312
+ arg=arguments[0]
313
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
314
+ data=""
315
+ if arg[:mock_response].keys.include?(:data) then
316
+ data=arg[:mock_response][:data]
317
+ if data.kind_of?(Hash) #to json
318
+ begin
319
+ require 'json'
320
+ data=data.to_json
321
+ rescue
322
+ @logger.fatal "There was a problem converting to json: #{data}"
323
+ end
324
+ end
325
+ end
326
+ @logger.warn "Pay attention!!! This is a mock response:"
327
+ @start_time_net = Time.now if @start_time_net.nil?
328
+ manage_response(arg[:mock_response], data.to_s)
329
+ return @response
330
+ end
331
+ end
332
+
333
+ begin
334
+ @start_time_net = Time.now if @start_time_net.nil?
335
+ if headers_t["Content-Type"] == "multipart/form-data" then
336
+ require 'net/http/post/multipart'
337
+ headers_t.each {|key, value|
338
+ arguments[0][:data].add_field(key, value) #add to Headers
339
+ }
340
+ resp=@http.request(arguments[0][:data])
341
+ else
342
+ resp=@http.post(path, data, headers_t)
343
+ data=resp.body
344
+ end
345
+ rescue Exception => stack
346
+ @logger.warn stack
347
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
348
+ @http.finish()
349
+ @http.start()
350
+ @start_time_net = Time.now if @start_time_net.nil?
351
+ resp, data=@http.post(path, data, headers_t)
352
+ end
353
+ manage_response(resp, data)
354
+ if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
355
+ if @num_redirects<=30 then
356
+ @num_redirects+=1
357
+ current_server="http"
358
+ current_server+="s" if @ssl==true
359
+ current_server+="://#{@host}"
360
+ location=@response[:location].gsub(current_server, "")
361
+ @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
362
+ get(location)
363
+ else
364
+ @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"
365
+ @num_redirects=0
366
+ end
367
+ else
368
+ @num_redirects=0
369
+ end
370
+ return @response
371
+ rescue Exception => stack
372
+ @logger.warn stack
373
+ return :error
374
+ end
375
+
376
+ end
377
+
378
+
379
+ ######################################################
380
+ # Put data to path
381
+ # input:
382
+ # 1 argument
383
+ # Hash containing at least keys :data, :path
384
+ # 3 arguments
385
+ # path (string)
386
+ # data (json data for example)
387
+ # additional_headers (Hash key=>value)
388
+ # output:
389
+ # response -> Hash including at least the symbol keys:
390
+ # :data = the response data body
391
+ # :message = plain text response
392
+ # :code = code response (200=ok,500=wrong...)
393
+ # *All keys in response are lowercase
394
+ # data, message and code can also be accessed as attributes like .message .code .data, for example:
395
+ # resp=@http.put(Requests::Customer.remove_phone)
396
+ # assert resp.code==200
397
+ ######################################################
398
+ def put(*arguments)
399
+ begin
400
+ path, data, headers_t=manage_request(*arguments)
401
+ @start_time = Time.now if @start_time.nil?
402
+ if arguments.size>0 and arguments[0].kind_of?(Hash) then
403
+ arg=arguments[0]
404
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
405
+ data=""
406
+ if arg[:mock_response].keys.include?(:data) then
407
+ data=arg[:mock_response][:data]
408
+ if data.kind_of?(Hash) #to json
409
+ begin
410
+ require 'json'
411
+ data=data.to_json
412
+ rescue
413
+ @logger.fatal "There was a problem converting to json: #{data}"
414
+ end
415
+ end
416
+ end
417
+ @logger.warn "Pay attention!!! This is a mock response:"
418
+ @start_time_net = Time.now if @start_time_net.nil?
419
+ manage_response(arg[:mock_response], data.to_s)
420
+ return @response
421
+ end
422
+ end
423
+
424
+ begin
425
+ @start_time_net = Time.now if @start_time_net.nil?
426
+ resp=@http.send_request("PUT", path, data, headers_t)
427
+ data=resp.body
428
+ rescue Exception => stack
429
+ @logger.warn stack
430
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
431
+ @http.finish()
432
+ @http.start()
433
+ @start_time_net = Time.now if @start_time_net.nil?
434
+ resp, data=@http.send_request("PUT", path, data, headers_t)
435
+ end
436
+ manage_response(resp, data)
437
+
438
+ return @response
439
+ rescue Exception => stack
440
+ @logger.fatal stack, self
441
+ return :error
442
+ end
443
+
444
+ end
445
+
446
+
447
+ ######################################################
448
+ # Patch data to path
449
+ # input:
450
+ # 1 argument
451
+ # Hash containing at least keys :data, :path
452
+ # 3 arguments
453
+ # path (string)
454
+ # data (json data for example)
455
+ # additional_headers (Hash key=>value)
456
+ # output:
457
+ # response -> Hash including at least the symbol keys:
458
+ # :data = the response data body
459
+ # :message = plain text response
460
+ # :code = code response (200=ok,500=wrong...)
461
+ # *All keys in response are lowercase
462
+ # data, message and code can also be accessed as attributes like .message .code .data, for example:
463
+ # resp=@http.patch(Requests::Customer.unrelease_account)
464
+ # assert resp.code==200
465
+ ######################################################
466
+ def patch(*arguments)
467
+ begin
468
+ path, data, headers_t=manage_request(*arguments)
469
+ @start_time = Time.now if @start_time.nil?
470
+ if arguments.size>0 and arguments[0].kind_of?(Hash) then
471
+ arg=arguments[0]
472
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
473
+ data=""
474
+ if arg[:mock_response].keys.include?(:data) then
475
+ data=arg[:mock_response][:data]
476
+ if data.kind_of?(Hash) #to json
477
+ begin
478
+ require 'json'
479
+ data=data.to_json
480
+ rescue
481
+ @logger.fatal "There was a problem converting to json: #{data}"
482
+ end
483
+ end
484
+ end
485
+ @logger.warn "Pay attention!!! This is a mock response:"
486
+ @start_time_net = Time.now if @start_time_net.nil?
487
+ manage_response(arg[:mock_response], data.to_s)
488
+ return @response
489
+ end
490
+ end
491
+
492
+ begin
493
+ @start_time_net = Time.now if @start_time_net.nil?
494
+ resp=@http.patch(path, data, headers_t)
495
+ data=resp.body
496
+ rescue Exception => stack
497
+ @logger.warn stack
498
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
499
+ @http.finish()
500
+ @http.start()
501
+ @start_time_net = Time.now if @start_time_net.nil?
502
+ resp, data=@http.patch(path, data, headers_t)
503
+ end
504
+ manage_response(resp, data)
505
+ if @auto_redirect and @response[:code].to_i>=300 and @response[:code].to_i<400 and @response.include?(:location) then
506
+ if @num_redirects<=30 then
507
+ @num_redirects+=1
508
+ current_server="http"
509
+ current_server+="s" if @ssl==true
510
+ current_server+="://#{@host}"
511
+ location=@response[:location].gsub(current_server, "")
512
+ @logger.info "(#{@num_redirects}) Redirecting NiceHttp to #{location}"
513
+ get(location)
514
+ else
515
+ @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"
516
+ @num_redirects=0
517
+ end
518
+ else
519
+ @num_redirects=0
520
+ end
521
+ return @response
522
+ rescue Exception => stack
523
+ @logger.fatal stack
524
+ return :error
525
+ end
526
+
527
+ end
528
+
529
+
530
+ ######################################################
531
+ # Delete an existing resource
532
+ # input:
533
+ # 1 argument
534
+ # Hash containing at least key :path
535
+ # 1 argument
536
+ # String giving the path
537
+ # output:
538
+ # response -> Hash including at least the symbol keys:
539
+ # :data = the response data body
540
+ # :message = plain text response
541
+ # :code = code response (200=ok,500=wrong...)
542
+ # *All keys in response are lowercase
543
+ # data, message and code can also be accessed as attributes like .message .code .data, for example:
544
+ # resp=@http.delete(Requests::Customer.remove_session)
545
+ # assert resp.code==204
546
+ ######################################################
547
+ def delete(argument)
548
+ begin
549
+ if argument.kind_of?(String) then
550
+ argument={:path => argument}
551
+ end
552
+ path, data, headers_t=manage_request(argument)
553
+ @start_time = Time.now if @start_time.nil?
554
+ if argument.kind_of?(Hash) then
555
+ arg=argument
556
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
557
+ data=""
558
+ if arg[:mock_response].keys.include?(:data) then
559
+ data=arg[:mock_response][:data]
560
+ if data.kind_of?(Hash) #to json
561
+ begin
562
+ require 'json'
563
+ data=data.to_json
564
+ rescue
565
+ @logger.fatal "There was a problem converting to json: #{data}"
566
+ end
567
+ end
568
+ end
569
+ @logger.warn "Pay attention!!! This is a mock response:"
570
+ @start_time_net = Time.now if @start_time_net.nil?
571
+ manage_response(arg[:mock_response], data.to_s)
572
+ return @response
573
+ end
574
+ end
575
+
576
+ begin
577
+ @start_time_net = Time.now if @start_time_net.nil?
578
+ resp=@http.delete(path, headers_t)
579
+ data=resp.body
580
+ rescue Exception => stack
581
+ @logger.warn stack
582
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
583
+ @http.finish()
584
+ @http.start()
585
+ @start_time_net = Time.now if @start_time_net.nil?
586
+ resp, data=@http.delete(path)
587
+ end
588
+ manage_response(resp, data)
589
+
590
+ return @response
591
+ rescue Exception => stack
592
+ @logger.fatal stack
593
+ return :error
594
+ end
595
+
596
+ end
597
+
598
+ ######################################################
599
+ # Implementation of the http HEAD method.
600
+ # Asks for the response identical to the one that would correspond to a GET request, but without the response body.
601
+ # This is useful for retrieving meta-information written in response headers, without having to transport the entire content.
602
+ # input:
603
+ # 1 argument
604
+ # Hash containing at least key :path
605
+ # 1 argument
606
+ # String giving the path
607
+ # output:
608
+ # response -> Hash including the symbol keys:
609
+ # :message = plain text response
610
+ # :code = code response (200=ok,500=wrong...)
611
+ # *All keys in response are lowercase
612
+ ######################################################
613
+ def head(argument)
614
+ begin
615
+ if argument.kind_of?(String) then
616
+ argument={:path => argument}
617
+ end
618
+ path, data, headers_t=manage_request(argument)
619
+ @start_time = Time.now if @start_time.nil?
620
+ if argument.kind_of?(Hash) then
621
+ arg=argument
622
+ if @use_mocks and arg.kind_of?(Hash) and arg.keys.include?(:mock_response) then
623
+ data=""
624
+ if arg[:mock_response].keys.include?(:data) then
625
+ data=arg[:mock_response][:data]
626
+ if data.kind_of?(Hash) #to json
627
+ begin
628
+ require 'json'
629
+ data=data.to_json
630
+ rescue
631
+ @logger.fatal "There was a problem converting to json: #{data}"
632
+ end
633
+ end
634
+ end
635
+ @logger.warn "Pay attention!!! This is a mock response:"
636
+ @start_time_net = Time.now if @start_time_net.nil?
637
+ manage_response(arg[:mock_response], data.to_s)
638
+ return @response
639
+ end
640
+ end
641
+
642
+ begin
643
+ @start_time_net = Time.now if @start_time_net.nil?
644
+ resp=@http.head(path, headers_t)
645
+ data=resp.body
646
+ rescue Exception => stack
647
+ @logger.warn stack
648
+ @logger.warn "The connection seems to be closed in the host machine. Trying to reconnect"
649
+ @http.finish()
650
+ @http.start()
651
+ @start_time_net = Time.now if @start_time_net.nil?
652
+ resp, data=@http.head(path)
653
+ end
654
+ manage_response(resp, data)
655
+ return @response
656
+ rescue Exception => stack
657
+ @logger.fatal stack
658
+ return :error
659
+ end
660
+ end
661
+
662
+
663
+ ######################################################
664
+ # Close HTTP connection
665
+ ######################################################
666
+ def close
667
+ begin
668
+ pos=0
669
+ found=false
670
+ NiceHttp.connections.each {|conn|
671
+ if conn.object_id == self.object_id then
672
+ found=true
673
+ break
674
+ end
675
+ pos+=1
676
+ }
677
+ if found
678
+ NiceHttp.connections.delete_at(pos)
679
+ end
680
+
681
+ unless @closed
682
+ if !@http.nil? then
683
+ @http.finish()
684
+ @http=nil
685
+ @logger.info "the HTTP connection was closed: #{@message_server}"
686
+ else
687
+ @http=nil
688
+ @logger.fatal "It was not possible to close the HTTP connection: #{@message_server}"
689
+ end
690
+ @closed=true
691
+ else
692
+ @logger.warn "It was not possible to close the HTTP connection, already closed: #{@message_server}"
693
+ end
694
+ rescue Exception => stack
695
+ @logger.fatal stack
696
+ end
697
+ NiceHttp.active-=1
698
+ end
699
+
700
+
701
+ ######################################################
702
+ # private method to manage Request
703
+ # input:
704
+ # 3 args: path, data, headers
705
+ # 1 arg: Hash containg at least keys :path and :data
706
+ # output:
707
+ # path, data, headers
708
+ ######################################################
709
+ def manage_request(*arguments)
710
+ require 'json'
711
+ begin
712
+ content_type_included=false
713
+ path=""
714
+ data=""
715
+
716
+ @response=Hash.new()
717
+ headers_t=@headers.dup()
718
+ cookies_to_set_str=""
719
+ if arguments.size==3 then
720
+ path=arguments[0]
721
+ elsif arguments.size==1 and arguments[0].kind_of?(Hash) then
722
+ path=arguments[0][:path]
723
+ elsif arguments.size==1 and arguments[0].kind_of?(String) then
724
+ path=arguments[0].to_s()
725
+ end
726
+ @cookies.each {|cookie_path, cookies_hash|
727
+ cookie_path="" if cookie_path=="/"
728
+ path_to_check=path
729
+ if path=="/" or path[-1]!="/" then
730
+ path_to_check+="/"
731
+ end
732
+ if path_to_check.scan(/^#{cookie_path}\//).size>0 then
733
+ cookies_hash.each {|key, value|
734
+ cookies_to_set_str+="#{key}=#{value}; "
735
+ }
736
+ end
737
+ }
738
+ headers_t["Cookie"]=cookies_to_set_str
739
+
740
+ method_s=caller[0].to_s().scan(/:in `(.*)'/).join
741
+
742
+ if arguments.size==3 then
743
+ data=arguments[1]
744
+ if arguments[2].kind_of?(Hash) then
745
+ headers_t.merge!(arguments[2])
746
+ end
747
+ elsif arguments.size==1 and arguments[0].kind_of?(Hash) then
748
+ if arguments[0][:data].nil? then
749
+ if arguments[0].keys.include?(:data) then
750
+ data=""
751
+ elsif arguments[0].keys.include?(:data_examples) and
752
+ arguments[0][:data_examples].kind_of?(Array) then
753
+ data=arguments[0][:data_examples][0] #the first example by default
754
+ else
755
+ data=""
756
+ end
757
+
758
+ else
759
+ data=arguments[0][:data]
760
+ end
761
+ if arguments[0].include?(:headers) then
762
+ headers_t.merge!(arguments[0][:headers])
763
+ end
764
+
765
+ if headers_t["Content-Type"].to_s()=="" and headers_t["content-type"].to_s()=="" and
766
+ headers_t[:"content-type"].to_s()=="" and headers_t[:"Content-Type"].to_s()=="" then
767
+ content_type_included=false
768
+ elsif headers_t["content-type"].to_s()!="" then
769
+ content_type_included=true
770
+ headers_t["Content-Type"]=headers_t["content-type"]
771
+ elsif headers_t[:"content-type"].to_s()!="" then
772
+ content_type_included=true
773
+ headers_t["Content-Type"]=headers_t[:"content-type"]
774
+ headers_t.delete(:"content-type")
775
+ elsif headers_t[:"Content-Type"].to_s()!="" then
776
+ content_type_included=true
777
+ headers_t["Content-Type"]=headers_t[:"Content-Type"]
778
+ headers_t.delete(:"Content-Type")
779
+ elsif headers_t["Content-Type"].to_s()!="" then
780
+ content_type_included=true
781
+ end
782
+
783
+ if !content_type_included and data.kind_of?(Hash)
784
+ headers_t['Content-Type'] = 'application/json'
785
+ content_type_included=true
786
+ end
787
+
788
+ if content_type_included and (!headers_t["Content-Type"][/text\/xml/].nil? or
789
+ !headers_t["Content-Type"]["application/soap+xml"].nil? or
790
+ !headers_t["Content-Type"][/application\/jxml/].nil?) then
791
+ if arguments[0].include?(:values) then
792
+ arguments[0][:values].each {|key, value|
793
+ data=NiceHttpUtils.set_value_xml_tag(key.to_s(), data, value.to_s(), true)
794
+ }
795
+ end
796
+ elsif content_type_included and !headers_t["Content-Type"][/application\/json/].nil? and data.to_s()!="" then
797
+ require 'json'
798
+ if data.kind_of?(String) then
799
+ if arguments[0].include?(:values) then
800
+ arguments[0][:values].each {|key, value|
801
+ data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *")(.*)(" *, *$)/, '\1' + value+ '\4') # "key":"value", or key:"value",
802
+ data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *")(.*)(" *$)/, '\1' + value+ '\4') # "key":"value" or key:"value"
803
+ data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *[^"])([^"].*)([^"] *, *$)/, '\1' + value+ '\4') # "key":456, or key:456,
804
+ data.gsub!(/(( *|^)"?#{key.to_s()}"? *: *[^"])([^"].*)([^"] * *$)/, '\1' + value+ '\4') # "key":456 or key:456
805
+ }
806
+ end
807
+ elsif data.kind_of?(Hash) then
808
+ data_n=Hash.new()
809
+ data.each {|key, value|
810
+ data_n[key.to_s()]=value
811
+ }
812
+ if arguments[0].include?(:values) then
813
+ #req[:values][:loginName] or req[:values]["loginName"]
814
+ new_values_hash=Hash.new()
815
+ arguments[0][:values].each {|kv, vv|
816
+ if data_n.keys.include?(kv.to_s()) then
817
+ new_values_hash[kv.to_s()]=vv
818
+ end
819
+ }
820
+ data_n.merge!(new_values_hash)
821
+ end
822
+ data=data_n.to_json()
823
+ elsif data.kind_of?(Array) then
824
+ data_arr=Array.new()
825
+ data.each_with_index {|row, indx|
826
+ unless row.kind_of?(Hash) then
827
+ @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string")
828
+ return :error, :error, :error
829
+ end
830
+ data_n=Hash.new()
831
+ row.each {|key, value|
832
+ data_n[key.to_s()]=value
833
+ }
834
+ if arguments[0].include?(:values) then
835
+ #req[:values][:loginName] or req[:values]["loginName"]
836
+ new_values_hash=Hash.new()
837
+ if arguments[0][:values].kind_of?(Hash) then #values[:mykey][3]
838
+ arguments[0][:values].each {|kv, vv|
839
+ if data_n.keys.include?(kv.to_s()) and !vv[indx].nil? then
840
+ new_values_hash[kv.to_s()]=vv[indx]
841
+ end
842
+ }
843
+ elsif arguments[0][:values].kind_of?(Array) then #values[5][:mykey]
844
+ if !arguments[0][:values][indx].nil? then
845
+ arguments[0][:values][indx].each {|kv, vv|
846
+ if data_n.keys.include?(kv.to_s()) then
847
+ new_values_hash[kv.to_s()]=vv
848
+ end
849
+ }
850
+ end
851
+ else
852
+ @logger.fatal("Wrong format on request application/json when supplying values, the data is an array of Hashes but the values supplied are not")
853
+ return :error, :error, :error
854
+ end
855
+ data_n.merge!(new_values_hash)
856
+ end
857
+ data_arr.push(data_n)
858
+ }
859
+ data=data_arr.to_json()
860
+ else
861
+ @logger.fatal("Wrong format on request application/json, be sure is a Hash, Array of Hashes or JSON string")
862
+ return :error, :error, :error
863
+ end
864
+ elsif content_type_included and arguments[0].include?(:values) then
865
+ if arguments[0][:values].kind_of?(Hash) and arguments[0][:values].keys.size>0 then
866
+ 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" then
867
+ @logger.warn(":values key given without a valid content-type or data for request. No values modified on the request")
868
+ end
869
+ end
870
+ end
871
+ elsif arguments.size==1 and arguments[0].kind_of?(String) then
872
+ #path=arguments[0].to_s()
873
+ data=""
874
+ else
875
+ @logger.fatal("Invalid number of arguments or wrong arguments in #{method_s}")
876
+ return :error, :error, :error
877
+ end
878
+ if headers_t.keys.include?("Content-Type") and !headers_t["Content-Type"]["multipart/form-data"].nil? and headers_t["Content-Type"]!=["multipart/form-data"] then #only for the case raw multipart request
879
+ encoding="UTF-8"
880
+ data_s=""
881
+ else
882
+ encoding=data.to_s().scan(/encoding='(.*)'/i).join
883
+ if encoding.to_s()=="" then
884
+ encoding=data.to_s().scan(/charset='(.*)'/i).join
885
+ end
886
+ if encoding.to_s()=="" and headers_t.include?("Content-Type") then
887
+ encoding=headers_t["Content-Type"].scan(/charset='?(.*)'?/i).join
888
+ if encoding.to_s()=="" then
889
+ encoding=headers_t["Content-Type"].scan(/encoding='?(.*)'?/i).join
890
+ end
891
+ end
892
+
893
+ begin
894
+ data_s=JSON.pretty_generate(JSON.parse(data))
895
+ rescue
896
+ data_s=data
897
+ end
898
+ data_s=data_s.to_s().gsub("<", "&lt;")
899
+ end
900
+ if headers_t.keys.include?("Accept-Encoding")
901
+ headers_t["Accept-Encoding"].gsub!("gzip","")#removed so the response is in plain text
902
+ end
903
+
904
+ headers_ts=""
905
+ headers_t.each {|key, val| headers_ts+=key.to_s + ":" + val.to_s() + ", "}
906
+ message="#{method_s} REQUEST: \npath= " + path.to_s() + "\n"
907
+ message+="headers= " + headers_ts.to_s() + "\n"
908
+ message+="data= " + data_s.to_s() + "\n"
909
+ message=@message_server+"\n"+message
910
+ if path.to_s().scan(/^https?:\/\//).size>0 and path.to_s().scan(/^https?:\/\/#{@host}/).size==0 then
911
+ # the path is for another server than the current
912
+ else
913
+ NiceHttp.last_request=message
914
+ @logger.info(message)
915
+ end
916
+
917
+ if data.to_s()!="" and encoding.to_s().upcase!="UTF-8" and encoding!="" then
918
+ data=data.to_s().encode(encoding, "UTF-8")
919
+ end
920
+ return path, data, headers_t
921
+ rescue Exception => stack
922
+ @logger.fatal(stack)
923
+ @logger.fatal("manage_request Error on method #{method_s} . path:#{path.to_s()}. data:#{data.to_s()}. headers:#{headers_t.to_s()}")
924
+ return :error
925
+ end
926
+ end
927
+
928
+ ######################################################
929
+ # private method to manage Response
930
+ # input:
931
+ # resp
932
+ # data
933
+ # output:
934
+ # @response updated
935
+ ######################################################
936
+ def manage_response(resp, data)
937
+ require 'json'
938
+ begin
939
+ if @start_time.kind_of?(Time)
940
+ @response[:time_elapsed_total]=Time.now-@start_time
941
+ @start_time = nil
942
+ else
943
+ @response[:time_elapsed_total]=nil
944
+ end
945
+ if @start_time_net.kind_of?(Time)
946
+ @response[:time_elapsed]=Time.now-@start_time_net
947
+ @start_time_net = nil
948
+ else
949
+ @response[:time_elapsed]=nil
950
+ end
951
+ begin
952
+ # this is to be able to access all keys as symbols
953
+ new_resp=Hash.new()
954
+ resp.each {|key, value|
955
+ if key.kind_of?(String) then
956
+ new_resp[key.to_sym]=value
957
+ end
958
+ }
959
+ new_resp.each {|key, value|
960
+ resp[key]=value
961
+ }
962
+ rescue
963
+ end
964
+ #for mock_responses to be able to add outside of the header like content-type for example
965
+ if resp.kind_of?(Hash) and !resp.has_key?(:header) then
966
+ resp[:header]={}
967
+ end
968
+ if resp.kind_of?(Hash)
969
+ resp.each {|k, v|
970
+ if k!=:code and k!=:message and k!=:data and k!=:'set-cookie' and k!=:header
971
+ resp[:header][k]=v
972
+ end
973
+ }
974
+ resp[:header].each {|k, v|
975
+ resp.delete(k) if resp.has_key?(k)
976
+ }
977
+ end
978
+
979
+ method_s=caller[0].to_s().scan(/:in `(.*)'/).join
980
+ if resp.header.kind_of?(Hash) and (resp.header["content-type"].to_s()=="application/x-deflate" or resp.header[:"content-type"].to_s()=="application/x-deflate") then
981
+ data=Zlib::Inflate.inflate(data)
982
+ end
983
+ encoding_response=""
984
+ if resp.header.kind_of?(Hash) and (resp.header["content-type"].to_s()!="" or resp.header[:"content-type"].to_s()!="") then
985
+ encoding_response=resp.header["content-type"].scan(/;charset=(.*)/i).join if resp.header.has_key?("content-type")
986
+ encoding_response=resp.header[:"content-type"].scan(/;charset=(.*)/i).join if resp.header.has_key?(:"content-type")
987
+ end
988
+ if encoding_response.to_s()=="" then
989
+ encoding_response="UTF-8"
990
+ end
991
+
992
+ if encoding_response.to_s()!="" and encoding_response.to_s().upcase!="UTF-8" then
993
+ data.encode!("UTF-8", encoding_response.to_s())
994
+ end
995
+ if encoding_response!="" and encoding_response.to_s().upcase!="UTF-8" then
996
+ @response[:message]=resp.message.to_s().encode("UTF-8", encoding_response.to_s())
997
+ #todo: response data in here for example is convert into string, verify if that is correct or needs to maintain the original data type (hash, array...)
998
+ resp.each {|key, val| @response[key]=val.to_s().encode("UTF-8", encoding_response.to_s())}
999
+ else
1000
+ @response[:message]=resp.message
1001
+ resp.each {|key, val| @response[key]=val}
1002
+ end
1003
+ if !defined?(Net::HTTP::Post::Multipart) or (defined?(Net::HTTP::Post::Multipart) and !data.kind_of?(Net::HTTP::Post::Multipart))
1004
+ @response[:data]=data
1005
+ else
1006
+ @response[:data]=""
1007
+ end
1008
+
1009
+ @response[:code]=resp.code
1010
+
1011
+ unless @response.nil? then
1012
+ message="\nRESPONSE: \n" + @response[:code].to_s()+ ":" + @response[:message].to_s()
1013
+ if @debug then
1014
+ NiceHttp.last_response=message
1015
+ @response.each {|key, value|
1016
+ if value.to_s()!="" then
1017
+ value_orig=value
1018
+ if key.kind_of?(Symbol) then
1019
+ if key==:code or key==:data or key==:header or key==:message then
1020
+ if key==:data then
1021
+ begin
1022
+ JSON.parse(value_orig)
1023
+ data_s=JSON.pretty_generate(JSON.parse(value_orig))
1024
+ rescue
1025
+ data_s=value_orig
1026
+ end
1027
+ NiceHttp.last_response+="\nresponse." + key.to_s() + " = '" + data_s.gsub("<", "&lt;") + "'\n"
1028
+ if value_orig != value then
1029
+ message+="\nresponse." + key.to_s() + " = '" + value.gsub("<", "&lt;") + "'\n"
1030
+ else
1031
+ message+="\nresponse." + key.to_s() + " = '" + data_s.gsub("<", "&lt;") + "'\n"
1032
+ end
1033
+ else
1034
+ NiceHttp.last_response+="\nresponse." + key.to_s() + " = '" + value.to_s().gsub("<", "&lt;") + "'"
1035
+ message+="\nresponse." + key.to_s() + " = '" + value.to_s().gsub("<", "&lt;") + "'"
1036
+ end
1037
+ else
1038
+ NiceHttp.last_response+="\nresponse[:" + key.to_s() + "] = '" + value.to_s().gsub("<", "&lt;") + "'"
1039
+ message+="\nresponse[:" + key.to_s() + "] = '" + value.to_s().gsub("<", "&lt;") + "'"
1040
+ end
1041
+ elsif !@response.include?(key.to_sym)
1042
+ NiceHttp.last_response+="\nresponse['" + key.to_s() + "'] = '" + value.to_s().gsub("<", "&lt;") + "'"
1043
+ message+="\nresponse['" + key.to_s() + "'] = '" + value.to_s().gsub("<", "&lt;") + "'"
1044
+ end
1045
+ end
1046
+ }
1047
+
1048
+ end
1049
+ @logger.info message
1050
+ if @response.kind_of?(Hash) then
1051
+ if @response.keys.include?(:requestid) then
1052
+ @headers["requestId"]=@response[:requestid]
1053
+ NiceHttp.request_id=@response[:requestid]
1054
+ @logger.info "requestId was found on the response header and it has been added to the headers for the next request"
1055
+ end
1056
+ end
1057
+ end
1058
+
1059
+ if resp[:'set-cookie'].to_s()!="" then
1060
+ if resp.kind_of?(Hash) then #mock_response
1061
+ cookies_to_set=resp[:'set-cookie'].to_s().split(", ")
1062
+ else #Net::Http
1063
+ cookies_to_set=resp.get_fields('set-cookie')
1064
+ end
1065
+ cookies_to_set.each {|cookie|
1066
+ cookie_pair=cookie.split('; ')[0].split("=")
1067
+ cookie_path=cookie.scan(/; path=([^;]+)/i).join
1068
+ @cookies[cookie_path]=Hash.new() unless @cookies.keys.include?(cookie_path)
1069
+ @cookies[cookie_path][cookie_pair[0]]=cookie_pair[1]
1070
+ }
1071
+
1072
+ @logger.info "set-cookie added to Cookie header as required"
1073
+
1074
+ if @headers.has_key?("X-CSRFToken") then
1075
+ csrftoken=resp[:"set-cookie"].to_s().scan(/csrftoken=([\da-z]+);/).join
1076
+ if csrftoken.to_s()!="" then
1077
+ @headers["X-CSRFToken"]=csrftoken
1078
+ @logger.info "X-CSRFToken exists on headers and has been overwritten"
1079
+ end
1080
+ else
1081
+ csrftoken=resp[:"set-cookie"].to_s().scan(/csrftoken=([\da-z]+);/).join
1082
+ if csrftoken.to_s()!="" then
1083
+ @headers["X-CSRFToken"]=csrftoken
1084
+ @logger.info "X-CSRFToken added to header as required"
1085
+ end
1086
+
1087
+ end
1088
+ end
1089
+
1090
+ rescue Exception => stack
1091
+ @logger.fatal stack
1092
+ @logger.fatal "manage_response Error on method #{method_s} "
1093
+ end
1094
+ end
1095
+
1096
+ private :manage_request, :manage_response
1097
+ end
1098
+