sqreen 1.16.2 → 1.17.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
2
  SHA256:
3
- metadata.gz: 424c794c9315a7e1a0544fd6be427194ec7d7155e665ba86c1c3413306078941
4
- data.tar.gz: 815fa9b893dd2577360a0408cc44194879c9fb1bbe5074cdce6c8c8629e82704
3
+ metadata.gz: edfd8cc358ff6408be042a8d11d473b85b00c2a1cf80c97cf5b154a6fa7da037
4
+ data.tar.gz: f558c9aef036f11b3e20fe0f8d41d7020b7d302233a4385d7cb760a983e91116
5
5
  SHA512:
6
- metadata.gz: 9bc336364648476b1e6a0b6a3955215646c008a418b35f39abacc1cee9fccd5bab9374e8e90b444bc2a1482eebc25ddf463526154479acca14acc7605e438bdf
7
- data.tar.gz: 53433d834097073f8ec98dd4396243029fb55e60c675bb6da379d12090000cbb31be0a23e736a9cc70615dd5fe7991559cc4a3c3c884d02cbbe6e5c787e5b415
6
+ metadata.gz: aa39b3c2a3af1e2b2135dd735b736dce973eab3810cbbe7dc7d017d25ca69d7f309f9029e9f0281d51cd523f996f86c75963d83b77a2294f6a359f847305f100
7
+ data.tar.gz: daa34349243dc5a56abadff975c776098db0e1d520f15720bae17443b157cc586ba77bc954ab4c7687866dab4bd4b8607cb6fee4c2e9e3bd68cc9f7b46b78faf
data/README.md CHANGED
@@ -75,3 +75,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
75
75
  ## Contributing
76
76
 
77
77
  Bug reports and pull requests are welcome on GitHub at https://github.com/sqreen/RubyAgent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
78
+
79
+ ## LICENSE
80
+
81
+ Sqreen for Ruby is free-to-use, proprietary software.
82
+
@@ -18,14 +18,21 @@ require 'thread'
18
18
 
19
19
  Sqreen.framework.on_start do |framework|
20
20
  if Sqreen.framework.on_pre_fork_preload?
21
+ Sqreen.log.debug "Sqreen detected a forking server with preloading"
21
22
  next
23
+ else
24
+ Sqreen.log.debug "Sqreen detected a single-process server"
22
25
  end
23
26
  Thread.new do
24
27
  begin
25
28
  runner = nil
29
+ Sqreen.log.debug("Reading configuration")
26
30
  configuration = Sqreen.config_init(framework)
27
- Sqreen.log.debug("Starting Sqreen #{Sqreen::VERSION}")
28
31
  framework.sqreen_configuration = configuration
32
+ Sqreen.log.debug("Initializing logs")
33
+ Sqreen.log_init
34
+ Sqreen.log.debug("Starting Sqreen #{Sqreen::VERSION}")
35
+ warn "[#{Process.pid}] Sqreen logging at level #{Sqreen.log.instance_eval { @logger }.level} to #{Sqreen.log.instance_eval { @logger }.instance_eval { @logdev.filename }}"
29
36
  prevent_startup = Sqreen.framework.prevent_startup
30
37
  if !prevent_startup
31
38
  runner = Sqreen::Runner.new(configuration, framework)
@@ -38,33 +45,33 @@ Sqreen.framework.on_start do |framework|
38
45
  rescue Sqreen::TokenInvalidException
39
46
  Sqreen.log.error "Sorry but your Sqreen token appears to be invalid.\nYour application is NOT currently protected by Sqreen.\n\nHave you correctly filled your config/sqreen.yml?\n\n"
40
47
  rescue Exception => e
41
- Sqreen.log.error e.inspect
42
- Sqreen.log.debug e.backtrace.join("\n")
48
+ Sqreen.log.debug("General exception caught: #{e.inspect}")
49
+ Sqreen.log.debug e.backtrace
43
50
  if runner
