rollbar 2.8.3 → 3.6.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.
Files changed (238) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +18 -0
  3. data/.github/pull_request_template.md +34 -0
  4. data/.github/workflows/ci.yml +67 -0
  5. data/.gitignore +3 -1
  6. data/.rubocop.yml +206 -7
  7. data/Appraisals +10 -10
  8. data/CHANGELOG.md +257 -3
  9. data/Gemfile +74 -13
  10. data/README.md +38 -833
  11. data/Rakefile +0 -0
  12. data/THANKS.md +1 -0
  13. data/data/rollbar.snippet.js +1 -1
  14. data/docs/configuration.md +64 -3
  15. data/docs/plugins.md +46 -0
  16. data/gemfiles/rails50.gemfile +56 -0
  17. data/gemfiles/rails51.gemfile +57 -0
  18. data/gemfiles/rails52.gemfile +56 -0
  19. data/gemfiles/rails60.gemfile +52 -0
  20. data/gemfiles/rails61.gemfile +52 -0
  21. data/gemfiles/rails70.gemfile +52 -0
  22. data/gemfiles/rails71.gemfile +52 -0
  23. data/lib/generators/rollbar/rollbar_generator.rb +24 -20
  24. data/lib/generators/rollbar/templates/{initializer.rb → initializer.erb} +19 -5
  25. data/lib/rails/rollbar_runner.rb +26 -22
  26. data/lib/rollbar/capistrano.rb +78 -38
  27. data/lib/rollbar/capistrano3.rb +62 -1
  28. data/lib/rollbar/capistrano_tasks.rb +166 -0
  29. data/lib/rollbar/configuration.rb +291 -71
  30. data/lib/rollbar/delay/active_job.rb +17 -0
  31. data/lib/rollbar/delay/delayed_job.rb +23 -0
  32. data/lib/rollbar/delay/girl_friday.rb +4 -9
  33. data/lib/rollbar/delay/resque.rb +3 -6
  34. data/lib/rollbar/delay/shoryuken.rb +36 -0
  35. data/lib/rollbar/delay/sidekiq.rb +6 -8
  36. data/lib/rollbar/delay/sucker_punch.rb +17 -22
  37. data/lib/rollbar/delay/thread.rb +74 -3
  38. data/lib/rollbar/deploy.rb +91 -0
  39. data/lib/rollbar/encoding/encoder.rb +22 -11
  40. data/lib/rollbar/encoding.rb +2 -7
  41. data/lib/rollbar/exception_reporter.rb +36 -12
  42. data/lib/rollbar/item/backtrace.rb +118 -0
  43. data/lib/rollbar/item/frame.rb +121 -0
  44. data/lib/rollbar/item/locals.rb +103 -0
  45. data/lib/rollbar/item.rb +314 -0
  46. data/lib/rollbar/js.rb +0 -28
  47. data/lib/rollbar/json.rb +7 -55
  48. data/lib/rollbar/language_support.rb +7 -19
  49. data/lib/rollbar/lazy_store.rb +8 -12
  50. data/lib/rollbar/logger.rb +71 -0
  51. data/lib/rollbar/logger_proxy.rb +18 -1
  52. data/lib/rollbar/middleware/js/json_value.rb +36 -0
  53. data/lib/rollbar/middleware/js.rb +297 -0
  54. data/lib/rollbar/middleware/rack/builder.rb +4 -4
  55. data/lib/rollbar/middleware/rack/test_session.rb +4 -4
  56. data/lib/rollbar/middleware/rack.rb +52 -0
  57. data/lib/rollbar/middleware/rails/rollbar.rb +19 -7
  58. data/lib/rollbar/middleware/rails/show_exceptions.rb +21 -9
  59. data/lib/rollbar/middleware/sinatra.rb +2 -40
  60. data/lib/rollbar/notifier/trace_with_bindings.rb +75 -0
  61. data/lib/rollbar/notifier.rb +913 -0
  62. data/lib/rollbar/plugin.rb +126 -0
  63. data/lib/rollbar/plugins/active_job.rb +54 -0
  64. data/lib/rollbar/plugins/basic_socket.rb +31 -0
  65. data/lib/rollbar/plugins/delayed_job/job_data.rb +50 -0
  66. data/lib/rollbar/plugins/delayed_job/plugin.rb +88 -0
  67. data/lib/rollbar/plugins/delayed_job.rb +12 -0
  68. data/lib/rollbar/plugins/error_context.rb +11 -0
  69. data/lib/rollbar/plugins/goalie.rb +65 -0
  70. data/lib/rollbar/plugins/rack.rb +18 -0
  71. data/lib/rollbar/plugins/rails/controller_methods.rb +56 -0
  72. data/lib/rollbar/plugins/rails/error_subscriber.rb +12 -0
  73. data/lib/rollbar/plugins/rails/railtie30.rb +18 -0
  74. data/lib/rollbar/plugins/rails/railtie32.rb +18 -0
  75. data/lib/rollbar/plugins/rails/railtie_mixin.rb +37 -0
  76. data/lib/rollbar/plugins/rails.rb +89 -0
  77. data/lib/rollbar/plugins/rake.rb +73 -0
  78. data/lib/rollbar/plugins/resque/failure.rb +39 -0
  79. data/lib/rollbar/plugins/resque.rb +11 -0
  80. data/lib/rollbar/plugins/sidekiq/plugin.rb +77 -0
  81. data/lib/rollbar/plugins/sidekiq.rb +37 -0
  82. data/lib/rollbar/plugins/thread.rb +14 -0
  83. data/lib/rollbar/plugins/validations.rb +45 -0
  84. data/lib/rollbar/plugins.rb +47 -0
  85. data/lib/rollbar/rails.rb +0 -1
  86. data/lib/rollbar/rake_tasks.rb +4 -66
  87. data/lib/rollbar/request_data_extractor.rb +157 -117
  88. data/lib/rollbar/rollbar_test.rb +38 -0
  89. data/lib/rollbar/scrubbers/params.rb +133 -0
  90. data/lib/rollbar/scrubbers/url.rb +90 -35
  91. data/lib/rollbar/scrubbers.rb +13 -0
  92. data/lib/rollbar/truncation/frames_strategy.rb +2 -1
  93. data/lib/rollbar/truncation/min_body_strategy.rb +3 -4
  94. data/lib/rollbar/truncation/mixin.rb +1 -1
  95. data/lib/rollbar/truncation/remove_any_key_strategy.rb +126 -0
  96. data/lib/rollbar/truncation/remove_extra_strategy.rb +37 -0
  97. data/lib/rollbar/truncation/remove_request_strategy.rb +21 -0
  98. data/lib/rollbar/truncation/strings_strategy.rb +6 -5
  99. data/lib/rollbar/truncation.rb +10 -4
  100. data/lib/rollbar/util/hash.rb +37 -6
  101. data/lib/rollbar/util/ip_anonymizer.rb +33 -0
  102. data/lib/rollbar/util/ip_obfuscator.rb +1 -1
  103. data/lib/rollbar/util.rb +101 -55
  104. data/lib/rollbar/version.rb +1 -1
  105. data/lib/rollbar.rb +91 -879
  106. data/lib/tasks/benchmark.rake +104 -0
  107. data/lib/tasks/tasks.rake +3 -3
  108. data/rollbar.gemspec +21 -32
  109. data/spec/support/rollbar_api.rb +67 -0
  110. metadata +78 -439
  111. data/.travis.yml +0 -155
  112. data/gemfiles/rails30.gemfile +0 -20
  113. data/gemfiles/rails31.gemfile +0 -16
  114. data/gemfiles/rails32.gemfile +0 -17
  115. data/gemfiles/rails40.gemfile +0 -17
  116. data/gemfiles/rails41.gemfile +0 -15
  117. data/gemfiles/rails42.gemfile +0 -15
  118. data/lib/rollbar/active_job.rb +0 -11
  119. data/lib/rollbar/active_record_extension.rb +0 -14
  120. data/lib/rollbar/core_ext/basic_socket.rb +0 -7
  121. data/lib/rollbar/core_ext/thread.rb +0 -9
  122. data/lib/rollbar/delayed_job.rb +0 -78
  123. data/lib/rollbar/encoding/legacy_encoder.rb +0 -20
  124. data/lib/rollbar/goalie.rb +0 -33
  125. data/lib/rollbar/js/frameworks/rails.rb +0 -29
  126. data/lib/rollbar/js/frameworks.rb +0 -6
  127. data/lib/rollbar/js/middleware.rb +0 -129
  128. data/lib/rollbar/js/version.rb +0 -5
  129. data/lib/rollbar/json/default.rb +0 -11
  130. data/lib/rollbar/json/oj.rb +0 -15
  131. data/lib/rollbar/rack.rb +0 -9
  132. data/lib/rollbar/rails/controller_methods.rb +0 -40
  133. data/lib/rollbar/railtie.rb +0 -46
  134. data/lib/rollbar/rake.rb +0 -38
  135. data/lib/rollbar/sidekiq.rb +0 -40
  136. data/lib/rollbar/tasks/rollbar.cap +0 -45
  137. data/spec/cacert.pem +0 -3988
  138. data/spec/controllers/home_controller_spec.rb +0 -455
  139. data/spec/delay/sidekiq_spec.rb +0 -61
  140. data/spec/delay/sucker_punch_spec.rb +0 -25
  141. data/spec/delayed/backend/test.rb +0 -139
  142. data/spec/delayed/serialization/test.rb +0 -0
  143. data/spec/dummyapp/.gitignore +0 -73
  144. data/spec/dummyapp/Rakefile +0 -7
  145. data/spec/dummyapp/app/assets/javascripts/application.js +0 -3
  146. data/spec/dummyapp/app/assets/stylesheets/application.css.scss +0 -37
  147. data/spec/dummyapp/app/controllers/application_controller.rb +0 -3
  148. data/spec/dummyapp/app/controllers/home_controller.rb +0 -60
  149. data/spec/dummyapp/app/controllers/users_controller.rb +0 -17
  150. data/spec/dummyapp/app/helpers/.gitkeep +0 -0
  151. data/spec/dummyapp/app/mailers/.gitkeep +0 -0
  152. data/spec/dummyapp/app/models/.gitkeep +0 -0
  153. data/spec/dummyapp/app/models/user.rb +0 -7
  154. data/spec/dummyapp/app/views/devise/registrations/edit.html.erb +0 -27
  155. data/spec/dummyapp/app/views/devise/registrations/new.html.erb +0 -20
  156. data/spec/dummyapp/app/views/devise/shared/_links.html.erb +0 -25
  157. data/spec/dummyapp/app/views/home/cause_exception.html.erb +0 -1
  158. data/spec/dummyapp/app/views/home/index.html.erb +0 -4
  159. data/spec/dummyapp/app/views/home/report_exception.html.erb +0 -1
  160. data/spec/dummyapp/app/views/js/test.html.erb +0 -1
  161. data/spec/dummyapp/app/views/layouts/_messages.html.erb +0 -5
  162. data/spec/dummyapp/app/views/layouts/_navigation.html.erb +0 -21
  163. data/spec/dummyapp/app/views/layouts/application.html.erb +0 -25
  164. data/spec/dummyapp/app/views/layouts/simple.html.erb +0 -18
  165. data/spec/dummyapp/app/views/users/index.html.erb +0 -8
  166. data/spec/dummyapp/app/views/users/show.html.erb +0 -3
  167. data/spec/dummyapp/config/application.rb +0 -59
  168. data/spec/dummyapp/config/boot.rb +0 -10
  169. data/spec/dummyapp/config/database.yml +0 -25
  170. data/spec/dummyapp/config/environment.rb +0 -5
  171. data/spec/dummyapp/config/environments/development.rb +0 -37
  172. data/spec/dummyapp/config/environments/production.rb +0 -67
  173. data/spec/dummyapp/config/environments/test.rb +0 -37
  174. data/spec/dummyapp/config/initializers/backtrace_silencers.rb +0 -7
  175. data/spec/dummyapp/config/initializers/inflections.rb +0 -15
  176. data/spec/dummyapp/config/initializers/mime_types.rb +0 -5
  177. data/spec/dummyapp/config/initializers/rollbar.rb +0 -23
  178. data/spec/dummyapp/config/initializers/secret_token.rb +0 -7
  179. data/spec/dummyapp/config/initializers/session_store.rb +0 -8
  180. data/spec/dummyapp/config/initializers/wrap_parameters.rb +0 -16
  181. data/spec/dummyapp/config/locales/devise.en.yml +0 -58
  182. data/spec/dummyapp/config/locales/en.yml +0 -5
  183. data/spec/dummyapp/config/routes.rb +0 -17
  184. data/spec/dummyapp/config.ru +0 -4
  185. data/spec/dummyapp/db/migrate/20121121184652_devise_create_users.rb +0 -46
  186. data/spec/dummyapp/db/migrate/20121121184654_add_name_to_users.rb +0 -5
  187. data/spec/dummyapp/db/schema.rb +0 -35
  188. data/spec/dummyapp/db/seeds.rb +0 -12
  189. data/spec/dummyapp/lib/assets/.gitkeep +0 -0
  190. data/spec/dummyapp/public/404.html +0 -26
  191. data/spec/dummyapp/public/422.html +0 -26
  192. data/spec/dummyapp/public/500.html +0 -25
  193. data/spec/dummyapp/public/favicon.ico +0 -0
  194. data/spec/dummyapp/script/rails +0 -6
  195. data/spec/fixtures/file1 +0 -1
  196. data/spec/fixtures/file2 +0 -1
  197. data/spec/fixtures/payloads/message.json +0 -25
  198. data/spec/fixtures/payloads/sample.trace.json +0 -275
  199. data/spec/fixtures/payloads/sample.trace_chain.json +0 -530
  200. data/spec/generators/rollbar/rollbar_generator_spec.rb +0 -24
  201. data/spec/requests/home_spec.rb +0 -49
  202. data/spec/rollbar/active_job_spec.rb +0 -33
  203. data/spec/rollbar/configuration_spec.rb +0 -24
  204. data/spec/rollbar/delay/girl_friday_spec.rb +0 -41
  205. data/spec/rollbar/delay/resque_spec.rb +0 -37
  206. data/spec/rollbar/delay/thread_spec.rb +0 -27
  207. data/spec/rollbar/delayed_job/job_data.rb +0 -35
  208. data/spec/rollbar/delayed_job_spec.rb +0 -90
  209. data/spec/rollbar/encoding/encoder_spec.rb +0 -63
  210. data/spec/rollbar/js/frameworks/rails_spec.rb +0 -19
  211. data/spec/rollbar/js/middleware_spec.rb +0 -162
  212. data/spec/rollbar/json/oj_spec.rb +0 -18
  213. data/spec/rollbar/json_spec.rb +0 -110
  214. data/spec/rollbar/lazy_store_spec.rb +0 -99
  215. data/spec/rollbar/logger_proxy_spec.rb +0 -34
  216. data/spec/rollbar/middleware/rack/builder_spec.rb +0 -151
  217. data/spec/rollbar/middleware/sinatra_spec.rb +0 -197
  218. data/spec/rollbar/rake_spec.rb +0 -34
  219. data/spec/rollbar/request_data_extractor_spec.rb +0 -82
  220. data/spec/rollbar/scrubbers/url_spec.rb +0 -111
  221. data/spec/rollbar/sidekiq_spec.rb +0 -90
  222. data/spec/rollbar/truncation/frames_strategy_spec.rb +0 -70
  223. data/spec/rollbar/truncation/min_body_strategy_spec.rb +0 -57
  224. data/spec/rollbar/truncation/strings_strategy_spec.rb +0 -89
  225. data/spec/rollbar/truncation_spec.rb +0 -27
  226. data/spec/rollbar/util/hash_spec.rb +0 -22
  227. data/spec/rollbar/util_spec.rb +0 -19
  228. data/spec/rollbar_bc_spec.rb +0 -380
  229. data/spec/rollbar_spec.rb +0 -2067
  230. data/spec/spec_helper.rb +0 -49
  231. data/spec/support/cause_exception.rb +0 -1
  232. data/spec/support/encoding_helpers.rb +0 -8
  233. data/spec/support/encodings/iso_8859_9 +0 -1
  234. data/spec/support/fixture_helpers.rb +0 -10
  235. data/spec/support/get_ip_raising.rb +0 -7
  236. data/spec/support/helpers.rb +0 -5
  237. data/spec/support/notifier_helpers.rb +0 -36
  238. data/spec/support/shared_contexts.rb +0 -12
