tshield 0.13.5.0 → 0.15.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 +4 -4
- data/README.md +0 -2
- data/config/tshield.yml +6 -6
- data/lib/tshield/configuration.rb +10 -8
- data/lib/tshield/controllers/requests.rb +21 -12
- data/lib/tshield/errors.rb +4 -0
- data/lib/tshield/grpc/grpc_counter.rb +24 -0
- data/lib/tshield/grpc/vcr.rb +73 -25
- data/lib/tshield/grpc.rb +3 -3
- data/lib/tshield/logger.rb +1 -1
- data/lib/tshield/request_vcr.rb +5 -4
- data/lib/tshield/sessions.rb +2 -0
- data/lib/tshield/version.rb +2 -2
- data/spec/tshield/configuration_spec.rb +3 -4
- data/spec/tshield/controllers/requests_spec.rb +19 -20
- data/spec/tshield/request_vcr_spec.rb +18 -22
- metadata +12 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3675ad22a08350950eadbc2000d89be8dbcf44acc9a4487d1b8c3a59bae3dcd1
|
|
4
|
+
data.tar.gz: c15c0f0d52cf43de37744efcc418932c83db271ba38a50b4ce72df7cd708e65b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b9b08892d5f9843a5cc2fd2db34a0d160126104a83a83ad1d9f4b041b83d9acd5d773ea8645539f16dbf046d85fb54ee2a0a92b963f87f954b88a3ca9656f39
|
|
7
|
+
data.tar.gz: 6300ebfca1c90b7e11a19d2facc3e5cc855db320ffe352b49326a6e20d9f73f401d3e6c4a1f6f3f2c6ba5a01a7c8a2426c1108ce20a2009d6be05c8c484ae9be
|
data/README.md
CHANGED
|
@@ -3,8 +3,6 @@ TShield
|
|
|
3
3
|
|
|
4
4
|
[](https://travis-ci.org/diegorubin/tshield)
|
|
5
5
|
[](https://coveralls.io/github/diegorubin/tshield?branch=master)
|
|
6
|
-
[](https://app.sourcelevel.io/github/diegorubin/-/tshield)
|
|
7
|
-
[](https://gitter.im/diegorubin/tshield?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
8
6
|
[](https://badge.fury.io/rb/tshield)
|
|
9
7
|

|
|
10
8
|
|
data/config/tshield.yml
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
grpc:
|
|
3
3
|
port: 5678
|
|
4
|
-
proto_dir:
|
|
4
|
+
proto_dir: "proto"
|
|
5
5
|
services:
|
|
6
|
-
|
|
7
|
-
module:
|
|
8
|
-
hostname:
|
|
6
|
+
"helloworld_services_pb":
|
|
7
|
+
module: "Helloworld::Greeter"
|
|
8
|
+
hostname: "0.0.0.0:50051"
|
|
9
9
|
request:
|
|
10
10
|
timeout: 10
|
|
11
11
|
domains:
|
|
12
|
-
|
|
13
|
-
name:
|
|
12
|
+
"http://localhost:9090":
|
|
13
|
+
name: "components"
|
|
14
14
|
skip_query_params:
|
|
15
15
|
- b
|
|
16
16
|
paths:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'yaml'
|
|
4
4
|
|
|
5
|
+
require 'tshield/errors'
|
|
5
6
|
require 'tshield/after_filter'
|
|
6
7
|
require 'tshield/before_filter'
|
|
7
8
|
require 'tshield/options'
|
|
@@ -29,10 +30,7 @@ module TShield
|
|
|
29
30
|
# generated directory
|
|
30
31
|
#
|
|
31
32
|
attr_reader :request
|
|
32
|
-
attr_reader :domains
|
|
33
|
-
attr_reader :tcp_servers
|
|
34
|
-
attr_reader :session_path
|
|
35
|
-
attr_reader :windows_compatibility
|
|
33
|
+
attr_reader :domains, :tcp_servers, :session_path, :windows_compatibility
|
|
36
34
|
|
|
37
35
|
def initialize(attributes)
|
|
38
36
|
attributes.each { |key, value| instance_variable_set("@#{key}", value) }
|
|
@@ -62,7 +60,7 @@ module TShield
|
|
|
62
60
|
result = self.class.get_url_for_domain_by_path(path, config)
|
|
63
61
|
return url if result
|
|
64
62
|
end
|
|
65
|
-
|
|
63
|
+
raise ConfigurationNotFoundError.new("Domain not found for path #{path}")
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
def windows_compatibility?
|
|
@@ -92,8 +90,12 @@ module TShield
|
|
|
92
90
|
end
|
|
93
91
|
|
|
94
92
|
def get_filters(domain)
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
begin
|
|
94
|
+
(domains[domain]['filters'] || [])
|
|
95
|
+
.collect { |filter| Class.const_get(filter) }
|
|
96
|
+
rescue
|
|
97
|
+
puts "Error loading filters for domain #{domain}"
|
|
98
|
+
end
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
def get_excluded_headers(domain)
|
|
@@ -106,6 +108,7 @@ module TShield
|
|
|
106
108
|
|
|
107
109
|
def send_header_content_type(domain)
|
|
108
110
|
return domains[domain]['send_header_content_type'] != false if domains[domain]
|
|
111
|
+
|
|
109
112
|
true
|
|
110
113
|
end
|
|
111
114
|
|
|
@@ -140,6 +143,5 @@ module TShield
|
|
|
140
143
|
def get_delay(domain, path)
|
|
141
144
|
((domains[domain] || {})['delay'] || {})[path] || 0
|
|
142
145
|
end
|
|
143
|
-
|
|
144
146
|
end
|
|
145
147
|
end
|
|
@@ -57,8 +57,6 @@ module TShield
|
|
|
57
57
|
ip: request.ip
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
treat_headers_by_domain(options, path)
|
|
61
|
-
|
|
62
60
|
if %w[POST PUT PATCH].include? method
|
|
63
61
|
result = request.body.read.encode('UTF-8',
|
|
64
62
|
invalid: :replace,
|
|
@@ -67,13 +65,21 @@ module TShield
|
|
|
67
65
|
options[:body] = result
|
|
68
66
|
end
|
|
69
67
|
api_response = TShield::RequestMatching.new(path, options.clone).match_request
|
|
70
|
-
|
|
71
68
|
unless api_response
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
begin
|
|
70
|
+
treat_headers_by_domain(options, path)
|
|
71
|
+
add_headers(options, path)
|
|
72
|
+
|
|
73
|
+
api_response ||= TShield::RequestVCR.new(path, options.clone).vcr_response
|
|
74
|
+
api_response.headers.reject! do |key, _v|
|
|
75
|
+
configuration.get_excluded_headers(domain(path)).include?(key)
|
|
76
|
+
end
|
|
77
|
+
rescue ConfigurationNotFoundError => e
|
|
78
|
+
logger.error("Error on recover configuration for #{path}")
|
|
79
|
+
|
|
80
|
+
status 500
|
|
81
|
+
body({tshield: e }.to_json)
|
|
82
|
+
return
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
|
|
@@ -110,11 +116,14 @@ module TShield
|
|
|
110
116
|
end
|
|
111
117
|
|
|
112
118
|
def delay(path)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
begin
|
|
120
|
+
delay_in_seconds = configuration.get_delay(domain(path), path) || 0
|
|
121
|
+
logger.info("Response with delay of #{delay_in_seconds} seconds")
|
|
122
|
+
sleep delay_in_seconds
|
|
123
|
+
rescue ConfigurationNotFoundError
|
|
124
|
+
logger.debug('No delay configured')
|
|
125
|
+
end
|
|
116
126
|
end
|
|
117
|
-
|
|
118
127
|
end
|
|
119
128
|
end
|
|
120
129
|
end
|
data/lib/tshield/errors.rb
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TShield
|
|
4
|
+
# Increment counter for sessions requests
|
|
5
|
+
class GrpcCounter
|
|
6
|
+
def initialize
|
|
7
|
+
@requests = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add(hexdigest)
|
|
11
|
+
count = @requests.fetch(hexdigest, 0)
|
|
12
|
+
count += 1
|
|
13
|
+
@requests[hexdigest] = count
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def current(hexdigest)
|
|
17
|
+
@requests.fetch(hexdigest, 0)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_json(options = {})
|
|
21
|
+
@requests.to_json(options)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/tshield/grpc/vcr.rb
CHANGED
|
@@ -5,79 +5,127 @@ require 'tshield/sessions'
|
|
|
5
5
|
|
|
6
6
|
module TShield
|
|
7
7
|
module Grpc
|
|
8
|
+
# Grpc vcr module
|
|
8
9
|
module VCR
|
|
10
|
+
# Path file to save Grpc request/response
|
|
11
|
+
class FilePath
|
|
12
|
+
attr_reader :path, :count
|
|
13
|
+
|
|
14
|
+
def initialize(path, count)
|
|
15
|
+
@path = path
|
|
16
|
+
@count = count
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
9
20
|
def initialize
|
|
10
21
|
@configuration = TShield::Configuration.singleton
|
|
11
22
|
end
|
|
23
|
+
|
|
12
24
|
def handler_in_vcr_mode(method_name, request, parameters, options)
|
|
13
25
|
parameters.peer =~ /ipv6:\[(.+?)\]|ipv4:(.+?):/
|
|
14
26
|
peer = Regexp.last_match(1) || Regexp.last_match(2)
|
|
15
27
|
|
|
16
28
|
TShield.logger.info("request from #{parameters.peer}")
|
|
17
29
|
@session = TShield::Sessions.current(peer)
|
|
30
|
+
@digest = hexdigest(request)
|
|
31
|
+
counter = @session ? request_count.current(@digest) : 0
|
|
18
32
|
|
|
19
33
|
TShield.logger.info("grpc using session #{@session || 'default'}")
|
|
20
34
|
module_name = options['module']
|
|
21
35
|
|
|
22
|
-
path = create_destiny(module_name, method_name
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
path = create_destiny(module_name, method_name)
|
|
37
|
+
@file_path = FilePath.new(path, counter)
|
|
38
|
+
save_request(request)
|
|
39
|
+
response = {}
|
|
40
|
+
saved_error
|
|
41
|
+
begin
|
|
42
|
+
response = saved_response
|
|
43
|
+
if response
|
|
44
|
+
TShield.logger.info("returning saved response for request #{request.to_json} saved into #{@digest}")
|
|
45
|
+
request_count.add(@digest) if @session
|
|
46
|
+
return response
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
response = send_request(request, module_name, options, method_name)
|
|
50
|
+
save_response(response)
|
|
51
|
+
rescue GRPC::BadStatus => e
|
|
52
|
+
save_error({ code: e.code, details: e.details })
|
|
53
|
+
raise e
|
|
28
54
|
end
|
|
55
|
+
request_count.add(@digest) if @session
|
|
56
|
+
response
|
|
57
|
+
end
|
|
29
58
|
|
|
59
|
+
def send_request(request, module_name, options, method_name)
|
|
30
60
|
TShield.logger.info("calling server to get response for #{request.to_json}")
|
|
31
61
|
client_class = Object.const_get("#{module_name}::Stub")
|
|
32
62
|
client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
63
|
+
client_instance.send(method_name, request)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def request_count
|
|
67
|
+
@session[:grpc_counter]
|
|
36
68
|
end
|
|
37
69
|
|
|
38
70
|
def encode_colon(value)
|
|
39
|
-
value.gsub(':','%3a')
|
|
71
|
+
value.gsub(':', '%3a')
|
|
40
72
|
end
|
|
41
73
|
|
|
42
|
-
def saved_response
|
|
43
|
-
response_file = File.join(path,
|
|
74
|
+
def saved_response
|
|
75
|
+
response_file = File.join(@file_path.path, "#{@file_path.count}.response")
|
|
44
76
|
return false unless File.exist? response_file
|
|
45
77
|
|
|
46
78
|
content = JSON.parse File.open(response_file).read
|
|
47
|
-
response_class = File.open(File.join(path,
|
|
79
|
+
response_class = File.open(File.join(@file_path.path, "#{@file_path.count}.response_class")).read.strip
|
|
48
80
|
Kernel.const_get(response_class).new(content)
|
|
49
81
|
end
|
|
50
82
|
|
|
51
|
-
def
|
|
52
|
-
|
|
83
|
+
def saved_error
|
|
84
|
+
error_file = File.join(@file_path.path, "#{@file_path.count}.error")
|
|
85
|
+
return false unless File.exist? error_file
|
|
86
|
+
|
|
87
|
+
request_count.add(@digest) if @session
|
|
88
|
+
content = JSON.parse File.open(error_file).read
|
|
89
|
+
grpc_error = GRPC::BadStatus.new(content['code'], content['details'])
|
|
90
|
+
raise grpc_error
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def save_request(request)
|
|
94
|
+
file = File.open(File.join(@file_path.path, "#{@file_path.count}.original_request"), 'w')
|
|
53
95
|
file.puts request.to_json
|
|
54
96
|
file.close
|
|
55
97
|
end
|
|
56
98
|
|
|
57
|
-
def
|
|
58
|
-
file = File.open(File.join(path,
|
|
99
|
+
def save_error(error)
|
|
100
|
+
file = File.open(File.join(@file_path.path, "#{@file_path.count}.error"), 'w')
|
|
101
|
+
file.puts error.to_json
|
|
102
|
+
file.close
|
|
103
|
+
request_count.add(@digest) if @session
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def save_response(response)
|
|
107
|
+
file = File.open(File.join(@file_path.path, "#{@file_path.count}.response"), 'w')
|
|
59
108
|
file.puts response.to_json
|
|
60
109
|
file.close
|
|
61
110
|
|
|
62
|
-
response_class = File.open(File.join(path,
|
|
111
|
+
response_class = File.open(File.join(@file_path.path, "#{@file_path.count}.response_class"), 'w')
|
|
63
112
|
response_class.puts response.class.to_s
|
|
64
113
|
response_class.close
|
|
65
114
|
end
|
|
66
115
|
|
|
67
|
-
def complete_path(module_name, method_name
|
|
116
|
+
def complete_path(module_name, method_name)
|
|
68
117
|
@session_name = (@session || {})[:name]
|
|
69
118
|
module_name = @configuration.windows_compatibility? ? encode_colon(module_name) : module_name
|
|
70
|
-
|
|
71
|
-
path
|
|
119
|
+
['requests', @session_name, module_name, method_name.to_s, @digest].compact
|
|
72
120
|
end
|
|
73
121
|
|
|
74
|
-
def create_destiny(module_name, method_name
|
|
122
|
+
def create_destiny(module_name, method_name)
|
|
75
123
|
current_path = []
|
|
76
124
|
|
|
77
|
-
path = complete_path(module_name, method_name
|
|
125
|
+
path = complete_path(module_name, method_name)
|
|
78
126
|
TShield.logger.info("using path #{path}")
|
|
79
|
-
path.each do |
|
|
80
|
-
current_path <<
|
|
127
|
+
path.each do |inner_path|
|
|
128
|
+
current_path << inner_path
|
|
81
129
|
destiny = File.join current_path
|
|
82
130
|
Dir.mkdir destiny unless File.exist? destiny
|
|
83
131
|
end
|
data/lib/tshield/grpc.rb
CHANGED
|
@@ -4,7 +4,6 @@ require 'grpc'
|
|
|
4
4
|
|
|
5
5
|
require 'tshield/configuration'
|
|
6
6
|
require 'tshield/grpc/vcr'
|
|
7
|
-
|
|
8
7
|
module TShield
|
|
9
8
|
module Grpc
|
|
10
9
|
module RequestHandler
|
|
@@ -14,6 +13,7 @@ module TShield
|
|
|
14
13
|
handler_in_vcr_mode(method_name, request, parameters, options)
|
|
15
14
|
end
|
|
16
15
|
end
|
|
16
|
+
|
|
17
17
|
def self.run!
|
|
18
18
|
@configuration = TShield::Configuration.singleton.grpc
|
|
19
19
|
|
|
@@ -41,6 +41,7 @@ module TShield
|
|
|
41
41
|
handlers = []
|
|
42
42
|
number_of_handlers = 0
|
|
43
43
|
services.each do |file, options|
|
|
44
|
+
|
|
44
45
|
require file
|
|
45
46
|
|
|
46
47
|
base = Object.const_get("#{options['module']}::Service")
|
|
@@ -55,8 +56,7 @@ module TShield
|
|
|
55
56
|
def self.build_handler(base, descriptions, number_of_handlers, options)
|
|
56
57
|
handler = Class.new(base) do
|
|
57
58
|
class << self
|
|
58
|
-
|
|
59
|
-
attr_reader :options
|
|
59
|
+
attr_accessor :options
|
|
60
60
|
end
|
|
61
61
|
descriptions.each do |service_name, description|
|
|
62
62
|
puts description
|
data/lib/tshield/logger.rb
CHANGED
data/lib/tshield/request_vcr.rb
CHANGED
|
@@ -79,7 +79,6 @@ module TShield
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def apply_set_cookie_header_values(raw_response, headers = {})
|
|
82
|
-
|
|
83
82
|
headers_clone = headers.clone
|
|
84
83
|
|
|
85
84
|
field = raw_response.get_fields('Set-Cookie')
|
|
@@ -98,6 +97,7 @@ module TShield
|
|
|
98
97
|
|
|
99
98
|
raw_response.headers.each do |k, v|
|
|
100
99
|
next if k == 'set-cookie'
|
|
100
|
+
|
|
101
101
|
headers[k] = v unless configuration.not_save_headers(domain).include? k
|
|
102
102
|
end
|
|
103
103
|
|
|
@@ -156,9 +156,10 @@ module TShield
|
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
def encode_for_windows_dir(directory)
|
|
159
|
-
replace = [['<','%3c'],['>','%3e'],[':','%3a'],['"','%22'],['?','%3f'],[' ','%20'],['*','%2a'],
|
|
159
|
+
replace = [['<', '%3c'], ['>', '%3e'], [':', '%3a'], ['"', '%22'], ['?', '%3f'], [' ', '%20'], ['*', '%2a'],
|
|
160
|
+
['/', '%2f']]
|
|
160
161
|
replace.each do |value|
|
|
161
|
-
directory = directory.gsub(value.first,value.last)
|
|
162
|
+
directory = directory.gsub(value.first, value.last)
|
|
162
163
|
end
|
|
163
164
|
directory
|
|
164
165
|
end
|
|
@@ -171,7 +172,7 @@ module TShield
|
|
|
171
172
|
else
|
|
172
173
|
directory = url.gsub(%r{/}, '-').gsub(/^-/, '')
|
|
173
174
|
end
|
|
174
|
-
|
|
175
|
+
configuration.windows_compatibility? ? encode_for_windows_dir(directory) : directory
|
|
175
176
|
end
|
|
176
177
|
end
|
|
177
178
|
end
|
data/lib/tshield/sessions.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'tshield/logger'
|
|
4
4
|
require 'tshield/counter'
|
|
5
|
+
require 'tshield/grpc/grpc_counter'
|
|
5
6
|
require 'tshield/errors'
|
|
6
7
|
|
|
7
8
|
module TShield
|
|
@@ -14,6 +15,7 @@ module TShield
|
|
|
14
15
|
sessions[normalize_ip(ip)] = {
|
|
15
16
|
name: name,
|
|
16
17
|
counter: TShield::Counter.new,
|
|
18
|
+
grpc_counter: TShield::GrpcCounter.new,
|
|
17
19
|
secondary_sessions: []
|
|
18
20
|
}
|
|
19
21
|
end
|
data/lib/tshield/version.rb
CHANGED
|
@@ -61,13 +61,13 @@ describe TShield::Configuration do
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
it 'return nil if domain not found' do
|
|
64
|
-
expect
|
|
64
|
+
expect{@configuration.get_domain_for('/api/four')}.to raise_error(ConfigurationNotFoundError)
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
describe 'SO compatibility' do
|
|
69
69
|
it 'should be compatible with windows when configuration is true' do
|
|
70
|
-
allow(YAML).to receive(:safe_load).and_return({:
|
|
70
|
+
allow(YAML).to receive(:safe_load).and_return({ windows_compatibility: true })
|
|
71
71
|
TShield::Configuration.clear
|
|
72
72
|
@configuration = TShield::Configuration.singleton
|
|
73
73
|
|
|
@@ -75,7 +75,7 @@ describe TShield::Configuration do
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
it 'should be compatible with Unix when configuration is false' do
|
|
78
|
-
allow(YAML).to receive(:safe_load).and_return({:
|
|
78
|
+
allow(YAML).to receive(:safe_load).and_return({ windows_compatibility: false })
|
|
79
79
|
TShield::Configuration.clear
|
|
80
80
|
@configuration = TShield::Configuration.singleton
|
|
81
81
|
|
|
@@ -89,7 +89,6 @@ describe TShield::Configuration do
|
|
|
89
89
|
|
|
90
90
|
expect(@configuration.windows_compatibility?).to eq(false)
|
|
91
91
|
end
|
|
92
|
-
|
|
93
92
|
end
|
|
94
93
|
end
|
|
95
94
|
context 'on config not exist' do
|
|
@@ -47,6 +47,7 @@ describe TShield::Controllers::Requests do
|
|
|
47
47
|
allow(matched_response).to receive(:headers).and_return({})
|
|
48
48
|
allow(matched_response).to receive(:body).and_return('')
|
|
49
49
|
allow(@mock_logger).to receive(:info)
|
|
50
|
+
allow(@mock_logger).to receive(:debug)
|
|
50
51
|
|
|
51
52
|
expect(TShield::Controllers::Helpers::SessionHelpers)
|
|
52
53
|
.to receive(:current_session_call).with(request, '/?a=b', 'GET')
|
|
@@ -73,7 +74,6 @@ describe TShield::Controllers::Requests do
|
|
|
73
74
|
allow(@configuration).to receive(:get_domain_for).and_return('example.org')
|
|
74
75
|
allow(@configuration).to receive(:get_delay).and_return(0)
|
|
75
76
|
|
|
76
|
-
|
|
77
77
|
allow(TShield::Options).to receive_message_chain(:instance, :break?)
|
|
78
78
|
@mock_logger = double
|
|
79
79
|
@controller = MockController.new(@mock_logger)
|
|
@@ -100,15 +100,15 @@ describe TShield::Controllers::Requests do
|
|
|
100
100
|
allow(matched_response).to receive(:body).and_return('')
|
|
101
101
|
allow(@mock_logger).to receive(:info)
|
|
102
102
|
|
|
103
|
-
expect(TShield::RequestVCR).to receive(:new).with(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
expect(TShield::RequestVCR).to receive(:new).with('/', {
|
|
104
|
+
call: 0,
|
|
105
|
+
headers: {},
|
|
106
|
+
ip: '0.0.0.0',
|
|
107
|
+
method: 'GET',
|
|
108
|
+
raw_query: 'a=b',
|
|
109
|
+
secondary_sessions: nil,
|
|
110
|
+
session: nil
|
|
111
|
+
})
|
|
112
112
|
@controller.treat(params, request, nil)
|
|
113
113
|
end
|
|
114
114
|
end
|
|
@@ -135,16 +135,15 @@ describe TShield::Controllers::Requests do
|
|
|
135
135
|
allow(matched_response).to receive(:body).and_return('')
|
|
136
136
|
allow(@mock_logger).to receive(:info)
|
|
137
137
|
|
|
138
|
-
expect(TShield::RequestVCR).to receive(:new).with(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
138
|
+
expect(TShield::RequestVCR).to receive(:new).with('/', {
|
|
139
|
+
call: 0,
|
|
140
|
+
headers: { 'Content-Type' => 'application/json' },
|
|
141
|
+
ip: '0.0.0.0',
|
|
142
|
+
method: 'GET',
|
|
143
|
+
raw_query: 'a=b',
|
|
144
|
+
secondary_sessions: nil,
|
|
145
|
+
session: nil
|
|
146
|
+
})
|
|
148
147
|
|
|
149
148
|
@controller.treat(params, request, nil)
|
|
150
149
|
end
|
|
@@ -107,9 +107,9 @@ describe TShield::RequestVCR do
|
|
|
107
107
|
|
|
108
108
|
it 'should create response directory in windows standard' do
|
|
109
109
|
allow(@configuration).to receive(:domains).and_return(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
'example.org' => {
|
|
111
|
+
'skip_query_params' => []
|
|
112
|
+
}
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
allow(@configuration).to receive(:windows_compatibility?).and_return(true)
|
|
@@ -118,28 +118,28 @@ describe TShield::RequestVCR do
|
|
|
118
118
|
file_double = double
|
|
119
119
|
|
|
120
120
|
allow(File).to receive(:join)
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
.with('./requests/example.org', '%3fparam=value')
|
|
122
|
+
.and_return('./requests/example.org/%3fparam=value')
|
|
123
123
|
allow(File).to receive(:join)
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
.with('./requests/example.org/%3fparam=value', 'get')
|
|
125
|
+
.and_return('./requests/example.org/%3fparam=value/get')
|
|
126
126
|
allow(File).to receive(:join)
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
.with('./requests/example.org/%3fparam=value/get', '0')
|
|
128
|
+
.and_return('./requests/example.org/%3fparam=value/get/0')
|
|
129
129
|
|
|
130
130
|
allow(file_double).to receive(:read).and_return('{}')
|
|
131
131
|
|
|
132
132
|
expect(File).to receive('open')
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
.with('./requests/example.org/%3fparam=value/get/0.content', 'w')
|
|
134
|
+
.and_return(file_double)
|
|
135
135
|
|
|
136
136
|
expect(File).to receive('open')
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
.with('./requests/example.org/%3fparam=value/get/0.json', 'w')
|
|
138
|
+
.and_return(file_double)
|
|
139
139
|
|
|
140
140
|
expect(file_double).to receive(:write).ordered.with('this is the body')
|
|
141
141
|
expect(file_double).to receive(:write)
|
|
142
|
-
|
|
142
|
+
.with("{\n \"status\": 200,\n \"headers\": {\n }\n}")
|
|
143
143
|
expect(file_double).to receive(:close)
|
|
144
144
|
expect(file_double).to receive(:close)
|
|
145
145
|
|
|
@@ -148,7 +148,6 @@ describe TShield::RequestVCR do
|
|
|
148
148
|
method: 'GET',
|
|
149
149
|
call: 0
|
|
150
150
|
end
|
|
151
|
-
|
|
152
151
|
end
|
|
153
152
|
end
|
|
154
153
|
|
|
@@ -161,7 +160,7 @@ describe TShield::RequestVCR do
|
|
|
161
160
|
'this is the body'
|
|
162
161
|
end
|
|
163
162
|
|
|
164
|
-
def get_fields(
|
|
163
|
+
def get_fields(_field = '')
|
|
165
164
|
[]
|
|
166
165
|
end
|
|
167
166
|
|
|
@@ -172,22 +171,19 @@ describe TShield::RequestVCR do
|
|
|
172
171
|
|
|
173
172
|
class RawResponseCookiesMultipleValues
|
|
174
173
|
def headers
|
|
175
|
-
|
|
174
|
+
{ 'Set-Cookie' => ['FirstCookie=An Value', 'SecondCookie=An Value'] }
|
|
176
175
|
end
|
|
177
176
|
|
|
178
177
|
def body
|
|
179
178
|
'this is the body'
|
|
180
179
|
end
|
|
181
180
|
|
|
182
|
-
def get_fields(field =
|
|
183
|
-
|
|
181
|
+
def get_fields(field = '')
|
|
182
|
+
headers[filed] unless headers.key?(field)
|
|
184
183
|
end
|
|
185
184
|
|
|
186
185
|
def code
|
|
187
186
|
200
|
|
188
187
|
end
|
|
189
188
|
end
|
|
190
|
-
|
|
191
189
|
end
|
|
192
|
-
|
|
193
|
-
|
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.15.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Diego Rubin
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2023-10-29 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: grpc
|
|
@@ -415,6 +415,7 @@ files:
|
|
|
415
415
|
- lib/tshield/errors.rb
|
|
416
416
|
- lib/tshield/extensions/string_extensions.rb
|
|
417
417
|
- lib/tshield/grpc.rb
|
|
418
|
+
- lib/tshield/grpc/grpc_counter.rb
|
|
418
419
|
- lib/tshield/grpc/vcr.rb
|
|
419
420
|
- lib/tshield/logger.rb
|
|
420
421
|
- lib/tshield/matching/filters.rb
|
|
@@ -467,19 +468,19 @@ signing_key:
|
|
|
467
468
|
specification_version: 4
|
|
468
469
|
summary: Proxy for mocks API responses
|
|
469
470
|
test_files:
|
|
471
|
+
- spec/spec_helper.rb
|
|
472
|
+
- spec/tshield/configuration_spec.rb
|
|
473
|
+
- spec/tshield/request_matching_spec.rb
|
|
474
|
+
- spec/tshield/sessions_spec.rb
|
|
470
475
|
- spec/tshield/controllers/requests_spec.rb
|
|
476
|
+
- spec/tshield/request_vcr_spec.rb
|
|
477
|
+
- spec/tshield/grpc_spec.rb
|
|
478
|
+
- spec/tshield/options_spec.rb
|
|
471
479
|
- spec/tshield/after_filter_spec.rb
|
|
472
|
-
- spec/tshield/configuration_spec.rb
|
|
473
|
-
- spec/tshield/fixtures/proto/test_services_pb.rb
|
|
474
480
|
- spec/tshield/fixtures/config/tshield-without-grpc.yml
|
|
475
|
-
- spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
|
|
476
481
|
- spec/tshield/fixtures/config/tshield.yml
|
|
482
|
+
- spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
|
|
477
483
|
- spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
|
|
478
484
|
- spec/tshield/fixtures/matching/example.json
|
|
485
|
+
- spec/tshield/fixtures/proto/test_services_pb.rb
|
|
479
486
|
- spec/tshield/fixtures/filters/example_filter.rb
|
|
480
|
-
- spec/tshield/request_vcr_spec.rb
|
|
481
|
-
- spec/tshield/sessions_spec.rb
|
|
482
|
-
- spec/tshield/grpc_spec.rb
|
|
483
|
-
- spec/tshield/options_spec.rb
|
|
484
|
-
- spec/tshield/request_matching_spec.rb
|
|
485
|
-
- spec/spec_helper.rb
|