44
- # immediately post exception
51
+ Sqreen.log.debug("Immediately posting exception for runner #{runner.inspect}")
45
52
  runner.session.post_sqreen_exception(Sqreen::RemoteException.new(e))
46
- Sqreen.log.debug("runner = #{runner.inspect}")
47
53
  begin
48
54
  runner.remove_instrumentation
49
- rescue => remove_exception
50
- Sqreen.log.debug(remove_exception.inspect)
51
- # We did not manage to remove instrumentation, state is unclear:
52
- # terminate thread
55
+ rescue => e
56
+ Sqreen.log.debug("Unexpected exception when removing instrumentation: #{e.inspect}")
57
+ Sqreen.log.debug e.backtrace
58
+ Sqreen.log.error("Terminating Sqreen thread")
53
59
  return nil
54
60
  end
55
61
  begin
56
62
  runner.logout(false)
57
- rescue => logout_exception
58
- Sqreen.log.debug(logout_exception.inspect)
63
+ rescue StandardError => e
64
+ Sqreen.log.debug("Unexpected exception when logging out: #{remove_exception.inspect}")
65
+ Sqreen.log.debug(e.backtrace)
59
66
  nil
60
67
  end
61
68
  end
62
69
  # Wait a few seconds before retrying
63
70
  delay = rand(120)
64
- Sqreen.log.debug("Sleeping #{delay} seconds before retry")
71
+ Sqreen.log.debug("Sleeping #{delay} seconds before restarting Sqreen thread")
65
72
  sleep(delay)
66
73
  retry
67
74
  end
68
- Sqreen.log.debug("shutting down Sqreen #{Sqreen::VERSION}")
75
+ Sqreen.log.debug("Shutting down Sqreen #{Sqreen::VERSION}")
69
76
  end
70
77
  end unless Sqreen::to_bool(ENV['SQREEN_DISABLE'])
@@ -96,6 +96,8 @@ module Sqreen
96
96
  if path
97
97
  file_config = parse_configuration_file(path)
98
98
  @config.merge!(file_config)
99
+ else
100
+ Sqreen.log.warn("could not find sqreen configuration file")
99
101
  end
100
102
 
101
103
  env_config = from_environment
@@ -162,8 +164,17 @@ module Sqreen
162
164
  protected
163
165
 
164
166
  def config_file_from_env
165
- path = ENV[Sqreen::CONFIG_FILE_BY_ENV]
166
- return path if path && File.exist?(path)
167
+ return unless (path = ENV[Sqreen::CONFIG_FILE_BY_ENV])
168
+
169
+ path = File.expand_path(path)
170
+
171
+ unless File.exist?(path)
172
+ Sqreen.log.warn("could not find sqreen configuration file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'")
173
+ end
174
+
175
+ Sqreen.log.info("using config file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'")
176
+
177
+ path
167
178
  end
168
179
 
169
180
  def local_config_file
@@ -57,10 +57,17 @@ module Sqreen
57
57
  else
58
58
  res[:request] = {}
59
59
  end
60
+ if payload['response']
61
+ res[:response] = payload['response'].dup
62
+ else
63
+ res[:response] = {}
64
+ end
60
65
 
61
66
  res[:request][:parameters] = payload['params'] if payload['params']
62
67
  res[:request][:headers] = payload['headers'] if payload['headers']
63
68
 
69
+ res = Sqreen::EncodingSanitizer.sanitize(res)
70
+
64
71
  if @redactor
65
72
  res[:request] = @redactor.redact(res[:request])
66
73
  end
@@ -108,6 +115,27 @@ module Sqreen
108
115
  end
109
116
  end
110
117
 