@@ -1,19 +1,28 @@
1
1
  require 'rack'
2
2
  require 'tempfile'
3
3
 
4
+ require 'rollbar/scrubbers'
4
5
  require 'rollbar/scrubbers/url'
6
+ require 'rollbar/scrubbers/params'
5
7
  require 'rollbar/util/ip_obfuscator'
8
+ require 'rollbar/util/ip_anonymizer'
9
+ require 'rollbar/json'
6
10
 
7
11
  module Rollbar
8
12
  module RequestDataExtractor
9
- SKIPPED_CLASSES = [Tempfile]
13
+ ALLOWED_HEADERS_REGEX = /^HTTP_|^CONTENT_TYPE$|^CONTENT_LENGTH$/.freeze
14
+ ALLOWED_BODY_PARSEABLE_METHODS = %w[POST PUT PATCH DELETE].freeze
10
15
 
11
16
  def extract_person_data_from_controller(env)
12
- if env.has_key? 'rollbar.person_data'
17
+ if env.key?('rollbar.person_data')
13
18
  person_data = env['rollbar.person_data'] || {}
14
19
  else
15
20
  controller = env['action_controller.instance']
16
- person_data = controller.rollbar_person_data rescue {}
21
+ person_data = begin
22
+ controller.rollbar_person_data
23
+ rescue StandardError
24
+ {}
25
+ end
17
26
  end
