tshield 0.11.17.0 → 0.13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +32 -2
- data/config/tshield.yml +1 -0
- data/lib/tshield/configuration.rb +10 -0
- data/lib/tshield/controllers/helpers/session_helpers.rb +5 -0
- data/lib/tshield/controllers/requests.rb +12 -2
- data/lib/tshield/controllers/sessions.rb +3 -0
- data/lib/tshield/errors.rb +4 -0
- data/lib/tshield/grpc.rb +4 -5
- data/lib/tshield/grpc/vcr.rb +37 -20
- data/lib/tshield/matching/filters.rb +8 -0
- data/lib/tshield/request.rb +8 -8
- data/lib/tshield/request_matching.rb +1 -0
- data/lib/tshield/request_vcr.rb +36 -23
- data/lib/tshield/sessions.rb +20 -2
- data/lib/tshield/version.rb +2 -2
- data/spec/tshield/configuration_spec.rb +27 -0
- data/spec/tshield/fixtures/matching/example.json +12 -0
- data/spec/tshield/request_matching_spec.rb +12 -0
- data/spec/tshield/request_vcr_spec.rb +49 -0
- data/spec/tshield/sessions_spec.rb +18 -0
- data/tshield.gemspec +5 -6
- metadata +94 -104
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: caa9310473bc1479ad6bc7db7ae67938b269bbd7
|
4
|
+
data.tar.gz: 34de8d7084f0eecb054f2b07b9950ef0dffbf32b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41afa4ac6a4471ea700beaa32ddf4c664f7eeb4f7a61639853b883a5ee0b6dd8f4262f9e14198a186e89cece5bb158669587a00f80dc7bef6bb460a5f6f7c5a3
|
7
|
+
data.tar.gz: ef52b07f2bfc68d8ff0561c0676350493da7b7f16b26f1e61687f13a78929e4ec9659859a396dcb6bb51d5eab8c041cc15cbb2ca92fcecc8a5ed768101a2a7bd
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ TShield is an open source proxy for mocks API responses.
|
|
13
13
|
* REST
|
14
14
|
* SOAP
|
15
15
|
* Session manager to separate multiple scenarios (success, error, sucess variation, ...)
|
16
|
-
|
16
|
+
* gRPC [EXPERIMENTAL]
|
17
17
|
* Lightweight
|
18
18
|
* MIT license
|
19
19
|
|
@@ -68,6 +68,17 @@ domains:
|
|
68
68
|
- /users
|
69
69
|
```
|
70
70
|
|
71
|
+
**Windows Compatibility:** If you need to use Tshield in Windows SO, change the config file and set the windows_compatibility to true.
|
72
|
+
|
73
|
+
Eg:
|
74
|
+
```yaml
|
75
|
+
windows_compatibility: true
|
76
|
+
request:
|
77
|
+
# wait time for real service
|
78
|
+
timeout: 8
|
79
|
+
...
|
80
|
+
```
|
81
|
+
|
71
82
|
## Config options for Pattern Matching
|
72
83
|
|
73
84
|
An example of file to create a stub:
|
@@ -93,6 +104,10 @@ Optional request attributes:
|
|
93
104
|
this stub will be returned if all headers are in request.
|
94
105
|
* **query**: works like headers but use query params.
|
95
106
|
|
107
|
+
Optional response attributes:
|
108
|
+
|
109
|
+
* **delay**: integer that represents time in seconds that the response will be delayed to return
|
110
|
+
|
96
111
|
**Important**: If VCR config conflicts with Matching config Matching will be
|
97
112
|
used. Matching config have priority.
|
98
113
|
|
@@ -155,6 +170,7 @@ To register stub into a session create an object with following attributes:
|
|
155
170
|
"method": "GET",
|
156
171
|
"path": "/matching/example",
|
157
172
|
"response": {
|
173
|
+
"delay": 5,
|
158
174
|
"body": "matching-example-response-in-session",
|
159
175
|
"headers": {},
|
160
176
|
"status": 200
|
@@ -195,6 +211,8 @@ domains:
|
|
195
211
|
- transfer-encoding
|
196
212
|
paths:
|
197
213
|
- /secure
|
214
|
+
delay:
|
215
|
+
'/secure': 10
|
198
216
|
|
199
217
|
'http://localhost:9092':
|
200
218
|
name: 'my-other-service'
|
@@ -205,6 +223,8 @@ domains:
|
|
205
223
|
- transfer-encoding
|
206
224
|
paths:
|
207
225
|
- /users
|
226
|
+
delay:
|
227
|
+
'/users': 5
|
208
228
|
```
|
209
229
|
**request**
|
210
230
|
* **timeout**: wait time for real service in seconds
|
@@ -220,6 +240,7 @@ domains:
|
|
220
240
|
* **filters**: Implementation of before or after filters used in domain requests
|
221
241
|
* **excluded_headers**: <<some_description>>
|
222
242
|
* **paths**: Paths list of all services that will be called. Used to filter what domain will "receive the request"
|
243
|
+
* **delay**: List of times in seconds that the response will be delayed to return for an specific path defined above
|
223
244
|
|
224
245
|
## Manage Sessions
|
225
246
|
|
@@ -250,6 +271,16 @@ _DELETE_ to http://localhost:4567/sessions
|
|
250
271
|
curl -X DELETE \
|
251
272
|
http://localhost:4567/sessions
|
252
273
|
```
|
274
|
+
### Append secondary TShield session
|
275
|
+
**Append session. Secondary sessions will used only for read content in VCR mode, writes will be do in the main session. Append only works if exists a current session setted.**
|
276
|
+
|
277
|
+
_POST_ to http://localhost:4567/sessions?name=<<same_name>>
|
278
|
+
|
279
|
+
```
|
280
|
+
curl -X POST \
|
281
|
+
'http://localhost:4567/sessions/append?name=my_valid'
|
282
|
+
```
|
283
|
+
|
253
284
|
## [Experimental] Config options for gRPC
|
254
285
|
|
255
286
|
```yaml
|
@@ -265,7 +296,6 @@ grpc:
|
|
265
296
|
|
266
297
|
### Not Implemented Yet
|
267
298
|
|
268
|
-
- Sessions
|
269
299
|
- Matching
|
270
300
|
|
271
301
|
### Configuration
|
data/config/tshield.yml
CHANGED
@@ -32,6 +32,7 @@ module TShield
|
|
32
32
|
attr_reader :domains
|
33
33
|
attr_reader :tcp_servers
|
34
34
|
attr_reader :session_path
|
35
|
+
attr_reader :windows_compatibility
|
35
36
|
|
36
37
|
def initialize(attributes)
|
37
38
|
attributes.each { |key, value| instance_variable_set("@#{key}", value) }
|
@@ -103,6 +104,10 @@ module TShield
|
|
103
104
|
session_path || '/sessions'
|
104
105
|
end
|
105
106
|
|
107
|
+
def get_questionmark_char
|
108
|
+
windows_compatibility ? '%3f' : '?'
|
109
|
+
end
|
110
|
+
|
106
111
|
def grpc
|
107
112
|
defaults = { 'port' => 5678, 'proto_dir' => 'proto', 'services' => {} }
|
108
113
|
defaults.merge(@grpc || {})
|
@@ -126,5 +131,10 @@ module TShield
|
|
126
131
|
)
|
127
132
|
raise 'Startup aborted'
|
128
133
|
end
|
134
|
+
|
135
|
+
def get_delay(domain, path)
|
136
|
+
((domains[domain] || {})['delay'] || {})[path] || 0
|
137
|
+
end
|
138
|
+
|
129
139
|
end
|
130
140
|
end
|
@@ -10,6 +10,11 @@ module TShield
|
|
10
10
|
session[:name] if session
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.secondary_sessions(request)
|
14
|
+
session = TShield::Sessions.current(request.ip)
|
15
|
+
session[:secondary_sessions] if session
|
16
|
+
end
|
17
|
+
|
13
18
|
def self.current_session_call(request, callid, method)
|
14
19
|
session = TShield::Sessions.current(request.ip)
|
15
20
|
session ? session[:counter].current(callid, method) : 0
|
@@ -43,6 +43,7 @@ module TShield
|
|
43
43
|
request_content_type = request.content_type
|
44
44
|
|
45
45
|
session_name = TShield::Controllers::Helpers::SessionHelpers.current_session_name(request)
|
46
|
+
secondary_sessions = TShield::Controllers::Helpers::SessionHelpers.secondary_sessions(request)
|
46
47
|
session_call = TShield::Controllers::Helpers::SessionHelpers
|
47
48
|
.current_session_call(request, callid, method)
|
48
49
|
|
@@ -51,6 +52,7 @@ module TShield
|
|
51
52
|
headers: Helpers.build_headers(request),
|
52
53
|
raw_query: request.env['QUERY_STRING'],
|
53
54
|
session: session_name,
|
55
|
+
secondary_sessions: secondary_sessions,
|
54
56
|
call: session_call,
|
55
57
|
ip: request.ip
|
56
58
|
}
|
@@ -67,12 +69,12 @@ module TShield
|
|
67
69
|
unless api_response
|
68
70
|
add_headers(options, path)
|
69
71
|
|
70
|
-
api_response ||= TShield::RequestVCR.new(path, options.clone).
|
72
|
+
api_response ||= TShield::RequestVCR.new(path, options.clone).vcr_response
|
71
73
|
api_response.headers.reject! do |key, _v|
|
72
74
|
configuration.get_excluded_headers(domain(path)).include?(key)
|
73
75
|
end
|
74
76
|
end
|
75
|
-
|
77
|
+
|
76
78
|
logger.info(
|
77
79
|
"original=#{api_response.original} method=#{method} path=#{path} "\
|
78
80
|
"content-type=#{request_content_type} "\
|
@@ -80,6 +82,7 @@ module TShield
|
|
80
82
|
)
|
81
83
|
TShield::Controllers::Helpers::SessionHelpers.update_session_call(request, callid, method)
|
82
84
|
|
85
|
+
delay(path)
|
83
86
|
status api_response.status
|
84
87
|
headers api_response.headers
|
85
88
|
body api_response.body
|
@@ -98,6 +101,13 @@ module TShield
|
|
98
101
|
def domain(path)
|
99
102
|
@domain ||= configuration.get_domain_for(path)
|
100
103
|
end
|
104
|
+
|
105
|
+
def delay(path)
|
106
|
+
delay_in_seconds = configuration.get_delay(domain(path), path) || 0
|
107
|
+
logger.info("Response with delay of #{delay_in_seconds} seconds")
|
108
|
+
sleep delay_in_seconds
|
109
|
+
end
|
110
|
+
|
101
111
|
end
|
102
112
|
end
|
103
113
|
end
|
@@ -23,6 +23,9 @@ module TShield
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.register_post(app, session_path)
|
26
|
+
app.post "#{session_path}/append" do
|
27
|
+
TShield::Sessions.append(request.ip, params[:name]).to_json
|
28
|
+
end
|
26
29
|
app.post session_path do
|
27
30
|
TShield::Sessions.start(request.ip, params[:name]).to_json
|
28
31
|
end
|
data/lib/tshield/grpc.rb
CHANGED
@@ -3,16 +3,15 @@
|
|
3
3
|
require 'grpc'
|
4
4
|
|
5
5
|
require 'tshield/configuration'
|
6
|
-
require 'tshield/sessions'
|
7
6
|
require 'tshield/grpc/vcr'
|
8
7
|
|
9
8
|
module TShield
|
10
9
|
module Grpc
|
11
10
|
module RequestHandler
|
12
11
|
include TShield::Grpc::VCR
|
13
|
-
def handler(method_name, request)
|
12
|
+
def handler(method_name, request, parameters)
|
14
13
|
options = self.class.options
|
15
|
-
handler_in_vcr_mode(method_name, request, options)
|
14
|
+
handler_in_vcr_mode(method_name, request, parameters, options)
|
16
15
|
end
|
17
16
|
end
|
18
17
|
def self.run!
|
@@ -62,8 +61,8 @@ module TShield
|
|
62
61
|
descriptions.each do |service_name, description|
|
63
62
|
puts description
|
64
63
|
method_name = service_name.to_s.underscore.to_sym
|
65
|
-
define_method(method_name) do |request,
|
66
|
-
handler(__method__, request)
|
64
|
+
define_method(method_name) do |request, parameters|
|
65
|
+
handler(__method__, request, parameters)
|
67
66
|
end
|
68
67
|
end
|
69
68
|
end
|
data/lib/tshield/grpc/vcr.rb
CHANGED
@@ -1,65 +1,82 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'tshield/sessions'
|
4
|
+
|
3
5
|
module TShield
|
4
6
|
module Grpc
|
5
7
|
module VCR
|
6
|
-
def handler_in_vcr_mode(method_name, request, options)
|
8
|
+
def handler_in_vcr_mode(method_name, request, parameters, options)
|
9
|
+
parameters.peer =~ /ipv6:\[(.+?)\]|ipv4:(.+?):/
|
10
|
+
peer = Regexp.last_match(1) || Regexp.last_match(2)
|
11
|
+
|
12
|
+
TShield.logger.info("request from #{parameters.peer}")
|
13
|
+
@session = TShield::Sessions.current(peer)
|
14
|
+
|
15
|
+
TShield.logger.info("grpc using session #{@session || 'default'}")
|
7
16
|
module_name = options['module']
|
8
17
|
|
9
|
-
|
10
|
-
|
18
|
+
path = create_destiny(module_name, method_name, request)
|
19
|
+
response = saved_response(path)
|
20
|
+
if response
|
21
|
+
TShield.logger.info("returning saved response for request #{request.to_json} saved into #{hexdigest(request)}")
|
22
|
+
return response
|
23
|
+
end
|
11
24
|
|
25
|
+
TShield.logger.info("calling server to get response for #{request.to_json}")
|
12
26
|
client_class = Object.const_get("#{module_name}::Stub")
|
13
27
|
client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
|
14
28
|
response = client_instance.send(method_name, request)
|
15
|
-
save_request_and_response(request, response)
|
29
|
+
save_request_and_response(path, request, response)
|
16
30
|
response
|
17
31
|
end
|
18
32
|
|
19
|
-
def saved_response(
|
20
|
-
|
21
|
-
response_file = File.join(@complete_path, 'response')
|
33
|
+
def saved_response(path)
|
34
|
+
response_file = File.join(path, 'response')
|
22
35
|
return false unless File.exist? response_file
|
23
36
|
|
24
37
|
content = JSON.parse File.open(response_file).read
|
25
|
-
response_class = File.open(File.join(
|
38
|
+
response_class = File.open(File.join(path, 'response_class')).read.strip
|
26
39
|
Kernel.const_get(response_class).new(content)
|
27
40
|
end
|
28
41
|
|
29
|
-
def save_request_and_response(request, response)
|
30
|
-
save_request(request)
|
31
|
-
save_response(response)
|
42
|
+
def save_request_and_response(path, request, response)
|
43
|
+
save_request(path, request)
|
44
|
+
save_response(path, response)
|
32
45
|
end
|
33
46
|
|
34
|
-
def save_request(request)
|
35
|
-
file = File.open(File.join(
|
47
|
+
def save_request(path, request)
|
48
|
+
file = File.open(File.join(path, 'original_request'), 'w')
|
36
49
|
file.puts request.to_json
|
37
50
|
file.close
|
38
51
|
end
|
39
52
|
|
40
|
-
def save_response(response)
|
41
|
-
file = File.open(File.join(
|
53
|
+
def save_response(path, response)
|
54
|
+
file = File.open(File.join(path, 'response'), 'w')
|
42
55
|
file.puts response.to_json
|
43
56
|
file.close
|
44
57
|
|
45
|
-
response_class = File.open(File.join(
|
58
|
+
response_class = File.open(File.join(path, 'response_class'), 'w')
|
46
59
|
response_class.puts response.class.to_s
|
47
60
|
response_class.close
|
48
61
|
end
|
49
62
|
|
50
63
|
def complete_path(module_name, method_name, request)
|
51
|
-
|
52
|
-
|
53
|
-
|
64
|
+
@session_name = (@session || {})[:name]
|
65
|
+
path = ['requests', 'grpc', @session_name, module_name, method_name.to_s, hexdigest(request)].compact
|
66
|
+
path
|
54
67
|
end
|
55
68
|
|
56
69
|
def create_destiny(module_name, method_name, request)
|
57
70
|
current_path = []
|
58
|
-
|
71
|
+
|
72
|
+
path = complete_path(module_name, method_name, request)
|
73
|
+
TShield.logger.info("using path #{path}")
|
74
|
+
path.each do |path|
|
59
75
|
current_path << path
|
60
76
|
destiny = File.join current_path
|
61
77
|
Dir.mkdir destiny unless File.exist? destiny
|
62
78
|
end
|
79
|
+
path
|
63
80
|
end
|
64
81
|
|
65
82
|
def hexdigest(request)
|
@@ -8,6 +8,14 @@ module TShield
|
|
8
8
|
result = filter_stubs(stubs[@options[:session]] || {})
|
9
9
|
return result if result
|
10
10
|
|
11
|
+
find_in_secondary_sessions(stubs, @options[:secondary_sessions] || [])
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_in_secondary_sessions(stubs, sessions)
|
15
|
+
sessions.each do |session|
|
16
|
+
result = filter_stubs(stubs[session] || {})
|
17
|
+
return result if result
|
18
|
+
end
|
11
19
|
filter_stubs(stubs[DEFAULT_SESSION] || {}) unless @options[:session] == DEFAULT_SESSION
|
12
20
|
end
|
13
21
|
|
data/lib/tshield/request.rb
CHANGED
@@ -13,8 +13,8 @@ module TShield
|
|
13
13
|
|
14
14
|
protected
|
15
15
|
|
16
|
-
def session_destiny(request_path)
|
17
|
-
session = @options[:session]
|
16
|
+
def session_destiny(request_path, current_session = nil)
|
17
|
+
session = current_session || @options[:session]
|
18
18
|
return request_path unless session
|
19
19
|
|
20
20
|
request_path = File.join(request_path, session)
|
@@ -22,19 +22,19 @@ module TShield
|
|
22
22
|
request_path
|
23
23
|
end
|
24
24
|
|
25
|
-
def content_destiny
|
26
|
-
"#{destiny}.content"
|
25
|
+
def content_destiny(current_session = nil)
|
26
|
+
"#{destiny(current_session)}.content"
|
27
27
|
end
|
28
28
|
|
29
|
-
def headers_destiny
|
30
|
-
"#{destiny}.json"
|
29
|
+
def headers_destiny(current_session = nil)
|
30
|
+
"#{destiny(current_session)}.json"
|
31
31
|
end
|
32
32
|
|
33
|
-
def destiny
|
33
|
+
def destiny(current_session = nil)
|
34
34
|
request_path = File.join('requests')
|
35
35
|
Dir.mkdir(request_path) unless File.exist?(request_path)
|
36
36
|
|
37
|
-
request_path = session_destiny(request_path)
|
37
|
+
request_path = session_destiny(request_path, current_session)
|
38
38
|
|
39
39
|
name_path = File.join(request_path, name)
|
40
40
|
Dir.mkdir(name_path) unless File.exist?(name_path)
|
data/lib/tshield/request_vcr.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'httparty'
|
4
4
|
require 'json'
|
5
|
-
require 'byebug'
|
6
5
|
|
7
6
|
require 'digest/sha1'
|
8
7
|
|
9
8
|
require 'tshield/configuration'
|
9
|
+
require 'tshield/logger'
|
10
10
|
require 'tshield/options'
|
11
11
|
require 'tshield/request'
|
12
12
|
require 'tshield/response'
|
@@ -14,6 +14,8 @@ require 'tshield/response'
|
|
14
14
|
module TShield
|
15
15
|
# Module to write and read saved responses
|
16
16
|
class RequestVCR < TShield::Request
|
17
|
+
attr_reader :vcr_response
|
18
|
+
|
17
19
|
def initialize(path, options = {})
|
18
20
|
super()
|
19
21
|
@path = path
|
@@ -35,27 +37,31 @@ module TShield
|
|
35
37
|
_method, @url, @options = filter.new.filter(method, @url, @options)
|
36
38
|
end
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
in_session = find_in_sessions
|
41
|
+
if in_session
|
42
|
+
# TODO: create concept of global session in vcr
|
43
|
+
in_session = nil if in_session == 'global'
|
44
|
+
@vcr_response = response(in_session)
|
45
|
+
@vcr_response.original = false
|
41
46
|
else
|
47
|
+
TShield.logger.info("calling original service for request with options #{@options}")
|
42
48
|
raw = HTTParty.send(method.to_s, @url, @options)
|
43
49
|
|
44
50
|
original_response = save(raw)
|
45
51
|
original_response.original = true
|
46
|
-
|
52
|
+
@vcr_response = original_response
|
47
53
|
end
|
48
54
|
|
49
55
|
configuration.get_after_filters(domain).each do |filter|
|
50
|
-
|
56
|
+
@vcr_response = filter.new.filter(@vcr_response)
|
51
57
|
end
|
52
|
-
resp
|
53
58
|
end
|
54
59
|
|
55
|
-
def response
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
def response(session)
|
61
|
+
response_content = saved_content(session)
|
62
|
+
TShield::Response.new(response_content['body'],
|
63
|
+
response_content['headers'] || [],
|
64
|
+
response_content['status'] || 200)
|
59
65
|
end
|
60
66
|
|
61
67
|
private
|
@@ -89,20 +95,27 @@ module TShield
|
|
89
95
|
TShield::Response.new(raw_response.body, headers, raw_response.code)
|
90
96
|
end
|
91
97
|
|
92
|
-
def saved_content
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
@saved_content['body'] = File.open(content_destiny).read unless @saved_content['body']
|
97
|
-
@saved_content
|
98
|
+
def saved_content(session)
|
99
|
+
content = JSON.parse(File.open(headers_destiny(session)).read)
|
100
|
+
content['body'] = File.open(content_destiny(session)).read unless content['body']
|
101
|
+
content
|
98
102
|
end
|
99
103
|
|
100
|
-
def file_exists
|
101
|
-
File.exist?(content_destiny)
|
104
|
+
def file_exists(session)
|
105
|
+
File.exist?(content_destiny(session))
|
102
106
|
end
|
103
107
|
|
104
|
-
def
|
105
|
-
|
108
|
+
def find_in_sessions
|
109
|
+
in_session = nil
|
110
|
+
|
111
|
+
([@options[:session]] + (@options[:secondary_sessions] || [])).each do |session|
|
112
|
+
if file_exists(session) && configuration.cache_request?(domain)
|
113
|
+
in_session = (session || 'global')
|
114
|
+
break
|
115
|
+
end
|
116
|
+
TShield.logger.info("saved response not found in #{session}")
|
117
|
+
end
|
118
|
+
in_session
|
106
119
|
end
|
107
120
|
|
108
121
|
def key
|
@@ -127,9 +140,9 @@ module TShield
|
|
127
140
|
if url.size > 225
|
128
141
|
path = url.gsub(/(\?.*)/, '')
|
129
142
|
params = Digest::SHA1.hexdigest Regexp.last_match(1)
|
130
|
-
"#{path.gsub(%r{/}, '-').gsub(/^-/, '')}
|
143
|
+
"#{path.gsub(%r{/}, '-').gsub(/^-/, '')}#{configuration.get_questionmark_char}#{params}"
|
131
144
|
else
|
132
|
-
url.gsub(%r{/}, '-').gsub(/^-/, '')
|
145
|
+
url.gsub(%r{/}, '-').gsub(/^-/, '').gsub('?', configuration.get_questionmark_char)
|
133
146
|
end
|
134
147
|
end
|
135
148
|
end
|
data/lib/tshield/sessions.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'tshield/logger'
|
4
4
|
require 'tshield/counter'
|
5
|
+
require 'tshield/errors'
|
5
6
|
|
6
7
|
module TShield
|
7
8
|
# Manage sessions
|
@@ -9,17 +10,34 @@ module TShield
|
|
9
10
|
# Start and stop session for ip
|
10
11
|
module Sessions
|
11
12
|
def self.start(ip, name)
|
12
|
-
|
13
|
+
TShield.logger.info("starting session #{name} for ip #{normalize_ip(ip)}")
|
14
|
+
sessions[normalize_ip(ip)] = {
|
15
|
+
name: name,
|
16
|
+
counter: TShield::Counter.new,
|
17
|
+
secondary_sessions: []
|
18
|
+
}
|
13
19
|
end
|
14
20
|
|
15
21
|
def self.stop(ip)
|
22
|
+
TShield.logger.info("stoping session for ip #{normalize_ip(ip)}")
|
16
23
|
sessions[normalize_ip(ip)] = nil
|
17
24
|
end
|
18
25
|
|
19
26
|
def self.current(ip)
|
27
|
+
TShield.logger.info("fetching session for ip #{normalize_ip(ip)}")
|
20
28
|
sessions[normalize_ip(ip)]
|
21
29
|
end
|
22
30
|
|
31
|
+
def self.append(ip, name)
|
32
|
+
TShield.logger.info("appeding session #{name} for ip #{normalize_ip(ip)}")
|
33
|
+
|
34
|
+
current_session = sessions[normalize_ip(ip)]
|
35
|
+
raise AppendSessionWithoutMainSessionError, "not found main session for #{ip}" unless current_session
|
36
|
+
|
37
|
+
current_session[:secondary_sessions] << name
|
38
|
+
current_session
|
39
|
+
end
|
40
|
+
|
23
41
|
def self.sessions
|
24
42
|
@sessions ||= {}
|
25
43
|
end
|
data/lib/tshield/version.rb
CHANGED
@@ -64,6 +64,33 @@ describe TShield::Configuration do
|
|
64
64
|
expect(@configuration.get_domain_for('/api/four')).to be_nil
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
describe 'SO compatibility' do
|
69
|
+
it 'should be compatible with windows when configuration is true' do
|
70
|
+
allow(YAML).to receive(:safe_load).and_return({:windows_compatibility => true })
|
71
|
+
TShield::Configuration.clear
|
72
|
+
@configuration = TShield::Configuration.singleton
|
73
|
+
|
74
|
+
expect(@configuration.get_questionmark_char).to eq('%3f')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should be compatible with Unix when configuration is false' do
|
78
|
+
allow(YAML).to receive(:safe_load).and_return({:windows_compatibility => false })
|
79
|
+
TShield::Configuration.clear
|
80
|
+
@configuration = TShield::Configuration.singleton
|
81
|
+
|
82
|
+
expect(@configuration.get_questionmark_char).to eq('?')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should be compatible with Unix when configuration is missing' do
|
86
|
+
allow(YAML).to receive(:safe_load).and_return({})
|
87
|
+
TShield::Configuration.clear
|
88
|
+
@configuration = TShield::Configuration.singleton
|
89
|
+
|
90
|
+
expect(@configuration.get_questionmark_char).to eq('?')
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
67
94
|
end
|
68
95
|
context 'on config not exist' do
|
69
96
|
before :each do
|
@@ -99,5 +99,17 @@
|
|
99
99
|
"body": "body content in session"
|
100
100
|
}
|
101
101
|
}]
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"session": "second-session",
|
105
|
+
"stubs": [{
|
106
|
+
"method": "GET",
|
107
|
+
"path": "/matching/second-example",
|
108
|
+
"response": {
|
109
|
+
"status": 200,
|
110
|
+
"headers": {},
|
111
|
+
"body": "body content in second-session"
|
112
|
+
}
|
113
|
+
}]
|
102
114
|
}
|
103
115
|
]
|
@@ -235,6 +235,18 @@ describe TShield::RequestMatching do
|
|
235
235
|
expect(@response.headers).to eql({})
|
236
236
|
expect(@response.status).to eql(201)
|
237
237
|
end
|
238
|
+
context 'with secondary session' do
|
239
|
+
it 'should return response object from session settings' do
|
240
|
+
@request_matching = TShield::RequestMatching.new('/matching/second-example',
|
241
|
+
method: 'GET',
|
242
|
+
session: 'a-session',
|
243
|
+
secondary_sessions: ['second-session'])
|
244
|
+
@response = @request_matching.match_request
|
245
|
+
expect(@response.body).to eql('body content in second-session')
|
246
|
+
expect(@response.headers).to eql({})
|
247
|
+
expect(@response.status).to eql(200)
|
248
|
+
end
|
249
|
+
end
|
238
250
|
end
|
239
251
|
end
|
240
252
|
end
|
@@ -62,6 +62,8 @@ describe TShield::RequestVCR do
|
|
62
62
|
}
|
63
63
|
)
|
64
64
|
|
65
|
+
allow(@configuration).to receive(:get_questionmark_char).and_return('?')
|
66
|
+
|
65
67
|
allow(HTTParty).to receive(:send).and_return(RawResponse.new)
|
66
68
|
file_double = double
|
67
69
|
|
@@ -83,6 +85,53 @@ describe TShield::RequestVCR do
|
|
83
85
|
method: 'GET',
|
84
86
|
call: 0
|
85
87
|
end
|
88
|
+
|
89
|
+
it 'should create response directory in windows standard' do
|
90
|
+
|
91
|
+
allow(@configuration).to receive(:domains).and_return(
|
92
|
+
'example.org' => {
|
93
|
+
'skip_query_params' => []
|
94
|
+
}
|
95
|
+
)
|
96
|
+
|
97
|
+
allow(@configuration).to receive(:get_questionmark_char).and_return('%3f')
|
98
|
+
|
99
|
+
allow(HTTParty).to receive(:send).and_return(RawResponse.new)
|
100
|
+
file_double = double
|
101
|
+
|
102
|
+
allow(File).to receive(:join)
|
103
|
+
.with('./requests/example.org', '%3fparam=value')
|
104
|
+
.and_return('./requests/example.org/%3fparam=value')
|
105
|
+
allow(File).to receive(:join)
|
106
|
+
.with('./requests/example.org/%3fparam=value', 'get')
|
107
|
+
.and_return('./requests/example.org/%3fparam=value/get')
|
108
|
+
allow(File).to receive(:join)
|
109
|
+
.with('./requests/example.org/%3fparam=value/get', '0')
|
110
|
+
.and_return('./requests/example.org/%3fparam=value/get/0')
|
111
|
+
|
112
|
+
allow(file_double).to receive(:read).and_return('{}')
|
113
|
+
|
114
|
+
expect(File).to receive('open')
|
115
|
+
.with('./requests/example.org/%3fparam=value/get/0.content', 'w')
|
116
|
+
.and_return(file_double)
|
117
|
+
|
118
|
+
expect(File).to receive('open')
|
119
|
+
.with('./requests/example.org/%3fparam=value/get/0.json', 'w')
|
120
|
+
.and_return(file_double)
|
121
|
+
|
122
|
+
expect(file_double).to receive(:write).ordered.with('this is the body')
|
123
|
+
expect(file_double).to receive(:write)
|
124
|
+
.with("{\n \"status\": 200,\n \"headers\": {\n }\n}")
|
125
|
+
expect(file_double).to receive(:close)
|
126
|
+
expect(file_double).to receive(:close)
|
127
|
+
|
128
|
+
TShield::RequestVCR.new '/',
|
129
|
+
raw_query: 'param=value',
|
130
|
+
method: 'GET',
|
131
|
+
call: 0
|
132
|
+
end
|
133
|
+
|
134
|
+
|
86
135
|
end
|
87
136
|
end
|
88
137
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tshield/sessions'
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
describe TShield::Sessions do
|
7
|
+
context 'on append session' do
|
8
|
+
it 'should raise error if not has a main session' do
|
9
|
+
expect { TShield::Sessions.append 'ip', 'secondary-session' }
|
10
|
+
.to raise_error(AppendSessionWithoutMainSessionError)
|
11
|
+
end
|
12
|
+
it 'should append if has main session' do
|
13
|
+
TShield::Sessions.start 'ip', 'main-session'
|
14
|
+
result = TShield::Sessions.append 'ip', 'secondary-session'
|
15
|
+
expect(result[:secondary_sessions]).to include('secondary-session')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/tshield.gemspec
CHANGED
@@ -22,19 +22,18 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.test_files = Dir['spec/**/*']
|
24
24
|
|
25
|
-
s.required_ruby_version = '>= 2.
|
25
|
+
s.required_ruby_version = '>= 2.4'
|
26
26
|
|
27
|
-
s.add_dependency('byebug', '~> 11.0', '>= 11.0.1')
|
28
27
|
s.add_dependency('grpc', '~> 1.28', '>= 1.28.0')
|
29
28
|
s.add_dependency('grpc-tools', '~> 1.28', '>= 1.28.0')
|
30
29
|
s.add_dependency('httparty', '~> 0.14', '>= 0.14.0')
|
31
30
|
s.add_dependency('json', '~> 2.0', '>= 2.0')
|
32
31
|
s.add_dependency('puma', '~> 4.3', '>= 4.3.3')
|
33
|
-
s.add_dependency('sinatra', '~> 1
|
32
|
+
s.add_dependency('sinatra', '~> 2.1', '>= 2.1.0')
|
34
33
|
s.add_dependency('sinatra-cross_origin', '~> 0.4.0', '>= 0.4')
|
35
|
-
s.add_development_dependency('coveralls')
|
34
|
+
s.add_development_dependency('coveralls', '~> 0.8', '>= 0.8.23')
|
36
35
|
s.add_development_dependency('cucumber', '~> 3.1', '>= 3.1.2')
|
37
|
-
s.add_development_dependency('guard', '~> 2.
|
36
|
+
s.add_development_dependency('guard', '~> 2.16', '>= 2.16.2')
|
38
37
|
s.add_development_dependency('guard-rspec', '~> 4.7', '>= 4.7.3')
|
39
38
|
s.add_development_dependency('rake', '>= 10.0', '~> 13.0')
|
40
39
|
s.add_development_dependency('rdoc', '~> 6.0', '>= 6.0')
|
@@ -42,6 +41,6 @@ Gem::Specification.new do |s|
|
|
42
41
|
s.add_development_dependency('rspec', '~> 3.5', '>= 3.5.0')
|
43
42
|
s.add_development_dependency('rubocop', '~> 0.73.0', '>= 0.73.0')
|
44
43
|
s.add_development_dependency('rubocop-rails', '~> 2.2.0', '>= 2.2.1')
|
45
|
-
s.add_development_dependency('simplecov', '~> 0.
|
44
|
+
s.add_development_dependency('simplecov', '~> 0.16', '>= 0.16.1')
|
46
45
|
s.add_development_dependency('webmock', '~> 2.1', '>= 2.1.0')
|
47
46
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tshield
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Diego Rubin
|
@@ -9,106 +9,86 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-11-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: grpc
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '1.28'
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 1.28.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - "~>"
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: '11.0'
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 11.0.1
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: grpc
|
36
|
-
requirement: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 1.28.0
|
41
28
|
- - "~>"
|
42
29
|
- !ruby/object:Gem::Version
|
43
30
|
version: '1.28'
|
44
|
-
type: :runtime
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: !ruby/object:Gem::Requirement
|
47
|
-
requirements:
|
48
31
|
- - ">="
|
49
32
|
- !ruby/object:Gem::Version
|
50
33
|
version: 1.28.0
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '1.28'
|
54
34
|
- !ruby/object:Gem::Dependency
|
55
35
|
name: grpc-tools
|
56
36
|
requirement: !ruby/object:Gem::Requirement
|
57
37
|
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: 1.28.0
|
61
38
|
- - "~>"
|
62
39
|
- !ruby/object:Gem::Version
|
63
40
|
version: '1.28'
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.28.0
|
64
44
|
type: :runtime
|
65
45
|
prerelease: false
|
66
46
|
version_requirements: !ruby/object:Gem::Requirement
|
67
47
|
requirements:
|
68
|
-
- - ">="
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: 1.28.0
|
71
48
|
- - "~>"
|
72
49
|
- !ruby/object:Gem::Version
|
73
50
|
version: '1.28'
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.28.0
|
74
54
|
- !ruby/object:Gem::Dependency
|
75
55
|
name: httparty
|
76
56
|
requirement: !ruby/object:Gem::Requirement
|
77
57
|
requirements:
|
78
|
-
- - ">="
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: 0.14.0
|
81
58
|
- - "~>"
|
82
59
|
- !ruby/object:Gem::Version
|
83
60
|
version: '0.14'
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.14.0
|
84
64
|
type: :runtime
|
85
65
|
prerelease: false
|
86
66
|
version_requirements: !ruby/object:Gem::Requirement
|
87
67
|
requirements:
|
88
|
-
- - ">="
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: 0.14.0
|
91
68
|
- - "~>"
|
92
69
|
- !ruby/object:Gem::Version
|
93
70
|
version: '0.14'
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.14.0
|
94
74
|
- !ruby/object:Gem::Dependency
|
95
75
|
name: json
|
96
76
|
requirement: !ruby/object:Gem::Requirement
|
97
77
|
requirements:
|
98
|
-
- - "
|
78
|
+
- - "~>"
|
99
79
|
- !ruby/object:Gem::Version
|
100
80
|
version: '2.0'
|
101
|
-
- - "
|
81
|
+
- - ">="
|
102
82
|
- !ruby/object:Gem::Version
|
103
83
|
version: '2.0'
|
104
84
|
type: :runtime
|
105
85
|
prerelease: false
|
106
86
|
version_requirements: !ruby/object:Gem::Requirement
|
107
87
|
requirements:
|
108
|
-
- - "
|
88
|
+
- - "~>"
|
109
89
|
- !ruby/object:Gem::Version
|
110
90
|
version: '2.0'
|
111
|
-
- - "
|
91
|
+
- - ">="
|
112
92
|
- !ruby/object:Gem::Version
|
113
93
|
version: '2.0'
|
114
94
|
- !ruby/object:Gem::Dependency
|
@@ -135,56 +115,62 @@ dependencies:
|
|
135
115
|
name: sinatra
|
136
116
|
requirement: !ruby/object:Gem::Requirement
|
137
117
|
requirements:
|
138
|
-
- - ">="
|
139
|
-
- !ruby/object:Gem::Version
|
140
|
-
version: 1.4.0
|
141
118
|
- - "~>"
|
142
119
|
- !ruby/object:Gem::Version
|
143
|
-
version: '1
|
120
|
+
version: '2.1'
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 2.1.0
|
144
124
|
type: :runtime
|
145
125
|
prerelease: false
|
146
126
|
version_requirements: !ruby/object:Gem::Requirement
|
147
127
|
requirements:
|
148
|
-
- - ">="
|
149
|
-
- !ruby/object:Gem::Version
|
150
|
-
version: 1.4.0
|
151
128
|
- - "~>"
|
152
129
|
- !ruby/object:Gem::Version
|
153
|
-
version: '1
|
130
|
+
version: '2.1'
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 2.1.0
|
154
134
|
- !ruby/object:Gem::Dependency
|
155
135
|
name: sinatra-cross_origin
|
156
136
|
requirement: !ruby/object:Gem::Requirement
|
157
137
|
requirements:
|
158
|
-
- - ">="
|
159
|
-
- !ruby/object:Gem::Version
|
160
|
-
version: '0.4'
|
161
138
|
- - "~>"
|
162
139
|
- !ruby/object:Gem::Version
|
163
140
|
version: 0.4.0
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0.4'
|
164
144
|
type: :runtime
|
165
145
|
prerelease: false
|
166
146
|
version_requirements: !ruby/object:Gem::Requirement
|
167
147
|
requirements:
|
168
|
-
- - ">="
|
169
|
-
- !ruby/object:Gem::Version
|
170
|
-
version: '0.4'
|
171
148
|
- - "~>"
|
172
149
|
- !ruby/object:Gem::Version
|
173
150
|
version: 0.4.0
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0.4'
|
174
154
|
- !ruby/object:Gem::Dependency
|
175
155
|
name: coveralls
|
176
156
|
requirement: !ruby/object:Gem::Requirement
|
177
157
|
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0.8'
|
178
161
|
- - ">="
|
179
162
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
163
|
+
version: 0.8.23
|
181
164
|
type: :development
|
182
165
|
prerelease: false
|
183
166
|
version_requirements: !ruby/object:Gem::Requirement
|
184
167
|
requirements:
|
168
|
+
- - "~>"
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0.8'
|
185
171
|
- - ">="
|
186
172
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
173
|
+
version: 0.8.23
|
188
174
|
- !ruby/object:Gem::Dependency
|
189
175
|
name: cucumber
|
190
176
|
requirement: !ruby/object:Gem::Requirement
|
@@ -209,22 +195,22 @@ dependencies:
|
|
209
195
|
name: guard
|
210
196
|
requirement: !ruby/object:Gem::Requirement
|
211
197
|
requirements:
|
212
|
-
- - ">="
|
213
|
-
- !ruby/object:Gem::Version
|
214
|
-
version: 2.15.0
|
215
198
|
- - "~>"
|
216
199
|
- !ruby/object:Gem::Version
|
217
|
-
version: '2.
|
200
|
+
version: '2.16'
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: 2.16.2
|
218
204
|
type: :development
|
219
205
|
prerelease: false
|
220
206
|
version_requirements: !ruby/object:Gem::Requirement
|
221
207
|
requirements:
|
222
|
-
- - ">="
|
223
|
-
- !ruby/object:Gem::Version
|
224
|
-
version: 2.15.0
|
225
208
|
- - "~>"
|
226
209
|
- !ruby/object:Gem::Version
|
227
|
-
version: '2.
|
210
|
+
version: '2.16'
|
211
|
+
- - ">="
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: 2.16.2
|
228
214
|
- !ruby/object:Gem::Dependency
|
229
215
|
name: guard-rspec
|
230
216
|
requirement: !ruby/object:Gem::Requirement
|
@@ -269,80 +255,80 @@ dependencies:
|
|
269
255
|
name: rdoc
|
270
256
|
requirement: !ruby/object:Gem::Requirement
|
271
257
|
requirements:
|
272
|
-
- - "
|
258
|
+
- - "~>"
|
273
259
|
- !ruby/object:Gem::Version
|
274
260
|
version: '6.0'
|
275
|
-
- - "
|
261
|
+
- - ">="
|
276
262
|
- !ruby/object:Gem::Version
|
277
263
|
version: '6.0'
|
278
264
|
type: :development
|
279
265
|
prerelease: false
|
280
266
|
version_requirements: !ruby/object:Gem::Requirement
|
281
267
|
requirements:
|
282
|
-
- - "
|
268
|
+
- - "~>"
|
283
269
|
- !ruby/object:Gem::Version
|
284
270
|
version: '6.0'
|
285
|
-
- - "
|
271
|
+
- - ">="
|
286
272
|
- !ruby/object:Gem::Version
|
287
273
|
version: '6.0'
|
288
274
|
- !ruby/object:Gem::Dependency
|
289
275
|
name: reek
|
290
276
|
requirement: !ruby/object:Gem::Requirement
|
291
277
|
requirements:
|
292
|
-
- - "
|
278
|
+
- - "~>"
|
293
279
|
- !ruby/object:Gem::Version
|
294
280
|
version: 5.4.0
|
295
|
-
- - "
|
281
|
+
- - ">="
|
296
282
|
- !ruby/object:Gem::Version
|
297
283
|
version: 5.4.0
|
298
284
|
type: :development
|
299
285
|
prerelease: false
|
300
286
|
version_requirements: !ruby/object:Gem::Requirement
|
301
287
|
requirements:
|
302
|
-
- - "
|
288
|
+
- - "~>"
|
303
289
|
- !ruby/object:Gem::Version
|
304
290
|
version: 5.4.0
|
305
|
-
- - "
|
291
|
+
- - ">="
|
306
292
|
- !ruby/object:Gem::Version
|
307
293
|
version: 5.4.0
|
308
294
|
- !ruby/object:Gem::Dependency
|
309
295
|
name: rspec
|
310
296
|
requirement: !ruby/object:Gem::Requirement
|
311
297
|
requirements:
|
312
|
-
- - ">="
|
313
|
-
- !ruby/object:Gem::Version
|
314
|
-
version: 3.5.0
|
315
298
|
- - "~>"
|
316
299
|
- !ruby/object:Gem::Version
|
317
300
|
version: '3.5'
|
301
|
+
- - ">="
|
302
|
+
- !ruby/object:Gem::Version
|
303
|
+
version: 3.5.0
|
318
304
|
type: :development
|
319
305
|
prerelease: false
|
320
306
|
version_requirements: !ruby/object:Gem::Requirement
|
321
307
|
requirements:
|
322
|
-
- - ">="
|
323
|
-
- !ruby/object:Gem::Version
|
324
|
-
version: 3.5.0
|
325
308
|
- - "~>"
|
326
309
|
- !ruby/object:Gem::Version
|
327
310
|
version: '3.5'
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: 3.5.0
|
328
314
|
- !ruby/object:Gem::Dependency
|
329
315
|
name: rubocop
|
330
316
|
requirement: !ruby/object:Gem::Requirement
|
331
317
|
requirements:
|
332
|
-
- - "
|
318
|
+
- - "~>"
|
333
319
|
- !ruby/object:Gem::Version
|
334
320
|
version: 0.73.0
|
335
|
-
- - "
|
321
|
+
- - ">="
|
336
322
|
- !ruby/object:Gem::Version
|
337
323
|
version: 0.73.0
|
338
324
|
type: :development
|
339
325
|
prerelease: false
|
340
326
|
version_requirements: !ruby/object:Gem::Requirement
|
341
327
|
requirements:
|
342
|
-
- - "
|
328
|
+
- - "~>"
|
343
329
|
- !ruby/object:Gem::Version
|
344
330
|
version: 0.73.0
|
345
|
-
- - "
|
331
|
+
- - ">="
|
346
332
|
- !ruby/object:Gem::Version
|
347
333
|
version: 0.73.0
|
348
334
|
- !ruby/object:Gem::Dependency
|
@@ -369,42 +355,42 @@ dependencies:
|
|
369
355
|
name: simplecov
|
370
356
|
requirement: !ruby/object:Gem::Requirement
|
371
357
|
requirements:
|
372
|
-
- - ">="
|
373
|
-
- !ruby/object:Gem::Version
|
374
|
-
version: 0.12.0
|
375
358
|
- - "~>"
|
376
359
|
- !ruby/object:Gem::Version
|
377
|
-
version: '0.
|
360
|
+
version: '0.16'
|
361
|
+
- - ">="
|
362
|
+
- !ruby/object:Gem::Version
|
363
|
+
version: 0.16.1
|
378
364
|
type: :development
|
379
365
|
prerelease: false
|
380
366
|
version_requirements: !ruby/object:Gem::Requirement
|
381
367
|
requirements:
|
382
|
-
- - ">="
|
383
|
-
- !ruby/object:Gem::Version
|
384
|
-
version: 0.12.0
|
385
368
|
- - "~>"
|
386
369
|
- !ruby/object:Gem::Version
|
387
|
-
version: '0.
|
370
|
+
version: '0.16'
|
371
|
+
- - ">="
|
372
|
+
- !ruby/object:Gem::Version
|
373
|
+
version: 0.16.1
|
388
374
|
- !ruby/object:Gem::Dependency
|
389
375
|
name: webmock
|
390
376
|
requirement: !ruby/object:Gem::Requirement
|
391
377
|
requirements:
|
392
|
-
- - ">="
|
393
|
-
- !ruby/object:Gem::Version
|
394
|
-
version: 2.1.0
|
395
378
|
- - "~>"
|
396
379
|
- !ruby/object:Gem::Version
|
397
380
|
version: '2.1'
|
381
|
+
- - ">="
|
382
|
+
- !ruby/object:Gem::Version
|
383
|
+
version: 2.1.0
|
398
384
|
type: :development
|
399
385
|
prerelease: false
|
400
386
|
version_requirements: !ruby/object:Gem::Requirement
|
401
387
|
requirements:
|
402
|
-
- - ">="
|
403
|
-
- !ruby/object:Gem::Version
|
404
|
-
version: 2.1.0
|
405
388
|
- - "~>"
|
406
389
|
- !ruby/object:Gem::Version
|
407
390
|
version: '2.1'
|
391
|
+
- - ">="
|
392
|
+
- !ruby/object:Gem::Version
|
393
|
+
version: 2.1.0
|
408
394
|
description: Proxy for mocks API responses
|
409
395
|
email: rubin.diego@gmail.com
|
410
396
|
executables:
|
@@ -426,6 +412,7 @@ files:
|
|
426
412
|
- lib/tshield/controllers/requests.rb
|
427
413
|
- lib/tshield/controllers/sessions.rb
|
428
414
|
- lib/tshield/counter.rb
|
415
|
+
- lib/tshield/errors.rb
|
429
416
|
- lib/tshield/extensions/string_extensions.rb
|
430
417
|
- lib/tshield/grpc.rb
|
431
418
|
- lib/tshield/grpc/vcr.rb
|
@@ -452,6 +439,7 @@ files:
|
|
452
439
|
- spec/tshield/options_spec.rb
|
453
440
|
- spec/tshield/request_matching_spec.rb
|
454
441
|
- spec/tshield/request_vcr_spec.rb
|
442
|
+
- spec/tshield/sessions_spec.rb
|
455
443
|
- tshield.gemspec
|
456
444
|
homepage: https://github.com/diegorubin/tshield
|
457
445
|
licenses:
|
@@ -465,28 +453,30 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
465
453
|
requirements:
|
466
454
|
- - ">="
|
467
455
|
- !ruby/object:Gem::Version
|
468
|
-
version: '2.
|
456
|
+
version: '2.4'
|
469
457
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
470
458
|
requirements:
|
471
459
|
- - ">="
|
472
460
|
- !ruby/object:Gem::Version
|
473
461
|
version: '0'
|
474
462
|
requirements: []
|
475
|
-
|
463
|
+
rubyforge_project:
|
464
|
+
rubygems_version: 2.6.14.4
|
476
465
|
signing_key:
|
477
466
|
specification_version: 4
|
478
467
|
summary: Proxy for mocks API responses
|
479
468
|
test_files:
|
480
469
|
- spec/spec_helper.rb
|
481
|
-
- spec/tshield/request_matching_spec.rb
|
482
|
-
- spec/tshield/grpc_spec.rb
|
483
|
-
- spec/tshield/configuration_spec.rb
|
484
470
|
- spec/tshield/request_vcr_spec.rb
|
471
|
+
- spec/tshield/sessions_spec.rb
|
485
472
|
- spec/tshield/controllers/requests_spec.rb
|
473
|
+
- spec/tshield/request_matching_spec.rb
|
474
|
+
- spec/tshield/grpc_spec.rb
|
486
475
|
- spec/tshield/options_spec.rb
|
487
|
-
- spec/tshield/after_filter_spec.rb
|
488
|
-
- spec/tshield/fixtures/matching/example.json
|
489
476
|
- spec/tshield/fixtures/proto/test_services_pb.rb
|
490
477
|
- spec/tshield/fixtures/filters/example_filter.rb
|
478
|
+
- spec/tshield/fixtures/matching/example.json
|
491
479
|
- spec/tshield/fixtures/config/tshield.yml
|
492
480
|
- spec/tshield/fixtures/config/tshield-without-grpc.yml
|
481
|
+
- spec/tshield/configuration_spec.rb
|
482
|
+
- spec/tshield/after_filter_spec.rb
|