118
+ class EncodingSanitizer
119
+ def self.sanitize(obj)
120
+ case obj
121
+ when String
122
+ sanitize_string(obj)
123
+ when Array
124
+ obj.map { |e| sanitize(e) }
125
+ when Hash
126
+ obj.each_with_object({}) { |(k, v), h| h[k] = sanitize(v) }
127
+ else
128
+ obj
129
+ end
130
+ end
131
+
132
+ def self.sanitize_string(s)
133
+ return s if s.encoding.name == 'UTF-8' && s.valid_encoding?
134
+
135
+ s.encode('UTF-16', :invalid => :replace, :undef => :replace).encode('UTF-8')
136
+ end
137
+ end
138
+
111
139
  # For redacting sensitive data and avoid having it sent to our servers
112
140
  class SensitiveDataRedactor
113
141
  DEFAULT_SENSITIVE_KEYS = Set.new(%w[password secret passwd authorization api_key apikey access_token]).freeze
@@ -20,7 +20,9 @@ module Sqreen
20
20
  require 'sqreen/frameworks/rails3'
21
21
  Sqreen::Frameworks::Rails3Framework
22
22
  else
23
- raise "Rails version #{Rails.version} not supported"
23
+ Sqreen.log.warn "Detected unsupported Rails version #{Rails.version}, but continuing"
24
+ require 'sqreen/frameworks/rails'
25
+ Sqreen::Frameworks::RailsFramework
24
26
  end
25
27
  when defined?(::Sinatra)
26
28
  require 'sqreen/frameworks/sinatra'
@@ -29,8 +31,7 @@ module Sqreen
29
31
  require 'sqreen/frameworks/sqreen_test'
30
32
  Sqreen::Frameworks::SqreenTestFramework
31
33
  else
32
- # FIXME: use sqreen logger before configuration?
33
- STDERR.puts "Error: cannot find any framework\n"
34
+ Sqreen.log.error "Error: cannot find any framework\n"
34
35
  require 'sqreen/frameworks/generic'
35
36
  Sqreen::Frameworks::GenericFramework
36
37
  end
@@ -44,6 +44,10 @@ module Sqreen
44
44
  ENV['RACK_ENV'] == 'development'
45
45
  end
46
46
 
47
+ def test?
48
+ ENV['RACK_ENV'] == 'test'
49
+ end
50
+
47
51
  PREFERRED_IP_HEADERS = %w[HTTP_X_FORWARDED_FOR HTTP_X_REAL_IP
48
52
  HTTP_CLIENT_IP HTTP_X_FORWARDED
49
53
  HTTP_X_CLUSTER_CLIENT_IP HTTP_FORWARDED_FOR
@@ -161,6 +165,23 @@ module Sqreen
161
165
  }
162
166
  end
163
167
 
168
+ def response_infos
169
+ return {} if response.nil?
170
+
171
+ content_type = response.header['Content-Type']
172
+ content_length = begin
173
+ Integer(response.header['Content-Length'])
174
+ rescue ArgumentError, TypeError
175
+ nil
176
+ end
177
+
178
+ {
179
+ :status => response.status,
180
+ :content_type => content_type,
181
+ :content_length => content_length,
182
+ }
183
+ end
184
+
164
185
  # Request URL path
165
186
  def request_path
166
187
  req = request
@@ -257,17 +278,26 @@ module Sqreen
257
278
  SharedStorage.set(:request_overtime, nil)
258
279
  end
259
280
 
281
+ def store_response(rv, _env)
282
+ SharedStorage.set(:response, Rack::Response.new([], rv[0], rv[1]))
283
+ end
284
+
260
285
  # Get the currently stored request
261
286
  def request
262
287
  SharedStorage.get(:request)
263
288
  end
264
289
 
290
+ def response
291
+ SharedStorage.get(:response)
292
+ end
293
+
265
294
  # Cleanup request context
266
295
  def clean_request
267
296
  payload_creator = Sqreen::PayloadCreator.new(self)
268
297
  close_request_record(Sqreen.queue, Sqreen.observations_queue, payload_creator)
269
298
  self.remaining_perf_budget = nil