18
27
 
19
28
  person_data
@@ -21,48 +30,60 @@ module Rollbar
21
30
 
22
31
  def extract_request_data_from_rack(env)
23
32
  rack_req = ::Rack::Request.new(env)
24
-
25
33
  sensitive_params = sensitive_params_list(env)
26
- request_params = rollbar_filtered_params(sensitive_params, rollbar_request_params(env))
27
- get_params = rollbar_filtered_params(sensitive_params, rollbar_get_params(rack_req))
28
- post_params = rollbar_filtered_params(sensitive_params, rollbar_post_params(rack_req))
29
- raw_body_params = rollbar_filtered_params(sensitive_params, mergeable_raw_body_params(rack_req))
30
- cookies = rollbar_filtered_params(sensitive_params, rollbar_request_cookies(rack_req))
31
- session = rollbar_filtered_params(sensitive_params, rollbar_request_session(rack_req))
32
- route_params = rollbar_filtered_params(sensitive_params, rollbar_route_params(env))
33
-
34
- url_scrubber = Rollbar::Scrubbers::URL.new(:scrub_fields => sensitive_params,
35
- :scrub_user => Rollbar.configuration.scrub_user,
36
- :scrub_password => Rollbar.configuration.scrub_password,
37
- :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length)
38
- url = url_scrubber.call(rollbar_url(env))
39
-
40
- params = request_params.merge(get_params).merge(post_params).merge(raw_body_params)
34
+
35
+ get_params = scrub_params(rollbar_get_params(rack_req), sensitive_params)
36
+ post_params = scrub_params(rollbar_post_params(rack_req), sensitive_params)
37
+ raw_body_params = scrub_params(mergeable_raw_body_params(rack_req),
38
+ sensitive_params)
39
+ cookies = scrub_params(rollbar_request_cookies(rack_req), sensitive_params)
40
+ session = scrub_params(rollbar_request_session(env), sensitive_params)
41
+ route_params = scrub_params(rollbar_route_params(env), sensitive_params)
42
+
43
+ url = scrub_url(rollbar_url(env), sensitive_params)
41
44
 
