tshield 0.13.0.0 → 0.13.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: caa9310473bc1479ad6bc7db7ae67938b269bbd7
4
- data.tar.gz: 34de8d7084f0eecb054f2b07b9950ef0dffbf32b
2
+ SHA256:
3
+ metadata.gz: ab5c5057fe81ae295f572912c6955ce0ea0bd9be6b42fb515a7832fe3451459a
4
+ data.tar.gz: 9c785dc23adb245fdfcc416698c551f7a45eaa32b5892a2cabea708f16fa2859
5
5
  SHA512:
6
- metadata.gz: 41afa4ac6a4471ea700beaa32ddf4c664f7eeb4f7a61639853b883a5ee0b6dd8f4262f9e14198a186e89cece5bb158669587a00f80dc7bef6bb460a5f6f7c5a3
7
- data.tar.gz: ef52b07f2bfc68d8ff0561c0676350493da7b7f16b26f1e61687f13a78929e4ec9659859a396dcb6bb51d5eab8c041cc15cbb2ca92fcecc8a5ed768101a2a7bd
6
+ metadata.gz: 58fd33ddf9e466af5882e6522612b2b0fa05c95f728578fe50b014dca0777357bf5ccfa17605a86309c5742cb828dd2e52eb9bb2839096f594e1e75fef80e81b
7
+ data.tar.gz: f085f1dcc7a3d861da1b28a0d07f3338f03dd5b27cdd234c283cecf0bce8a0dc66f26193755ea8f5b442cbf4953fb2bd4ce295f90257b76121ac7fdbcbdd38b0
data/README.md CHANGED
@@ -3,9 +3,10 @@ TShield
3
3
 