270
299
  SharedStorage.set(:request, nil)
300
+ SharedStorage.set(:response, nil)
271
301
  SharedStorage.set(:xss_params, nil)
272
302
  SharedStorage.set(:whitelisted, nil)
273
303
  SharedStorage.set(:request_overtime, nil)
@@ -397,7 +427,7 @@ module Sqreen
397
427
  each_key_value_for_hash(p) do |value|
398
428
  next unless value.is_a?(String)
399
429
  next if value.size < 5
400
- value = value.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
430
+ value = value.dup.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
401
431
  next if regexp && !regexp.match?(value)
402
432
  parm << value
403
433
  end
@@ -415,7 +445,7 @@ module Sqreen
415
445
  each_key_value_for_hash(p) do |value|
416
446
  next unless value.is_a?(String)
417
447
  next if value.size < 5
418
- value = value.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
448
+ value = value.dup.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8) unless value.valid_encoding?
419
449
  next if regexp && !regexp.match(value)
420
450
  parm << value
421
451
  end
@@ -564,7 +594,13 @@ module Sqreen
564
594
  end
565
595
 
566
596
  def split_ip_addresses(ip_addresses)
567
- ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : []
597
+ return [] unless ip_addresses
598
+
599
+ r = ip_addresses.strip.split(/[,\s]+/)
600
+ r.map! do |ip|
601
+ m = /^(?:(?<ip>.*\..*)\:|\[(?<ip>.*)\]\:)/.match(ip)
602
+ m ? m[:ip] : ip
603
+ end
568
604
  end
569
605
 
570
606
  def valid_ip?(ip)
@@ -415,36 +415,31 @@ module Sqreen
415
415
  end
416
416
 
417
417
  def override_class_method(klass, meth)
418
- # FIXME: This is somehow ugly. We should reduce the amount of
419
- # `evaled` code.
420
- str = " class << #{klass}
418
+ original = meth.to_sym
419
+ saved_meth_name = get_saved_method_name(meth).to_sym
420
+ new_method = "#{meth}_modified".to_sym
421
421
 
422
- original = '#{meth}'.to_sym
423
- saved_meth_name = '#{get_saved_method_name(meth)}'.to_sym
424
- new_method = '#{meth}_modified'.to_sym
422
+ klass.singleton_class.instance_eval do
423
+ alias_method saved_meth_name, original
425
424
 
426
- alias_method saved_meth_name, original
425
+ p = Instrumentation.define_callback_method(original, saved_meth_name, klass)
426
+ define_method(new_method, p)
427
427
 