42
45
  data = {
43
- :params => params,
44
46
  :url => url,
47
+ :params => route_params,
48
+ :GET => get_params,
49
+ :POST => post_params,
50
+ :body => Rollbar::JSON.dump(raw_body_params),
45
51
  :user_ip => rollbar_user_ip(env),
46
52
  :headers => rollbar_headers(env),
47
53
  :cookies => cookies,
48
54
  :session => session,
49
- :method => rollbar_request_method(env),
50
- :route => route_params,
55
+ :method => rollbar_request_method(env)
51
56
  }
52
57
 
53
- if env["action_dispatch.request_id"]
54
- data[:request_id] = env["action_dispatch.request_id"]
58
+ if env['action_dispatch.request_id']
59
+ data[:request_id] =
60
+ env['action_dispatch.request_id']
55
61
  end
56
62
 
57
63
  data
58
64
  end
59
65
 
60
- def rollbar_scrubbed(value)
61
- if Rollbar.configuration.randomize_scrub_length
62
- random_filtered_value
63
- else
64
- '*' * (value.length rescue 8)
65
- end
66
+ def scrub_url(url, sensitive_params)
67
+ options = {
68
+ :url => url,
69
+ :scrub_fields => Array(Rollbar.configuration.scrub_fields) + sensitive_params,
70
+ :scrub_user => Rollbar.configuration.scrub_user,
71
+ :scrub_password => Rollbar.configuration.scrub_password,
72
+ :randomize_scrub_length => Rollbar.configuration.randomize_scrub_length,
73
+ :whitelist => Rollbar.configuration.scrub_whitelist
74
+ }
75
+
76
+ Rollbar::Scrubbers::URL.call(options)
77
+ end
78
+
79
+ def scrub_params(params, sensitive_params)
80
+ options = {
81
+ :params => params,
82
+ :config => Rollbar.configuration.scrub_fields,
83
+ :extra_fields => sensitive_params,
84
+ :whitelist => Rollbar.configuration.scrub_whitelist
85
+ }
86
+ Rollbar::Scrubbers::Params.call(options)
66
87
  end
