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