428
- p = Instrumentation.define_callback_method(original, saved_meth_name,
429
- #{klass})
430
- define_method(new_method, p)
428
+ private new_method
431
429
 
432
- private new_method
430
+ method_kind = nil
431
+ if public_method_defined?(original)
432
+ method_kind = :public
433
+ elsif protected_method_defined?(original)
434
+ method_kind = :protected
435
+ elsif private_method_defined?(original)
436
+ method_kind = :private
437
+ end
433
438
 
434
- method_kind = nil
435
- case
436
- when public_method_defined?(original)
437
- method_kind = :public
438
- when protected_method_defined?(original)
439
- method_kind = :protected
440
- when private_method_defined?(original)
441
- method_kind = :private
439
+ alias_method original, new_method
440
+ send(method_kind, original)
441
+ private saved_meth_name
442
442
  end
443
- alias_method original, new_method
444
- send(method_kind, original)
445
- private saved_meth_name
446
- end "
447
- eval str
448
443
  end
449
444
 
450
445
  def unoverride_instance_method(obj, meth)
@@ -516,19 +511,19 @@ module Sqreen
516
511
  # WARNING We do not actually remove `meth`
517
512
  def unoverride_class_method(klass, meth)
518
513
  saved_meth_name = get_saved_method_name(meth)
514
+ method_kind = nil
519
515
 
520
- eval "method_kind = nil; class << #{klass}
521
- case
522
- when public_method_defined?(#{meth.to_sym.inspect})
523
- method_kind = :public
524
- when protected_method_defined?(original)
525
- method_kind = :protected
526
- when private_method_defined?(#{meth.to_sym.inspect})
527
- method_kind = :private
528
- end
529
- alias_method #{meth.to_sym.inspect}, #{saved_meth_name.to_sym.inspect}
530
- send(method_kind, #{meth.to_sym.inspect})
531
- end "
516
+ klass.singleton_class.instance_eval do
517
+ if public_method_defined?(meth.to_sym)
518
+ method_kind = :public
519
+ elsif protected_method_defined?(original)
520
+ method_kind = :protected
521
+ elsif private_method_defined?(meth.to_sym)
522
+ method_kind = :private
523
+ end
524
+ alias_method meth.to_sym, saved_meth_name.to_sym
525
+ send(method_kind, meth.to_sym)
526
+ end
532
527
  end
533
528
 
534
529
  if RUBY_VERSION < '1.9'
@@ -9,18 +9,20 @@ require 'sqreen/performance_notifications/log_performance'
9
9
  require 'sqreen/configuration'
10
10
 
11
11
  module Sqreen
12
- def self::log
13
- @logger ||= nil
14
- return @logger unless @logger.nil?
15
- return NoopLogger.instance unless Sqreen.configured?
12
+ def self.log_init
16
13
  @logger = Logger.new(
17
14
  Sqreen.config_get(:log_level).to_s.upcase,
18
15
  Sqreen.config_get(:log_location)
19
16
  )
17
+ DeferredLogger.instance.flush_to(@logger.instance_eval { @logger })
20
18
  rescue => e
21
19
  warn "Sqreen logger exception: #{e}"
22
20
  end
23
21
 
22
+ def self::log
23
+ @logger || DeferredLogger.instance
24
+ end
25
+
24
26
  # Ruby default formatter modified to display current thread_id
25
27
  class FormatterWithTid
26
28
  Format = "%s, [%s#%d.%s] %5s -- %s: %s\n".freeze
@@ -113,7 +115,7 @@ module Sqreen
113
115
  end
114
116
 
115
117
  def create_error_logger
116
- @error_logger = ::Logger.new(STDERR)
118
+ @error_logger = Kernel.const_defined?('MiniTest') ? NullLogger.instance : ::Logger.new(STDERR)
117
119
  enforce_log_format(@error_logger)
118
120
  end
119
121
 
@@ -122,7 +124,7 @@ module Sqreen
122
124
  end
123
125
  end
124
126
 
125
- class NoopLogger
127
+ class NullLogger
126
128
  include Singleton
127
129
 
128
130
  def debug(_msg = nil); end
@@ -132,5 +134,54 @@ module Sqreen
132
134
  def warn(_msg = nil); end
133
135
 
134
136
  def error(_msg = nil); end
137
+
138
+ def formatter=(_); end
139
+ end
140
+
141
+ class DeferredLogger
142
+ include Singleton
143
+
144
+ def initialize
145
+ @buffer = StringIO.new
146
+ @logger = ::Logger.new(@buffer)
147
+ end
148
+
149
+ def debug(msg = nil, &block)
150
+ @logger.debug(msg, &block)
151
+ end
152
+
153
+ def info(msg = nil, &block)
154
+ @logger.info(msg, &block)
155
+ end
156
+
157
+ def warn(msg = nil, &block)
158
+ @logger.warn(msg, &block)
159
+ end
160
+
161
+ def error(msg = nil, &block)
162
+ @logger.error(msg, &block)
163
+ end
164
+
165
+ def formatter=(value)
166
+ @logger.formatter = value
167
+ end
168
+
169
+ def flush_to(logger)
170
+ logger.instance_eval { @logdev }.write(read).tap { reset }
171
+ end
172
+
173
+ private
174
+
175
+ def read
176
+ @buffer.rewind
177
+ @buffer.read
178
+ end
179
+
180
+ def reset
181
+ buffer = StringIO.new
182
+ logger = ::Logger.new(buffer)
183
+ logger.formatter = @logger.formatter
184
+ @buffer, @logger = buffer, logger
185
+ end
135
186
  end
136
187
  end
@@ -54,6 +54,7 @@ module Sqreen
54
54
 
55
55
  FULL_SECTIONS = {
56
56
  'request' => 'request_infos',
57
+ 'response' => 'response_infos',
57
58
  'params' => 'filtered_request_params',
58
59
  'headers' => 'ip_headers',
59
60
  'local' => 'local_infos',
@@ -64,6 +65,9 @@ module Sqreen
64
65
  'addr' => 'client_ip',
65
66
  'rid' => 'request_id',
66
67
  },
68
+ 'response' => {
69
+ 'status' => 'status',
70
+ },
67
71
  'local' => {
68
72
  'name' => 'hostname',
69
73
  },
@@ -30,7 +30,8 @@ module Sqreen
30
30
  advise_action(nil)
31
31
  end
32
32
 
33
- def post(_rv, _inst, _args, _budget = nil, &_block)
33
+ def post(rv, _inst, args, _budget = nil, &_block)
34
+ framework.store_response(rv, args[0])
34
35
  framework.clean_request
35
36
  advise_action(nil)
36
37
  end
@@ -228,16 +228,18 @@ module Sqreen
228
228
 
229
229
 
230
230
  def setup_instrumentation(context_infos = {})
231
- Sqreen.log.info 'setup instrumentation'
231
+ Sqreen.log.info 'Setting up instrumentation'
232
232
  rulespack_id, rules = load_rules(context_infos)
233
233
  @framework.instrument_when_ready!(instrumenter, rules)
234
+ Sqreen.log.info 'Instrumentation set up'
234
235
  rulespack_id.to_s
235
236
  end
236
237
 
237
238
  def remove_instrumentation(_context_infos = {})
238
- Sqreen.log.debug 'removing instrumentation'
239
+ Sqreen.log.debug 'Removing instrumentation'
239
240
  instrumenter.remove_all_callbacks
240
241
  Sqreen::Actions::Repository.instance.clear
242
+ Sqreen.log.debug 'Instrumentation removed'
241
243
  true
242
244
  end
243
245
 
@@ -419,6 +421,7 @@ module Sqreen
419
421
 
420
422
  def logout(retrying = true)
421
423
  return unless session
424
+ Sqreen.log.debug("Logging out")
422
425
  if @framework.development?
423
426
  @running = false
424
427
  return
@@ -440,7 +443,13 @@ module Sqreen
440
443
  if exit_from_sinatra_startup? && try_again
441
444
  register_exit_cb(false)
442
445
  else
443
- logout
446
+ begin
447
+ logout
448
+ rescue StandardError => e
449
+ Sqreen.log.debug(e.inspect)
450
+ Sqreen.log.debug(e.backtrace)
451
+ nil
452
+ end
444
453
  end
445
454
  end
446
455
  end
@@ -89,16 +89,6 @@ module Sqreen
89
89
  @http.finish if connected?
90
90
  end
91
91
 
92
- NET_ERRORS = [Timeout::Error,
93
- Errno::EINVAL,
94
- Errno::ECONNRESET,
95
- Errno::ECONNREFUSED,
96
- EOFError,
97
- Net::HTTPBadResponse,
98
- Net::HTTPHeaderSyntaxError,
99
- SocketError,
100
- Net::ProtocolError].freeze
101
-
102
92
  def connect
103
93
  return if connected?
104
94
  Sqreen.log.warn "connection to #{@server_url}..."
@@ -106,7 +96,9 @@ module Sqreen
106
96
  @conn_retry = 0
107
97
  begin
108
98
  @con = @http.start
109
- rescue *NET_ERRORS
99
+ rescue StandardError => e
100
+ Sqreen.log.debug { "Caught exception during request: #{e.inspect}" }
101
+ Sqreen.log.debug { e.backtrace }
110
102
  Sqreen.log.debug "Cannot connect, retry in #{RETRY_CONNECT_SECONDS} seconds"
111
103
  sleep RETRY_CONNECT_SECONDS
112
104
  @conn_retry += 1
@@ -133,16 +125,18 @@ module Sqreen
133
125
  end
134
126
 
135
127
  def resiliently(retry_request_seconds, max_retry, current_retry = 0)
128
+ connect unless connected?
136
129
  return yield
137
130
  rescue => e
138
- Sqreen.log.debug { e.inspect }
131
+ Sqreen.log.debug { "Caught exception during request: #{e.inspect}" }
132
+ Sqreen.log.debug { e.backtrace }
139
133
 
140
134
  current_retry += 1
141
135
 
142
136
  raise e if current_retry >= max_retry || e.is_a?(Sqreen::NotImplementedYet)
143
137
 
144
138
  sleep_delay = [MAX_DELAY, retry_request_seconds * current_retry].min
145
- Sqreen.log.debug format('Sleeping %ds', sleep_delay)
139
+ Sqreen.log.debug format("Sleeping %ds before retry #{current_retry}/#{max_retry}", sleep_delay)
146
140
  sleep(sleep_delay)
147
141
 
148
142
  retry
@@ -159,7 +153,6 @@ module Sqreen
159
153
  end
160
154
 
161
155
  def do_http_request(method, path, data, headers = {}, max_retry = 2)
162
- connect unless connected?
163
156
  now = Time.now.utc
164
157
  headers['X-Session-Key'] = @session_id if @session_id
165
158
  headers['X-Sqreen-Time'] = now.to_f.to_s
@@ -170,6 +163,7 @@ module Sqreen
170
163
  @req_nb,
171
164
  Time.now.utc.to_f)
172
165
  headers['Content-Type'] = 'application/json'
166
+ headers['Accept'] = 'application/json'
173
167
  if request_compression && !method.casecmp(:GET).zero?
174
168
  headers['Content-Encoding'] = 'gzip'
175
169
  end
@@ -198,11 +192,15 @@ module Sqreen
198
192
  raise Sqreen::NotImplementedYet
199
193
  end
200
194
  end
201
-
202
195
  if json && json.body
203
- res = JSON.parse(json.body)
204
- unless res['status']
205
- Sqreen.log.debug(format('Cannot %s %s.', method, path))
196
+ if json['Content-Type'] && json['Content-Type'].start_with?('application/json')
197
+ res = JSON.parse(json.body)
198
+ unless res['status']
199
+ Sqreen.log.debug(format('Cannot %s %s. Parsed response body was: %s', method, path, res.inspect))
200
+ end
201
+ else
202
+ Sqreen.log.debug "Unexpected response Content-Type: #{json['Content-Type']}"
203
+ Sqreen.log.debug "Unexpected response body: #{json.body.inspect}"
206
204
  end
207
205
  else
208
206
  Sqreen.log.debug 'warning: empty return value'
@@ -283,7 +281,7 @@ module Sqreen
283
281
  # @param exception [RemoteException] Exception and context to be sent over
284
282
  def post_sqreen_exception(exception)
285
283
  post('sqreen_exception', exception.to_hash, {}, 5)
286
- rescue *NET_ERRORS => e
284
+ rescue StandardError => e
287
285
  Sqreen.log.warn(format('Could not post exception (network down? %s) %s',
288
286
  e.inspect,
289
287
  exception.to_hash.inspect))
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
2
  # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
3
  module Sqreen
4
- VERSION = '1.16.2'.freeze
4
+ VERSION = '1.17.0'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqreen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.2
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2019-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sq_mini_racer