67
88
 
68
89
  private
@@ -70,9 +91,10 @@ module Rollbar
70
91
  def mergeable_raw_body_params(rack_req)
71
92
  raw_body_params = rollbar_raw_body_params(rack_req)
72
93
 
73
- if raw_body_params.is_a?(Hash)
94
+ case raw_body_params
95
+ when Hash
74
96
  raw_body_params
75
- elsif raw_body_params.is_a?(Array)
97
+ when Array
76
98
  { 'body.multi' => raw_body_params }
77
99
  else
78
100
  { 'body.value' => raw_body_params }
@@ -84,12 +106,26 @@ module Rollbar
84
106
  end
85
107
 
86
108
  def rollbar_headers(env)
87
- env.keys.grep(/^HTTP_/).map do |header|
109
+ env.keys.grep(ALLOWED_HEADERS_REGEX).map do |header|
88
110
  name = header.gsub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
89
111
  if name == 'Cookie'
90
112
  {}
91
113
  elsif sensitive_headers_list.include?(name)
92
- { name => rollbar_scrubbed(env[header]) }
114
+ { name => Rollbar::Scrubbers.scrub_value(env[header]) }
115
+ elsif name == 'X-Forwarded-For' && !Rollbar.configuration.collect_user_ip
116
+ {}
117
+ elsif name == 'X-Forwarded-For' &&
118
+ Rollbar.configuration.collect_user_ip &&
119
+ Rollbar.configuration.anonymize_user_ip
120
+ ips = env[header].sub(' ', '').split(',')
121
+ ips = ips.map { |ip| Rollbar::Util::IPAnonymizer.anonymize_ip(ip) }
122
+ { name => ips.join(', ') }
123
+ elsif name == 'X-Real-Ip' && !Rollbar.configuration.collect_user_ip
124
+ {}
125
+ elsif name == 'X-Real-Ip' &&
126
+ Rollbar.configuration.collect_user_ip &&
127
+ Rollbar.configuration.anonymize_user_ip
128
+ { name => Rollbar::Util::IPAnonymizer.anonymize_ip(env[header]) }
93
129
  else
94
130
  { name => env[header] }
95
131
  end
@@ -100,148 +136,152 @@ module Rollbar
100
136
  forwarded_proto = env['HTTP_X_FORWARDED_PROTO'] || env['rack.url_scheme'] || ''
101
137
  scheme = forwarded_proto.split(',').first
102
138
 