4
4
  [![Build Status](https://travis-ci.org/diegorubin/tshield.svg)](https://travis-ci.org/diegorubin/tshield)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/diegorubin/tshield/badge.svg?branch=master)](https://coveralls.io/github/diegorubin/tshield?branch=master)
6
- [![SourceLevel](https://app.sourcelevel.io/github/diegorubin/tshield.svg)](https://app.sourcelevel.io/github/diegorubin/tshield)
6
+ [![SourceLevel](https://app.sourcelevel.io/github/diegorubin/-/tshield.svg)](https://app.sourcelevel.io/github/diegorubin/-/tshield)
7
7
  [![Join the chat at https://gitter.im/diegorubin/tshield](https://badges.gitter.im/diegorubin/tshield.svg)](https://gitter.im/diegorubin/tshield?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
8
  [![Gem Version](https://badge.fury.io/rb/tshield.svg)](https://badge.fury.io/rb/tshield)
9
+ ![TShield Publish](https://github.com/diegorubin/tshield/workflows/TShield%20Publish/badge.svg)
9
10
 
10
11
  ## API mocks for development and testing
11
12
  TShield is an open source proxy for mocks API responses.
@@ -191,6 +192,7 @@ domains:
191
192
  headers:
192
193
  HTTP_AUTHORIZATION: Authorization
193
194
  HTTP_COOKIE: Cookie
195
+ send_header_content_type: true
194
196
  not_save_headers:
195
197
  - transfer-encoding
196
198
  cache_request: <<value>>
@@ -234,6 +236,7 @@ domains:
234
236
  * Define Base URI of service
235
237
  * **name**: Name to identify the domain in the generated files
236
238
  * **headers**: github-issue #17
239
+ * **send_header_content_type**: Boolean domain config to send header 'Content-Type' when requesting this domain
237
240
  * **not_save_headers**: List of headers that should be ignored in generated file
238
241
  * **skip_query_params**: List of query params that should be ignored in generated file
239
242
  * **cache_request**: <<some_description>>
@@ -65,6 +65,10 @@ module TShield
65
65
  nil
66
66
  end
67
67
 
68
+ def windows_compatibility?
69
+ windows_compatibility || false
70
+ end
71
+
68
72
  def get_headers(domain)
69
73
  (domains[domain] || {})['headers'] || {}
70
74
  end
@@ -100,12 +104,13 @@ module TShield
100
104
  domains[domain]['not_save_headers'] || []
101
105
  end
102
106
 
103
- def read_session_path
104
- session_path || '/sessions'
107
+ def send_header_content_type(domain)
108
+ return domains[domain]['send_header_content_type'] != false if domains[domain]
109
+ true
105
110
  end
106
111
 
107
- def get_questionmark_char
108
- windows_compatibility ? '%3f' : '?'
112
+ def read_session_path
113
+ session_path || '/sessions'
109
114
  end
110
115
 
111
116
  def grpc
@@ -57,6 +57,8 @@ module TShield
57
57
  ip: request.ip
58
58
  }
59
59
 
60
+ treat_headers_by_domain(options, path)
61
+
60
62
  if %w[POST PUT PATCH].include? method
61
63
  result = request.body.read.encode('UTF-8',
62
64
  invalid: :replace,
@@ -74,7 +76,7 @@ module TShield
74
76
  configuration.get_excluded_headers(domain(path)).include?(key)
75
77
  end
76
78
  end
77
-
79
+
78
80
  logger.info(
79
81
  "original=#{api_response.original} method=#{method} path=#{path} "\
80
82
  "content-type=#{request_content_type} "\
@@ -94,6 +96,11 @@ module TShield
94
96
  end
95
97
  end
96
98
 
99
+ def treat_headers_by_domain(options, path)
100
+ @send_header_content_type = configuration.send_header_content_type(domain(path))
101
+ options[:headers].delete('Content-Type') unless @send_header_content_type
102
+ end
103
+
97
104
  def configuration
98
105
  @configuration ||= TShield::Configuration.singleton
99
106
  end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tshield/configuration'
3
4
  require 'tshield/sessions'
4
5
 
5
6
  module TShield
6
7
  module Grpc
7
8
  module VCR
9
+ def initialize
10
+ @configuration = TShield::Configuration.singleton
11
+ end
8
12
  def handler_in_vcr_mode(method_name, request, parameters, options)
9
13
  parameters.peer =~ /ipv6:\[(.+?)\]|ipv4:(.+?):/
10
14
  peer = Regexp.last_match(1) || Regexp.last_match(2)
@@ -16,6 +20,7 @@ module TShield
16
20
  module_name = options['module']
17
21
 
18
22
  path = create_destiny(module_name, method_name, request)
23
+ save_request(path, request)
19
24
  response = saved_response(path)
20
25
  if response
21
26
  TShield.logger.info("returning saved response for request #{request.to_json} saved into #{hexdigest(request)}")
@@ -26,10 +31,14 @@ module TShield
26
31
  client_class = Object.const_get("#{module_name}::Stub")
27
32
  client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
28
33
  response = client_instance.send(method_name, request)
29
- save_request_and_response(path, request, response)
34
+ save_response(path, response)
30
35
  response
31
36
  end
32
37
 
38
+ def encode_colon(value)
39
+ value.gsub(':','%3a')
40
+ end
41
+
33
42
  def saved_response(path)
34
43
  response_file = File.join(path, 'response')
35
44
  return false unless File.exist? response_file
@@ -39,11 +48,6 @@ module TShield
39
48
  Kernel.const_get(response_class).new(content)
40
49
  end
41
50
 
42
- def save_request_and_response(path, request, response)
43
- save_request(path, request)
44
- save_response(path, response)
45
- end
46
-
47
51
  def save_request(path, request)
48
52
  file = File.open(File.join(path, 'original_request'), 'w')
49
53
  file.puts request.to_json
@@ -62,6 +66,7 @@ module TShield
62
66
 
63
67
  def complete_path(module_name, method_name, request)
64
68
  @session_name = (@session || {})[:name]
69
+ module_name = @configuration.windows_compatibility? ? encode_colon(module_name) : module_name
65
70
  path = ['requests', 'grpc', @session_name, module_name, method_name.to_s, hexdigest(request)].compact
66
71
  path
67
72
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tshield/logger'
3
4
  require 'tshield/matching/filters'
4
5
  require 'tshield/request'
5
6
 
@@ -59,15 +60,38 @@ module TShield
59
60
  end
60
61
 
61
62
  def load_stub(file)
62
- content = JSON.parse File.open(file).read
63
+ content = read_stub_file(file)
63
64
  content.each do |stub|
64
- stub_session_name = init_stub_session(stub)
65
+ next unless valid_stub?(file, stub)
65
66
 
66
- if stub['stubs']
67
- load_items(stub['stubs'] || [], stub_session_name)
68
- else
69
- load_item(stub, stub_session_name)
70
- end
67
+ load_valid_stub(stub)
68
+ end
69
+ end
70
+
71
+ def read_stub_file(file)
72
+ JSON.parse File.open(file).read
73
+ rescue StandardError
74
+ TShield.logger.error "error in loading matching file #{file}"
75
+ []
76
+ end
77
+
78
+ def valid_stub?(file, stub)
79
+ is_valid = stub.is_a?(Hash) && mandatory_attributes?(stub)
80
+ TShield.logger.info "loading matching file #{file}" if is_valid
81
+ is_valid
82
+ end
83
+
84
+ def mandatory_attributes?(stub)
85
+ (stub['method'] && stub['path'] && stub['response']) || (stub['session'] && stub['stubs'])
86
+ end
87
+
88
+ def load_valid_stub(stub)
89
+ stub_session_name = init_stub_session(stub)
90
+
91
+ if stub['stubs']
92
+ load_items(stub['stubs'] || [], stub_session_name)
93
+ else
94
+ load_item(stub, stub_session_name)
71
95
  end
72
96
  end
73
97
 
@@ -78,12 +78,31 @@ module TShield
78
78
  @method ||= @options[:method].downcase
79
79
  end
80
80
 
81
+ def apply_set_cookie_header_values(raw_response, headers = {})
82
+
83
+ headers_clone = headers.clone
84
+
85
+ field = raw_response.get_fields('Set-Cookie')
86
+
87
+ if !field.nil? && !field.empty?
88
+ cookies_values = []
89
+ field.each { |value| cookies_values.push(value) }
90
+ headers_clone['Set-Cookie'] = cookies_values
91
+ end
92
+
93
+ headers_clone
94
+ end
95
+
81
96
  def save(raw_response)
82
97
  headers = {}
98
+
83
99
  raw_response.headers.each do |k, v|
100
+ next if k == 'set-cookie'
84
101
  headers[k] = v unless configuration.not_save_headers(domain).include? k
85
102
  end
86
103
 
104
+ headers = apply_set_cookie_header_values(raw_response, headers)
105
+
87
106
  content = {
88
107
  body: raw_response.body,
89
108
  status: raw_response.code,
@@ -136,14 +155,23 @@ module TShield
136
155
  content[:body] = body
137
156
  end
138
157
 
158
+ def encode_for_windows_dir(directory)
159
+ replace = [['<','%3c'],['>','%3e'],[':','%3a'],['"','%22'],['?','%3f'],[' ','%20'],['*','%2a'],['/','%2f']]
160
+ replace.each do |value|
161
+ directory = directory.gsub(value.first,value.last)
162
+ end
163
+ directory
164
+ end
165
+
139
166
  def safe_dir(url)
140
167
  if url.size > 225
141
168
  path = url.gsub(/(\?.*)/, '')
142
169
  params = Digest::SHA1.hexdigest Regexp.last_match(1)
143
- "#{path.gsub(%r{/}, '-').gsub(/^-/, '')}#{configuration.get_questionmark_char}#{params}"
170
+ directory = "#{path.gsub(%r{/}, '-').gsub(/^-/, '')}?#{params}"
144
171
  else
145
- url.gsub(%r{/}, '-').gsub(/^-/, '').gsub('?', configuration.get_questionmark_char)
172
+ directory = url.gsub(%r{/}, '-').gsub(/^-/, '')
146
173
  end
174
+ configuration.windows_compatibility? ? encode_for_windows_dir(directory) : directory
147
175
  end
148
176
  end
149
177
  end
@@ -29,9 +29,9 @@ module TShield
29
29
 
30
30
  options '*' do
31
31
  response.headers['Allow'] = 'GET, PUT, POST, DELETE, OPTIONS'
32
- response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type,
33
- Accept, X-User-Email, X-Auth-Token'
32
+ response.headers['Access-Control-Allow-Headers'] = '*'
34
33
  response.headers['Access-Control-Allow-Origin'] = '*'
34
+ response.headers['Access-Control-Allow-Methods'] = '*'
35
35
  200
36
36
  end
37
37
 
@@ -5,7 +5,7 @@ module TShield
5
5
  class Version
6
6
  MAJOR = 0
7
7
  MINOR = 13
8
- PATCH = 0
8
+ PATCH = 5
9
9
  PRE = 0
10
10
 
11
11
  class << self
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'coveralls'
4
- Coveralls.wear!
3
+ if ENV['COVERALLS_REPO_TOKEN']
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+ end
5
7
 
6
8
  require 'bundler/setup'
7
9
  Bundler.setup
@@ -71,7 +71,7 @@ describe TShield::Configuration do
71
71
  TShield::Configuration.clear
72
72
  @configuration = TShield::Configuration.singleton
73
73
 
74
- expect(@configuration.get_questionmark_char).to eq('%3f')
74
+ expect(@configuration.windows_compatibility?).to eq(true)
75
75
  end
76
76
 
77
77
  it 'should be compatible with Unix when configuration is false' do
@@ -79,7 +79,7 @@ describe TShield::Configuration do
79
79
  TShield::Configuration.clear
80
80
  @configuration = TShield::Configuration.singleton
81
81
 
82
- expect(@configuration.get_questionmark_char).to eq('?')
82
+ expect(@configuration.windows_compatibility?).to eq(false)
83
83
  end
84
84
 
85
85
  it 'should be compatible with Unix when configuration is missing' do
@@ -87,7 +87,7 @@ describe TShield::Configuration do
87
87
  TShield::Configuration.clear
88
88
  @configuration = TShield::Configuration.singleton
89
89
 
90
- expect(@configuration.get_questionmark_char).to eq('?')
90
+ expect(@configuration.windows_compatibility?).to eq(false)
91
91
  end
92
92
 
93
93
  end
@@ -108,14 +108,42 @@ describe TShield::Configuration do
108
108
 
109
109
  context 'on config exists without grpc entry' do
110
110
  before :each do
111
- options_instance = double
112
- allow(options_instance).to receive(:configuration_file)
113
- .and_return('spec/tshield/fixtures/config/tshield-without-grpc.yml')
114
- allow(TShield::Options).to receive(:instance).and_return(options_instance)
115
- @configuration = TShield::Configuration.singleton
111
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-without-grpc.yml')
112
+ TShield::Configuration.clear
116
113
  end
117
114
  it 'should set default value for port' do
118
115
  expect(@configuration.grpc).to eql('port' => 5678, 'proto_dir' => 'proto', 'services' => {})
119
116
  end
120
117
  end
118
+
119
+ context 'on config property request.domains.domain.send_header_content_type does not exists' do
120
+ before :each do
121
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-without-grpc.yml')
122
+ TShield::Configuration.clear
123
+ end
124
+ it 'should return send_header_content_type as true when property is not set' do
125
+ expect(@configuration.send_header_content_type('example.org')).to be true
126
+ end
127
+ end
128
+
129
+ context 'on config property request.domains.domain.send_header_content_type does exists' do
130
+ before :each do
131
+ TShield::Configuration.clear
132
+ end
133
+ it 'should return send_header_content_type as true when property is true' do
134
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml')
135
+ expect(@configuration.send_header_content_type('example.org')).to be true
136
+ end
137
+ it 'should return send_header_content_type as false when property is false' do
138
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml')
139
+ expect(@configuration.send_header_content_type('example.org')).to be false
140
+ end
141
+ end
142
+ end
143
+
144
+ def generate_configuration_from_file(file)
145
+ options_instance = double
146
+ allow(options_instance).to receive(:configuration_file).and_return(file)
147
+ allow(TShield::Options).to receive(:instance).and_return(options_instance)
148
+ TShield::Configuration.singleton
121
149
  end
@@ -58,3 +58,95 @@ describe TShield::Controllers::Requests do
58
58
  end
59
59
  end
60
60
  end
61
+
62
+ describe TShield::Controllers::Requests do
63
+ before :each do
64
+ @configuration = double
65
+ allow(TShield::Configuration)
66
+ .to receive(:singleton).and_return(@configuration)
67
+ allow(@configuration).to receive(:get_before_filters).and_return([])
68
+ allow(@configuration).to receive(:not_save_headers).and_return([])
69
+ allow(@configuration).to receive(:get_after_filters).and_return([])
70
+ allow(@configuration).to receive(:get_headers).and_return([])
71
+ allow(@configuration).to receive(:request).and_return('timeout' => 10)
72
+ allow(@configuration).to receive(:get_name).and_return('example.org')
73
+ allow(@configuration).to receive(:get_domain_for).and_return('example.org')
74
+ allow(@configuration).to receive(:get_delay).and_return(0)
75
+
76
+
77
+ allow(TShield::Options).to receive_message_chain(:instance, :break?)
78
+ @mock_logger = double
79
+ @controller = MockController.new(@mock_logger)
80
+ end
81
+ context 'when send_header_content_type is false for a single domain' do
82
+ it 'should remove application/json header when making a request' do
83
+ params = { 'captures' => ['/'] }
84
+ request = double
85
+ matcher = double
86
+ matched_response = double
87
+
88
+ allow(@configuration).to receive(:send_header_content_type).and_return(false)
89
+ allow(request).to receive(:request_method).and_return('GET')
90
+ allow(request).to receive(:content_type).and_return('application/json')
91
+ allow(request).to receive(:ip).and_return('0.0.0.0')
92
+ allow(request).to receive(:env).and_return('QUERY_STRING' => 'a=b')
93
+ allow(TShield::RequestMatching).to receive(:new).and_return(matcher)
94
+ allow(matcher).to receive(:match_request).and_return(nil)
95
+ allow(TShield::RequestVCR).to receive(:new).and_return(matcher)
96
+ allow(matcher).to receive(:vcr_response).and_return(matched_response)
97
+ allow(matched_response).to receive(:original).and_return(false)
98
+ allow(matched_response).to receive(:status).and_return(200)
99
+ allow(matched_response).to receive(:headers).and_return({})
100
+ allow(matched_response).to receive(:body).and_return('')
101
+ allow(@mock_logger).to receive(:info)
102
+
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
+ @controller.treat(params, request, nil)
113
+ end
114
+ end
115
+
116
+ context 'when send_header_content_type is true for a single domain' do
117
+ it 'should NOT remove application/json header when making a request' do
118
+ params = { 'captures' => ['/'] }
119
+ request = double
120
+ matcher = double
121
+ matched_response = double
122
+
123
+ allow(@configuration).to receive(:send_header_content_type).and_return(true)
124
+ allow(request).to receive(:request_method).and_return('GET')
125
+ allow(request).to receive(:content_type).and_return('application/json')
126
+ allow(request).to receive(:ip).and_return('0.0.0.0')
127
+ allow(request).to receive(:env).and_return('QUERY_STRING' => 'a=b')
128
+ allow(TShield::RequestMatching).to receive(:new).and_return(matcher)
129
+ allow(matcher).to receive(:match_request).and_return(nil)
130
+ allow(TShield::RequestVCR).to receive(:new).and_return(matcher)
131
+ allow(matcher).to receive(:vcr_response).and_return(matched_response)
132
+ allow(matched_response).to receive(:original).and_return(false)
133
+ allow(matched_response).to receive(:status).and_return(200)
134
+ allow(matched_response).to receive(:headers).and_return({})
135
+ allow(matched_response).to receive(:body).and_return('')
136
+ allow(@mock_logger).to receive(:info)
137
+
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
+ })
147
+
148
+
149
+ @controller.treat(params, request, nil)
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,18 @@
1
+ ---
2
+ request:
3
+ timeout: 0
4
+ domains:
5
+ 'example.org':
6
+ name: 'example.org'
7
+ send_header_content_type: true
8
+ filters:
9
+ - 'ExampleFilter'
10
+ paths:
11
+ - '/api/one'
12
+ - '/api/two'
13
+ skip_query_params:
14
+ - 'a'
15
+ 'example.com':
16
+ name: 'example.com'
17
+ paths:
18
+ - '/api/three'
@@ -0,0 +1,18 @@
1
+ ---
2
+ request:
3
+ timeout: 0
4
+ domains:
5
+ 'example.org':
6
+ name: 'example.org'
7
+ send_header_content_type: false
8
+ filters:
9
+ - 'ExampleFilter'
10
+ paths:
11
+ - '/api/one'
12
+ - '/api/two'
13
+ skip_query_params:
14
+ - 'a'
15
+ 'example.com':
16
+ name: 'example.com'
17
+ paths:
18
+ - '/api/three'
@@ -36,6 +36,38 @@ describe TShield::RequestMatching do
36
36
  end
37
37
  end
38
38
 
39
+ context 'invalid matching file' do
40
+ before :each do
41
+ allow(Dir).to receive(:glob)
42
+ .and_return(['spec/tshield/fixtures/matching/invalid_matching_file.json'])
43
+ end
44
+
45
+ context 'on loading stubs' do
46
+ before :each do
47
+ @request_matching = TShield::RequestMatching.new('/')
48
+ end
49
+ it 'should stubs be empty' do
50
+ expect(@request_matching.class.stubs[DEFAULT_SESSION]).to be_nil
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'empty matching file' do
56
+ before :each do
57
+ allow(Dir).to receive(:glob)
58
+ .and_return(['spec/tshield/fixtures/matching/empty.json'])
59
+ end
60
+
61
+ context 'on loading stubs' do
62
+ before :each do
63
+ @request_matching = TShield::RequestMatching.new('/')
64
+ end
65
+ it 'should stubs be empty' do
66
+ expect(@request_matching.class.stubs[DEFAULT_SESSION]).to be_nil
67
+ end
68
+ end
69
+ end
70
+
39
71
  context 'matching path' do
40
72
  before :each do
41
73
  allow(Dir).to receive(:glob)
@@ -10,6 +10,7 @@ describe TShield::RequestVCR do
10
10
  allow(TShield::Configuration)
11
11
  .to receive(:singleton).and_return(@configuration)
12
12
  allow(@configuration).to receive(:get_before_filters).and_return([])
13
+ allow(@configuration).to receive(:not_save_headers).and_return([])
13
14
  allow(@configuration).to receive(:get_after_filters).and_return([])
14
15
  allow(@configuration).to receive(:request).and_return('timeout' => 10)
15
16
  allow(@configuration).to receive(:get_domain_for).and_return('example.org')
@@ -35,6 +36,24 @@ describe TShield::RequestVCR do
35
36
  TShield::RequestVCR.new '/', method: 'GET'
36
37
  end
37
38
 
39
+ it 'should write response headers as multiple occcurences when has more than one with same key' do
40
+ allow_any_instance_of(TShield::RequestVCR).to receive(:exists)
41
+ .and_return(false)
42
+ allow_any_instance_of(TShield::RequestVCR).to receive(:destiny)
43
+ allow(HTTParty).to receive(:send).and_return(RawResponseCookiesMultipleValues.new)
44
+
45
+ write_spy = double
46
+ allow(File).to receive(:open).and_return(write_spy)
47
+
48
+ expect(write_spy).to receive(:write).ordered.with('this is the body')
49
+ expect(write_spy).to receive(:write)
50
+ .ordered
51
+ .with("{\n \"status\": 200,\n \"headers\": {\n \"Set-Cookie\": [\n \"FirstCookie=An Value\",\n \"SecondCookie=An Value\"\n ]\n }\n}")
52
+ allow(write_spy).to receive(:close)
53
+
54
+ TShield::RequestVCR.new '/', method: 'GET'
55
+ end
56
+
38
57
  describe 'and query params exists in list to skip' do
39
58
  before :each do
40
59
  allow(@configuration).to receive(:get_name).and_return('example.org')
@@ -62,7 +81,7 @@ describe TShield::RequestVCR do
62
81
  }
63
82
  )
64
83
 
65
- allow(@configuration).to receive(:get_questionmark_char).and_return('?')
84
+ allow(@configuration).to receive(:windows_compatibility?).and_return(false)
66
85
 
67
86
  allow(HTTParty).to receive(:send).and_return(RawResponse.new)
68
87
  file_double = double
@@ -87,14 +106,13 @@ describe TShield::RequestVCR do
87
106
  end
88
107
 
89
108
  it 'should create response directory in windows standard' do
90
-
91
109
  allow(@configuration).to receive(:domains).and_return(
92
110
  'example.org' => {
93
111
  'skip_query_params' => []
94
112
  }
95
113
  )
96
114
 
97
- allow(@configuration).to receive(:get_questionmark_char).and_return('%3f')
115
+ allow(@configuration).to receive(:windows_compatibility?).and_return(true)
98
116
 
99
117
  allow(HTTParty).to receive(:send).and_return(RawResponse.new)
100
118
  file_double = double
@@ -131,7 +149,6 @@ describe TShield::RequestVCR do
131
149
  call: 0
132
150
  end
133
151
 
134
-
135
152
  end
136
153
  end
137
154
 
@@ -144,8 +161,33 @@ describe TShield::RequestVCR do
144
161
  'this is the body'
145
162
  end
146
163
 
164
+ def get_fields(field = "")
165
+ []
166
+ end
167
+
168
+ def code
169
+ 200
170
+ end
171
+ end
172
+
173
+ class RawResponseCookiesMultipleValues
174
+ def headers
175
+ {'Set-Cookie' => ['FirstCookie=An Value', 'SecondCookie=An Value']}
176
+ end
177
+
178
+ def body
179
+ 'this is the body'
180
+ end
181
+
182
+ def get_fields(field = "")
183
+ self.headers[filed] unless self.headers.key?(field)
184
+ end
185
+
147
186
  def code
148
187
  200
149
188
  end
150
189
  end
190
+
151
191
  end
192
+
193
+
data/tshield.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency('grpc-tools', '~> 1.28', '>= 1.28.0')
29
29
  s.add_dependency('httparty', '~> 0.14', '>= 0.14.0')
30
30
  s.add_dependency('json', '~> 2.0', '>= 2.0')
31
- s.add_dependency('puma', '~> 4.3', '>= 4.3.3')
31
+ s.add_dependency('puma', '>= 4.3.3', '< 6.0')
32
32
  s.add_dependency('sinatra', '~> 2.1', '>= 2.1.0')
33
33
  s.add_dependency('sinatra-cross_origin', '~> 0.4.0', '>= 0.4')
34
34
  s.add_development_dependency('coveralls', '~> 0.8', '>= 0.8.23')
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.13.0.0
4
+ version: 0.13.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Diego Rubin
@@ -9,148 +9,148 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-25 00:00:00.000000000 Z
12
+ date: 2021-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grpc
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.28'
21
18
  - - ">="
22
19
  - !ruby/object:Gem::Version
23
20
  version: 1.28.0
21
+ - - "~>"
22
+ - !ruby/object:Gem::Version
23
+ version: '1.28'
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: '1.28'
31
28
  - - ">="
32
29
  - !ruby/object:Gem::Version
33
30
  version: 1.28.0
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.28'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: grpc-tools
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.28'
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
40
  version: 1.28.0
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.28'
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - "~>"
49
- - !ruby/object:Gem::Version
50
- version: '1.28'
51
48
  - - ">="
52
49
  - !ruby/object:Gem::Version
53
50
  version: 1.28.0
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.28'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: httparty
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '0.14'
61
58
  - - ">="
62
59
  - !ruby/object:Gem::Version
63
60
  version: 0.14.0
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '0.14'
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - "~>"
69
- - !ruby/object:Gem::Version
70
- version: '0.14'
71
68
  - - ">="
72
69
  - !ruby/object:Gem::Version
73
70
  version: 0.14.0
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.14'
74
74
  - !ruby/object:Gem::Dependency
75
75
  name: json
76
76
  requirement: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - "~>"
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '2.0'
81
- - - ">="
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '2.0'
84
84
  type: :runtime
85
85
  prerelease: false
86
86
  version_requirements: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
90
  version: '2.0'
91
- - - ">="
91
+ - - "~>"
92
92
  - !ruby/object:Gem::Version
93
93
  version: '2.0'
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: puma
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  requirements:
98
- - - "~>"
99
- - !ruby/object:Gem::Version
100
- version: '4.3'
101
98
  - - ">="
102
99
  - !ruby/object:Gem::Version
103
100
  version: 4.3.3
101
+ - - "<"
102
+ - !ruby/object:Gem::Version
103
+ version: '6.0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '4.3'
111
108
  - - ">="
112
109
  - !ruby/object:Gem::Version
113
110
  version: 4.3.3
111
+ - - "<"
112
+ - !ruby/object:Gem::Version
113
+ version: '6.0'
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: sinatra
116
116
  requirement: !ruby/object:Gem::Requirement
117
117
  requirements:
118
- - - "~>"
119
- - !ruby/object:Gem::Version
120
- version: '2.1'
121
118
  - - ">="
122
119
  - !ruby/object:Gem::Version
123
120
  version: 2.1.0
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '2.1'
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '2.1'
131
128
  - - ">="
132
129
  - !ruby/object:Gem::Version
133
130
  version: 2.1.0
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: '2.1'
134
134
  - !ruby/object:Gem::Dependency
135
135
  name: sinatra-cross_origin
136
136
  requirement: !ruby/object:Gem::Requirement
137
137
  requirements:
138
- - - "~>"
139
- - !ruby/object:Gem::Version
140
- version: 0.4.0
141
138
  - - ">="
142
139
  - !ruby/object:Gem::Version
143
140
  version: '0.4'
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: 0.4.0
144
144
  type: :runtime
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
- - - "~>"
149
- - !ruby/object:Gem::Version
150
- version: 0.4.0
151
148
  - - ">="
152
149
  - !ruby/object:Gem::Version
153
150
  version: '0.4'
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: 0.4.0
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: coveralls
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -255,80 +255,80 @@ dependencies:
255
255
  name: rdoc
256
256
  requirement: !ruby/object:Gem::Requirement
257
257
  requirements:
258
- - - "~>"
258
+ - - ">="
259
259
  - !ruby/object:Gem::Version
260
260
  version: '6.0'
261
- - - ">="
261
+ - - "~>"
262
262
  - !ruby/object:Gem::Version
263
263
  version: '6.0'
264
264
  type: :development
265
265
  prerelease: false
266
266
  version_requirements: !ruby/object:Gem::Requirement
267
267
  requirements:
268
- - - "~>"
268
+ - - ">="
269
269
  - !ruby/object:Gem::Version
270
270
  version: '6.0'
271
- - - ">="
271
+ - - "~>"
272
272
  - !ruby/object:Gem::Version
273
273
  version: '6.0'
274
274
  - !ruby/object:Gem::Dependency
275
275
  name: reek
276
276
  requirement: !ruby/object:Gem::Requirement
277
277
  requirements:
278
- - - "~>"
278
+ - - ">="
279
279
  - !ruby/object:Gem::Version
280
280
  version: 5.4.0
281
- - - ">="
281
+ - - "~>"
282
282
  - !ruby/object:Gem::Version
283
283
  version: 5.4.0
284
284
  type: :development
285
285
  prerelease: false
286
286
  version_requirements: !ruby/object:Gem::Requirement
287
287
  requirements:
288
- - - "~>"
288
+ - - ">="
289
289
  - !ruby/object:Gem::Version
290
290
  version: 5.4.0
291
- - - ">="
291
+ - - "~>"
292
292
  - !ruby/object:Gem::Version
293
293
  version: 5.4.0
294
294
  - !ruby/object:Gem::Dependency
295
295
  name: rspec
296
296
  requirement: !ruby/object:Gem::Requirement
297
297
  requirements:
298
- - - "~>"
299
- - !ruby/object:Gem::Version
300
- version: '3.5'
301
298
  - - ">="
302
299
  - !ruby/object:Gem::Version
303
300
  version: 3.5.0
301
+ - - "~>"
302
+ - !ruby/object:Gem::Version
303
+ version: '3.5'
304
304
  type: :development
305
305
  prerelease: false
306
306
  version_requirements: !ruby/object:Gem::Requirement
307
307
  requirements:
308
- - - "~>"
309
- - !ruby/object:Gem::Version
310
- version: '3.5'
311
308
  - - ">="
312
309
  - !ruby/object:Gem::Version
313
310
  version: 3.5.0
311
+ - - "~>"
312
+ - !ruby/object:Gem::Version
313
+ version: '3.5'
314
314
  - !ruby/object:Gem::Dependency
315
315
  name: rubocop
316
316
  requirement: !ruby/object:Gem::Requirement
317
317
  requirements:
318
- - - "~>"
318
+ - - ">="
319
319
  - !ruby/object:Gem::Version
320
320
  version: 0.73.0
321
- - - ">="
321
+ - - "~>"
322
322
  - !ruby/object:Gem::Version
323
323
  version: 0.73.0
324
324
  type: :development
325
325
  prerelease: false
326
326
  version_requirements: !ruby/object:Gem::Requirement
327
327
  requirements:
328
- - - "~>"
328
+ - - ">="
329
329
  - !ruby/object:Gem::Version
330
330
  version: 0.73.0
331
- - - ">="
331
+ - - "~>"
332
332
  - !ruby/object:Gem::Version
333
333
  version: 0.73.0
334
334
  - !ruby/object:Gem::Dependency
@@ -375,22 +375,22 @@ dependencies:
375
375
  name: webmock
376
376
  requirement: !ruby/object:Gem::Requirement
377
377
  requirements:
378
- - - "~>"
379
- - !ruby/object:Gem::Version
380
- version: '2.1'
381
378
  - - ">="
382
379
  - !ruby/object:Gem::Version
383
380
  version: 2.1.0
381
+ - - "~>"
382
+ - !ruby/object:Gem::Version
383
+ version: '2.1'
384
384
  type: :development
385
385
  prerelease: false
386
386
  version_requirements: !ruby/object:Gem::Requirement
387
387
  requirements:
388
- - - "~>"
389
- - !ruby/object:Gem::Version
390
- version: '2.1'
391
388
  - - ">="
392
389
  - !ruby/object:Gem::Version
393
390
  version: 2.1.0
391
+ - - "~>"
392
+ - !ruby/object:Gem::Version
393
+ version: '2.1'
394
394
  description: Proxy for mocks API responses
395
395
  email: rubin.diego@gmail.com
396
396
  executables:
@@ -430,6 +430,8 @@ files:
430
430
  - spec/tshield/after_filter_spec.rb
431
431
  - spec/tshield/configuration_spec.rb
432
432
  - spec/tshield/controllers/requests_spec.rb
433
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
434
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
433
435
  - spec/tshield/fixtures/config/tshield-without-grpc.yml
434
436
  - spec/tshield/fixtures/config/tshield.yml
435
437
  - spec/tshield/fixtures/filters/example_filter.rb
@@ -460,23 +462,24 @@ required_rubygems_version: !ruby/object:Gem::Requirement
460
462
  - !ruby/object:Gem::Version
461
463
  version: '0'
462
464
  requirements: []
463
- rubyforge_project:
464
- rubygems_version: 2.6.14.4
465
+ rubygems_version: 3.0.3.1
465
466
  signing_key:
466
467
  specification_version: 4
467
468
  summary: Proxy for mocks API responses
468
469
  test_files:
469
- - spec/spec_helper.rb
470
+ - spec/tshield/controllers/requests_spec.rb
471
+ - spec/tshield/after_filter_spec.rb
472
+ - spec/tshield/configuration_spec.rb
473
+ - spec/tshield/fixtures/proto/test_services_pb.rb
474
+ - spec/tshield/fixtures/config/tshield-without-grpc.yml
475
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
476
+ - spec/tshield/fixtures/config/tshield.yml
477
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
478
+ - spec/tshield/fixtures/matching/example.json
479
+ - spec/tshield/fixtures/filters/example_filter.rb
470
480
  - spec/tshield/request_vcr_spec.rb
471
481
  - spec/tshield/sessions_spec.rb
472
- - spec/tshield/controllers/requests_spec.rb
473
- - spec/tshield/request_matching_spec.rb
474
482
  - spec/tshield/grpc_spec.rb
475
483
  - spec/tshield/options_spec.rb
476
- - spec/tshield/fixtures/proto/test_services_pb.rb
477
- - spec/tshield/fixtures/filters/example_filter.rb
478
- - spec/tshield/fixtures/matching/example.json
479
- - spec/tshield/fixtures/config/tshield.yml
480
- - spec/tshield/fixtures/config/tshield-without-grpc.yml
481
- - spec/tshield/configuration_spec.rb
482
- - spec/tshield/after_filter_spec.rb
484
+ - spec/tshield/request_matching_spec.rb
485
+ - spec/spec_helper.rb