103
- host = env['HTTP_X_FORWARDED_HOST'] || env['HTTP_HOST'] || env['SERVER_NAME']
139
+ host = env['HTTP_X_FORWARDED_HOST'] || env['HTTP_HOST'] || env['SERVER_NAME'] || ''
140
+ host = host.split(',').first.strip unless host.empty?
141
+
104
142
  path = env['ORIGINAL_FULLPATH'] || env['REQUEST_URI']
105
- unless path.nil? || path.empty?
106
- path = '/' + path.to_s if path.to_s.slice(0, 1) != '/'
107
- end
143
+ query = env['QUERY_STRING'].to_s.empty? ? nil : "?#{env['QUERY_STRING']}"
144
+ path ||= "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}#{query}"
145
+ path = "/#{path}" if !(path.nil? || path.empty?) && (path.to_s.slice(0, 1) != '/')
108
146
 
109
147
  port = env['HTTP_X_FORWARDED_PORT']
110
- if port && !(scheme.downcase == 'http' && port.to_i == 80) && \
111
- !(scheme.downcase == 'https' && port.to_i == 443) && \
112
- !(host.include? ':')
113
- host = host + ':' + port
148
+ if port && !(!scheme.nil? && scheme.casecmp('http').zero? && port.to_i == 80) && \
149
+ !(!scheme.nil? && scheme.casecmp('https').zero? && port.to_i == 443) && \
150
+ !(host.include? ':')
151
+ host = "#{host}:#{port}"
114
152
  end
115
153
 
116
154
  [scheme, '://', host, path].join
117
155
  end
118
156
 
119
157
  def rollbar_user_ip(env)
120
- user_ip_string = (env['action_dispatch.remote_ip'] || env['HTTP_X_REAL_IP'] || env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR']).to_s
158
+ return nil unless Rollbar.configuration.collect_user_ip
159
+
160
+ user_ip_string = (user_ip_at_configured_key(env) ||
161
+ env['action_dispatch.remote_ip'] ||
162
+ env['HTTP_X_REAL_IP'] ||
163
+ x_forwarded_for_client(env['HTTP_X_FORWARDED_FOR']) ||
164
+ env['REMOTE_ADDR']).to_s
165
+
166
+ user_ip_string = Rollbar::Util::IPAnonymizer.anonymize_ip(user_ip_string)
121
167
 
122
168
  Rollbar::Util::IPObfuscator.obfuscate_ip(user_ip_string)
123
- rescue
169
+ rescue StandardError
124
170
  nil
125
171
  end
126
172
 
173
+ def user_ip_at_configured_key(env)
174
+ return nil unless Rollbar.configuration.user_ip_rack_env_key
175
+
176
+ env[Rollbar.configuration.user_ip_rack_env_key]
177
+ end
178
+
179
+ def x_forwarded_for_client(header_value)
180
+ return nil unless header_value
181
+
182
+ ips = header_value.split(',').map(&:strip)
183
+
184
+ find_not_private_ip(ips)
185
+ end
186
+
187
+ def find_not_private_ip(ips)
188
+ ips.detect do |ip|
189
+ octets = ip.match(/^(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})$/)[1, 4].map(&:to_i)
190
+
191
+ is_private = (octets[0] == 10) ||
192
+ ((octets[0] == 172) && (octets[1] >= 16) && (octets[1] <= 31)) ||
193
+ ((octets[0] == 192) && (octets[1] == 168))
194
+
195
+ !is_private
196
+ end
197
+ end
198
+
127
199
  def rollbar_get_params(rack_req)
128
200
  rack_req.GET
129
- rescue
201
+ rescue StandardError
130
202
  {}
131
203
  end
132
204
 
133
205
  def rollbar_post_params(rack_req)
134
206
  rack_req.POST
135
- rescue
207
+ rescue StandardError
136
208
  {}
137
209
  end
138
210
 
139
211
  def rollbar_raw_body_params(rack_req)
140
- correct_method = rack_req.post? || rack_req.put? || rack_req.patch?
212
+ correct_method = ALLOWED_BODY_PARSEABLE_METHODS.include?(rack_req.request_method)
141
213
 
142
214
  return {} unless correct_method
143
215
  return {} unless json_request?(rack_req)
144
216
 
145
- Rollbar::JSON.load(rack_req.body.read)
146
- rescue
217
+ raw_body = read_raw_body(rack_req.body)
218
+ begin
219
+ Rollbar::JSON.load(raw_body)
220
+ rescue StandardError
221
+ raw_body
222
+ end
223
+ rescue StandardError
147
224
  {}
148
- ensure
149
- rack_req.body.rewind
150
225
  end
151
226
 
152
- def json_request?(rack_req)
153
- !!(rack_req.env['CONTENT_TYPE'] =~ %r{application/json} ||
154
- rack_req.env['ACCEPT'] =~ /\bjson\b/)
227
+ def read_raw_body(body)
228
+ return {} unless body.respond_to?(:rewind)
229
+
230
+ body.rewind
231
+ raw_body = body.read
232
+ body.rewind
233
+ raw_body
155
234
  end
156
235
 
157
- def rollbar_request_params(env)
158
- env['action_dispatch.request.parameters'] || {}
236
+ def json_request?(rack_req)
237
+ json_regex = /\bjson\b/
238
+
239
+ !!(rack_req.env['CONTENT_TYPE'] =~ json_regex)
159
240
  end
160
241
 
161
242
  def rollbar_route_params(env)
162
243
  return {} unless defined?(Rails)
163
244
 
164
245
  begin
165
- route = ::Rails.application.routes.recognize_path(env['PATH_INFO'])
166
-
167
- {
168
- :controller => route[:controller],
169
- :action => route[:action],
170
- :format => route[:format]
171
- }
172
- rescue
246
+ environment = { :method => rollbar_request_method(env) }
247
+
248
+ # recognize_path() will return the controller, action
249
+ # route params (if any)and format (if defined)
250
+ ::Rails.application.routes.recognize_path(env['PATH_INFO'],
251
+ environment)
252
+ rescue StandardError
173
253
  {}
174
254
  end
175
255
  end
176
256
 
177
- def rollbar_request_session(rack_req)
178
- session = rack_req.session
257
+ def rollbar_request_session(env)
258
+ session = env.fetch('rack.session', {})
179
259
 
180
260
  session.to_hash
181
- rescue
261
+ rescue StandardError
182
262
  {}
183
263
  end
184
264
 
185
265
  def rollbar_request_cookies(rack_req)
186
266
  rack_req.cookies
187
- rescue
267
+ rescue StandardError
188
268
  {}
189
269
  end
190
270
 
191
- def rollbar_filtered_params(sensitive_params, params)
192
- sensitive_params_regexp = Regexp.new(sensitive_params.map{ |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
193
-
194
- return {} unless params
195
-
196
- params.to_hash.inject({}) do |result, (key, value)|
197
- if sensitive_params_regexp =~ Rollbar::Encoding.encode(key).to_s
198
- result[key] = rollbar_scrubbed(value)
199
- elsif value.is_a?(Hash)
200
- result[key] = rollbar_filtered_params(sensitive_params, value)
201
- elsif value.is_a?(Array)
202
- result[key] = value.map do |v|
203
- v.is_a?(Hash) ? rollbar_filtered_params(sensitive_params, v) : rollbar_filtered_param_value(v)
204
- end
205
- elsif skip_value?(value)
206
- result[key] = "Skipped value of class '#{value.class.name}'"
207
- else
208
- result[key] = rollbar_filtered_param_value(value)
209
- end
210
-
211
- result
212
- end
213
- end
214
-
215
- def rollbar_filtered_param_value(value)
216
- if ATTACHMENT_CLASSES.include?(value.class.name)
217
- begin
218
- {
219
- :content_type => value.content_type,
220
- :original_filename => value.original_filename,
221
- :size => value.tempfile.size
222
- }
223
- rescue
224
- 'Uploaded file'
225
- end
226
- else
227
- value
228
- end
229
- end
230
-
231
271
  def sensitive_params_list(env)
232
- Array(Rollbar.configuration.scrub_fields) | Array(env['action_dispatch.parameter_filter'])
272
+ Array(env['action_dispatch.parameter_filter'])
233
273
  end
234
274
 
235
275
  def sensitive_headers_list
236
- Rollbar.configuration.scrub_headers || []
237
- end
238
-
239
- def random_filtered_value
240
- '*' * (rand(5) + 3)
241
- end
276
+ unless Rollbar.configuration.scrub_headers &&
277
+ Rollbar.configuration.scrub_headers.is_a?(Array)
278
+ return []
279
+ end
242
280
 
243
- def skip_value?(value)
244
- SKIPPED_CLASSES.any? { |klass| value.is_a?(klass) }
281
+ # Normalize into the expected matching format
282
+ Rollbar.configuration.scrub_headers.map do |header|
283
+ header.split(/[-_]/).map(&:capitalize).join('-').gsub(/^Http-/, '')
284
+ end
245
285
  end
246
286
  end
247
287
  end
@@ -0,0 +1,38 @@
1
+ require 'rollbar'
2
+
3
+ module RollbarTest # :nodoc:
4
+ def self.run
5
+ return unless confirmed_token?
6
+
7
+ puts 'Test sending to Rollbar...'
8
+ result = Rollbar.info('Test message from rollbar:test')
9
+
10
+ if result == 'error'
11
+ puts error_message
12
+ else
13
+ puts success_message
14
+ end
15
+ end
16
+
17
+ def self.confirmed_token?
18
+ return true if Rollbar.configuration.access_token
19
+
20
+ puts token_error_message
21
+
22
+ false
23
+ end
24
+
25
+ def self.token_error_message
26
+ 'Rollbar needs an access token configured. Check the README for instructions.'
27
+ end
28
+
29
+ def self.error_message
30
+ 'Test failed! You may have a configuration issue, or you could be using a ' \
31
+ 'gem that\'s blocking the test. Contact support@rollbar.com if you need ' \
32
+ 'help troubleshooting.'
33
+ end
34
+
35
+ def self.success_message
36
+ 'Testing rollbar with "rake rollbar:test". If you can see this, it works.'
37
+ end
38
+ end
@@ -0,0 +1,133 @@
1
+ require 'tempfile'
2
+ require 'rollbar/scrubbers'
3
+
4
+ module Rollbar
5
+ module Scrubbers
6
+ # This class contains the logic to scrub the received parameters. It will
7
+ # scrub the parameters matching Rollbar.configuration.scrub_fields Array.
8
+ # Also, if that configuration option is set to :scrub_all, it will scrub all
9
+ # received parameters. It will not scrub anything that is in the scrub_whitelist
10
+ # configuration array even if :scrub_all is true.
11
+ class Params
12
+ SKIPPED_CLASSES = [::Tempfile].freeze
13
+ ATTACHMENT_CLASSES = %w[ActionDispatch::Http::UploadedFile
14
+ Rack::Multipart::UploadedFile].freeze
15
+ SCRUB_ALL = :scrub_all
16
+
17
+ def self.call(*args)
18
+ new.call(*args)
19
+ end
20
+
21
+ def call(options = {})
22
+ params = options[:params]
23
+ return {} unless params
24
+
25
+ @scrubbed_objects = {}.compare_by_identity
26
+
27
+ config = options[:config]
28
+ extra_fields = options[:extra_fields]
29
+ whitelist = options[:whitelist] || []
30
+
31
+ scrub(params, build_scrub_options(config, extra_fields, whitelist))
32
+ end
33
+
34
+ private
35
+
36
+ def build_scrub_options(config, extra_fields, whitelist)
37
+ ary_config = Array(config)
38
+
39
+ {
40
+ :fields_regex => build_fields_regex(ary_config, extra_fields),
41
+ :scrub_all => ary_config.include?(SCRUB_ALL),
42
+ :whitelist => build_whitelist_regex(whitelist)
43
+ }
44
+ end
45
+
46
+ def build_fields_regex(config, extra_fields)
47
+ fields = config.find_all { |f| f.is_a?(String) || f.is_a?(Symbol) }
48
+ fields += Array(extra_fields)
49
+
50
+ return unless fields.any?
51
+
52
+ Regexp.new(fields.map { |val| Regexp.escape(val.to_s).to_s }.join('|'), true)
53
+ end
54
+
55
+ def build_whitelist_regex(whitelist)
56
+ fields = whitelist.find_all do |f|
57
+ f.is_a?(String) || f.is_a?(Symbol) || f.is_a?(Regexp)
58
+ end
59
+ return unless fields.any?
60
+
61
+ Regexp.new(fields.map do |val|
62
+ val.is_a?(Regexp) ? val : /\A#{Regexp.escape(val.to_s)}\z/
63
+ end.join('|'))
64
+ end
65
+
66
+ def scrub(params, options)
67
+ return params if @scrubbed_objects[params]
68
+
69
+ @scrubbed_objects[params] = true
70
+
71
+ fields_regex = options[:fields_regex]
72
+ scrub_all = options[:scrub_all]
73
+ whitelist_regex = options[:whitelist]
74
+
75
+ return scrub_array(params, options) if params.is_a?(Array)
76
+
77
+ params.to_hash.inject({}) do |result, (key, value)|
78
+ encoded_key = Rollbar::Encoding.encode(key).to_s
79
+ result[key] = if (fields_regex === encoded_key) &&
80
+ !(whitelist_regex === encoded_key)
81
+ scrub_value(value)
82
+ elsif value.is_a?(Hash)
83
+ scrub(value, options)
84
+ elsif scrub_all && !(whitelist_regex === encoded_key)
85
+ scrub_value(value)
86
+ elsif value.is_a?(Array)
87
+ scrub_array(value, options)
88
+ elsif skip_value?(value)
89
+ "Skipped value of class '#{value.class.name}'"
90
+ else
91
+ rollbar_filtered_param_value(value)
92
+ end
93
+
94
+ result
95
+ end
96
+ end
97
+
98
+ def scrub_array(array, options)
99
+ array.map do |value|
100
+ value.is_a?(Hash) ? scrub(value, options) : rollbar_filtered_param_value(value)
101
+ end
102
+ end
103
+
104
+ def scrub_value(value)
105
+ Rollbar::Scrubbers.scrub_value(value)
106
+ end
107
+
108
+ def rollbar_filtered_param_value(value)
109
+ if ATTACHMENT_CLASSES.include?(value.class.name)
110
+ begin
111
+ attachment_value(value)
112
+ rescue StandardError
113
+ 'Uploaded file'
114
+ end
115
+ else
116
+ value
117
+ end
118
+ end
119
+
120
+ def attachment_value(value)
121
+ {
122
+ :content_type => value.content_type,
123
+ :original_filename => value.original_filename,
124
+ :size => value.tempfile.size
125
+ }
126
+ end
127
+
128
+ def skip_value?(value)
129
+ SKIPPED_CLASSES.any? { |klass| value.is_a?(klass) }
130
+ end
131
+ end
132
+ end
133
+ end