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
@@ -0,0 +1,297 @@
1
+ require 'rack'
2
+ require 'rack/response'
3
+
4
+ require 'rollbar/request_data_extractor'
5
+ require 'rollbar/util'
6
+
7
+ module Rollbar
8
+ module Middleware
9
+ # Middleware to inject the rollbar.js snippet into a 200 html response
10
+ class Js
11
+ include Rollbar::RequestDataExtractor
12
+
13
+ attr_reader :app, :config
14
+
15
+ JS_IS_INJECTED_KEY = 'rollbar.js_is_injected'.freeze
16
+ SNIPPET = File.read(File.expand_path('../../../../data/rollbar.snippet.js',
17
+ __FILE__))
18
+
19
+ def initialize(app, config)
20
+ @app = app
21
+ @config = config
22
+ end
23
+
24
+ def call(env)
25
+ app_result = app.call(env)
26
+
27
+ begin
28
+ return app_result unless add_js?(env, app_result[1])
29
+
30
+ response_string = add_js(env, app_result[2])
31
+ build_response(env, app_result, response_string)
32
+ rescue StandardError => e
33
+ Rollbar.log_error(
34
+ "[Rollbar] Rollbar.js could not be added because #{e} exception"
35
+ )
36
+
37
+ app_result
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def enabled?
44
+ !!config[:enabled]
45
+ end
46
+
47
+ def add_js?(env, headers)
48
+ enabled? && !env[JS_IS_INJECTED_KEY] &&
49
+ html?(headers) && !attachment?(headers) && !streaming?(env)
50
+ end
51
+
52
+ def html?(headers)
53
+ headers['Content-Type'] && headers['Content-Type'].include?('text/html')
54
+ end
55
+
56
+ def attachment?(headers)
57
+ headers['Content-Disposition'].to_s.include?('attachment')
58
+ end
59
+
60
+ def streaming?(env)
61
+ return false unless defined?(ActionController::Live)
62
+
63
+ env['action_controller.instance']
64
+ .class.included_modules.include?(ActionController::Live)
65
+ end
66
+
67
+ def add_js(env, response)
68
+ body = join_body(response)
69
+ close_old_response(response)
70
+
71
+ return nil unless body
72
+
73
+ insert_after_idx = find_insertion_point(body)
74
+ return nil unless insert_after_idx
75
+
76
+ build_body_with_js(env, body, insert_after_idx)
77
+ rescue StandardError => e
78
+ Rollbar.log_error(
79
+ "[Rollbar] Rollbar.js could not be added because #{e} exception"
80
+ )
81
+ nil
82
+ end
83
+
84
+ def build_response(env, app_result, response_string)
85
+ return app_result unless response_string
86
+
87
+ env[JS_IS_INJECTED_KEY] = true
88
+
89
+ status, headers, = app_result
90
+ if headers.key?('Content-Length')
91
+ headers['Content-Length'] =
92
+ response_string.bytesize.to_s
93
+ end
94
+
95
+ response = ::Rack::Response.new(response_string, status, headers)
96
+
97
+ finished = response.finish
98
+
99
+ # Rack < 2.x Response#finish returns self in array[2].
100
+ # Rack >= 2.x returns self.body.
101
+ # Always return with the response object here regardless of rack version.
102
+ finished[2] = response
103
+ finished
104
+ end
105
+
106
+ def build_body_with_js(env, body, head_open_end)
107
+ return body unless head_open_end
108
+
109
+ body[0..head_open_end] << config_js_tag(env) << snippet_js_tag(env) <<
110
+ body[head_open_end + 1..-1]
111
+ end
112
+
113
+ def find_insertion_point(body)
114
+ find_end_after_regex(body, /<meta\s*charset=/i) ||
115
+ find_end_after_regex(body, /<meta\s*http-equiv="Content-Type"/i) ||
116
+ find_end_after_regex(body, /<head\W/i)
117
+ end
118
+
119
+ def find_end_after_regex(body, regex)
120
+ open_idx = body.index(regex)
121
+ body.index('>', open_idx) if open_idx
122
+ end
123
+
124
+ def join_body(response)
125
+ response.to_enum.reduce('') do |acc, fragment|
126
+ acc << fragment.to_s
127
+ acc
128
+ end
129
+ end
130
+
131
+ def close_old_response(response)
132
+ response.close if response.respond_to?(:close)
133
+ end
134
+
135
+ def config_js_tag(env)
136
+ require 'json'
137
+ require 'rollbar/middleware/js/json_value'
138
+
139
+ js_config = Rollbar::Util.deep_copy(config[:options])
140
+
141
+ add_person_data(js_config, env)
142
+
143
+ # MUST use the Ruby JSON encoder (JSON#generate).
144
+ # See lib/rollbar/middleware/js/json_value
145
+ json = ::JSON.generate(js_config, Rollbar::JSON::JsOptionsState.new)
146
+
147
+ script_tag("var _rollbarConfig = #{json};", env)
148
+ end
149
+
150
+ def add_person_data(js_config, env)
151
+ person_data = extract_person_data_from_controller(env)
152
+
153
+ return if person_data && person_data.empty?
154
+
155
+ js_config[:payload] ||= {}
156
+ js_config[:payload][:person] = person_data if person_data
157
+ end
158
+
159
+ def snippet_js_tag(env)
160
+ script_tag(js_snippet, env)
161
+ end
162
+
163
+ def js_snippet
164
+ SNIPPET
165
+ end
166
+
167
+ def script_tag(content, env)
168
+ nonce = rails5_nonce(env) || secure_headers_nonce(env)
169
+ script_tag_content = if nonce
170
+ "\n<script nonce=\"#{nonce}\">#{content}</script>"
171
+ else
172
+ "\n<script>#{content}</script>"
173
+ end
174
+
175
+ html_safe_if_needed(script_tag_content)
176
+ end
177
+
178
+ def html_safe_if_needed(string)
179
+ string = string.html_safe if string.respond_to?(:html_safe)
180
+ string
181
+ end
182
+
183
+ # Rails 5.2+ Secure Content Policy
184
+ def rails5_nonce(env)
185
+ req = ::ActionDispatch::Request.new(env)
186
+
187
+ # Rails will only return a nonce if the app has set a nonce generator.
188
+ # So if we get a valid nonce here, we know we should use it.
189
+ #
190
+ # Having both 'unsafe-inline' and a nonce is a valid and preferred
191
+ # browser compatibility configuration.
192
+ #
193
+ # If the script_src key is missing, Rails will not add the nonce to the headers,
194
+ # so we detect this and will not add it in this case.
195
+ req.respond_to?(:content_security_policy) &&
196
+ req.content_security_policy &&
197
+ req.content_security_policy.directives['script-src'] &&
198
+ req.content_security_policy_nonce
199
+ end
200
+
201
+ # Secure Headers gem
202
+ def secure_headers_nonce(env)
203
+ req = ::Rack::Request.new(env)
204
+
205
+ return unless secure_headers(req).append_nonce?
206
+
207
+ ::SecureHeaders.content_security_policy_script_nonce(req)
208
+ end
209
+
210
+ def secure_headers(req)
211
+ return SecureHeadersFalse.new unless defined?(::SecureHeaders::Configuration)
212
+
213
+ # If the nonce key has been set, the app is using nonces for this request.
214
+ # If it hasn't, we shouldn't cause one to be added to script_src, so return now.
215
+ return SecureHeadersFalse.new unless secure_headers_nonce_key(req)
216
+
217
+ config = ::SecureHeaders::Configuration
218
+
219
+ has_nonce = ::SecureHeaders.respond_to?(
220
+ :content_security_policy_script_nonce
221
+ )
222
+ secure_headers_cls = if !has_nonce
223
+ SecureHeadersFalse
224
+ elsif config.respond_to?(:get)
225
+ SecureHeaders3To5
226
+ elsif config.dup.respond_to?(:csp)
227
+ SecureHeaders6
228
+ else
229
+ SecureHeadersFalse
230
+ end
231
+
232
+ secure_headers_cls.new
233
+ end
234
+
235
+ def secure_headers_nonce_key(req)
236
+ defined?(::SecureHeaders::NONCE_KEY) &&
237
+ req.env[::SecureHeaders::NONCE_KEY]
238
+ end
239
+
240
+ class SecureHeadersResolver
241
+ def append_nonce?
242
+ csp_needs_nonce?(find_csp)
243
+ end
244
+
245
+ private
246
+
247
+ def find_csp
248
+ raise NotImplementedError
249
+ end
250
+
251
+ def csp_needs_nonce?(csp)
252
+ !opt_out?(csp)
253
+ end
254
+
255
+ def opt_out?(_csp)
256
+ raise NotImplementedError
257
+ end
258
+ end
259
+
260
+ class SecureHeadersFalse < SecureHeadersResolver
261
+ def append_nonce?
262
+ false
263
+ end
264
+ end
265
+
266
+ class SecureHeaders3To5 < SecureHeadersResolver
267
+ private
268
+
269
+ def find_csp
270
+ ::SecureHeaders::Configuration.get.csp
271
+ end
272
+
273
+ def opt_out?(csp)
274
+ if csp.respond_to?(:opt_out?) && csp.opt_out?
275
+ csp.opt_out?
276
+ # secure_headers csp 3.0.x-3.4.x doesn't respond to 'opt_out?'
277
+ elsif defined?(::SecureHeaders::OPT_OUT) &&
278
+ ::SecureHeaders::OPT_OUT.is_a?(Symbol)
279
+ csp == ::SecureHeaders::OPT_OUT
280
+ end
281
+ end
282
+ end
283
+
284
+ class SecureHeaders6 < SecureHeadersResolver
285
+ private
286
+
287
+ def find_csp
288
+ ::SecureHeaders::Configuration.dup.csp
289
+ end
290
+
291
+ def opt_out?(csp)
292
+ csp.opt_out?
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end
@@ -3,7 +3,7 @@ require 'rollbar/request_data_extractor'
3
3
 
4
4
  module Rollbar
5
5
  module Middleware
6
- module Rack
6
+ class Rack
7
7
  module Builder
8
8
  include ExceptionReporter
9
9
  include RequestDataExtractor
@@ -14,8 +14,8 @@ module Rollbar
14
14
  Rollbar.scoped(fetch_scope(env)) do
15
15
  begin
16
16
  call_without_rollbar(env)
17
- rescue ::Exception => exception
18
- report_exception_to_rollbar(env, exception)
17
+ rescue ::Exception => e # rubocop:disable Lint/RescueException
18
+ report_exception_to_rollbar(env, e)
19
19
  raise
20
20
  end
21
21
  end
@@ -26,7 +26,7 @@ module Rollbar
26
26
  :request => proc { extract_request_data_from_rack(env) },
27
27
  :person => person_data_proc(env)
28
28
  }
29
- rescue Exception => e
29
+ rescue Exception => e # rubocop:disable Lint/RescueException
30
30
  report_exception_to_rollbar(env, e)
31
31
  raise
32
32
  end
@@ -1,14 +1,14 @@
1
1
  module Rollbar
2
2
  module Middleware
3
- module Rack
3
+ class Rack
4
4
  module TestSession
5
5
  include ExceptionReporter
6
6
 
7
7
  def env_for_with_rollbar(path, env)
8
8
  env_for_without_rollbar(path, env)
9
- rescue Exception => exception
10
- report_exception_to_rollbar(env, exception)
11
- raise exception
9
+ rescue Exception => e # rubocop:disable Lint/RescueException
10
+ report_exception_to_rollbar(env, e)
11
+ raise e
12
12
  end
13
13
 
14
14
  def self.included(base)
@@ -0,0 +1,52 @@
1
+ require 'rollbar'
2
+ require 'rollbar/exception_reporter'
3
+ require 'rollbar/request_data_extractor'
4
+
5
+ module Rollbar
6
+ module Middleware
7
+ class Rack
8
+ include ::Rollbar::ExceptionReporter
9
+ include RequestDataExtractor
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ Rollbar.reset_notifier!
17
+
18
+ Rollbar.scoped(fetch_scope(env)) do
19
+ begin
20
+ Rollbar.notifier.enable_locals
21
+ response = @app.call(env)
22
+ report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
23
+ response
24
+ rescue Exception => e # rubocop:disable Lint/RescueException
25
+ report_exception_to_rollbar(env, e)
26
+ raise
27
+ ensure
28
+ Rollbar.notifier.disable_locals
29
+ end
30
+ end
31
+ end
32
+
33
+ def fetch_scope(env)
34
+ {
35
+ :request => proc { extract_request_data_from_rack(env) },
36
+ :person => person_data_proc(env)
37
+ }
38
+ rescue Exception => e # rubocop:disable Lint/RescueException
39
+ report_exception_to_rollbar(env, e)
40
+ raise
41
+ end
42
+
43
+ def person_data_proc(env)
44
+ proc { extract_person_data_from_controller(env) }
45
+ end
46
+
47
+ def framework_error(env)
48
+ env['rack.exception']
49
+ end
50
+ end
51
+ end
52
+ end
@@ -21,6 +21,7 @@ module Rollbar
21
21
 
22
22
  Rollbar.scoped(scope) do
23
23
  begin
24
+ Rollbar.notifier.enable_locals
24
25
  response = @app.call(env)
25
26
 
26
27
  if (framework_exception = env['action_dispatch.exception'])
@@ -28,9 +29,11 @@ module Rollbar
28
29
  end
29
30
 
30
31
  response
31
- rescue Exception => exception
32
- report_exception_to_rollbar(env, exception)
32
+ rescue Exception => e # rubocop:disable Lint/RescueException
33
+ report_exception_to_rollbar(env, e)
33
34
  raise
35
+ ensure
36
+ Rollbar.notifier.disable_locals
34
37
  end
35
38
  end
36
39
  end
@@ -60,17 +63,26 @@ module Rollbar
60
63
 
61
64
  def person_data_proc(env)
62
65
  block = proc { extract_person_data_from_controller(env) }
63
- return block unless(defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?)
66
+ unless defined?(ActiveRecord::Base) && ActiveRecord::Base.connected?
67
+ return block
68
+ end
64
69
 
65
- proc { ActiveRecord::Base.connection_pool.with_connection(&block) }
70
+ proc do
71
+ begin
72
+ ActiveRecord::Base.connection_pool.with_connection(&block)
73
+ rescue ActiveRecord::ConnectionTimeoutError
74
+ {}
75
+ end
76
+ end
66
77
  end
67
78
 
68
79
  def context(request_data)
69
- return unless request_data[:route]
80
+ route_params = request_data[:params]
70
81
 
71
- route = request_data[:route]
72
82
  # make sure route is a hash built by RequestDataExtractor
73
- return "#{route[:controller]}" + '#' + "#{route[:action]}" if route.is_a?(Hash) && !route.empty?
83
+ return unless route_params.is_a?(Hash) && !route_params.empty?
84
+
85
+ "#{route_params[:controller]}##{route_params[:action]}"
74
86
  end
75
87
  end
76
88
  end
@@ -4,10 +4,10 @@ module Rollbar
4
4
  module ShowExceptions
5
5
  include ExceptionReporter
6
6
 
7
- def render_exception_with_rollbar(env, exception)
7
+ def render_exception_with_rollbar(env, exception, wrapper = nil)
8
8
  key = 'action_dispatch.show_detailed_exceptions'
9
9
 
10
- if exception.is_a?(ActionController::RoutingError) && env[key]
10
+ if exception.is_a?(ActionController::RoutingError) && env.params[key.to_s]
11
11
  scope = extract_scope_from(env)
12
12
 
13
13
  Rollbar.scoped(scope) do
@@ -15,32 +15,44 @@ module Rollbar
15
15
  end
16
16
  end
17
17
 
18
- render_exception_without_rollbar(env, exception)
18
+ # Rails 7.1 changes the method signature for render_exception.
19
+ if self.class.instance_method(:render_exception_without_rollbar).arity == 2
20
+ render_exception_without_rollbar(env, exception)
21
+ else
22
+ render_exception_without_rollbar(env, exception, wrapper)
23
+ end
19
24
  end
20
25
 
21
26
  def call_with_rollbar(env)
22
27
  call_without_rollbar(env)
23
- rescue ActionController::RoutingError => exception
28
+ rescue ActionController::RoutingError => e
24
29
  # won't reach here if show_detailed_exceptions is true
25
30
  scope = extract_scope_from(env)
26
31
 
27
32
  Rollbar.scoped(scope) do
28
- report_exception_to_rollbar(env, exception)
33
+ report_exception_to_rollbar(env, e)
29
34
  end
30
35
 
31
- raise exception
36
+ raise e
32
37
  end
33
38
 
34
39
  def extract_scope_from(env)
35
40
  scope = env['rollbar.scope']
36
- Rollbar.log_warn('[Rollbar] rollbar.scope key has been removed from Rack env.') unless scope
41
+ unless scope
42
+ Rollbar.log_warn(
43
+ '[Rollbar] rollbar.scope key has been removed from Rack env.'
44
+ )
45
+ end
37
46
 
38
47
  scope || {}
39
48
  end
40
49
 
41
50
  def self.included(base)
42
- base.send(:alias_method_chain, :call, :rollbar)
43
- base.send(:alias_method_chain, :render_exception, :rollbar)
51
+ base.send(:alias_method, :call_without_rollbar, :call)
52
+ base.send(:alias_method, :call, :call_with_rollbar)
53
+
54
+ base.send(:alias_method, :render_exception_without_rollbar, :render_exception)
55
+ base.send(:alias_method, :render_exception, :render_exception_with_rollbar)
44
56
  end
45
57
  end
46
58
  end
@@ -1,46 +1,8 @@
1
- require 'rollbar'
2
- require 'rollbar/exception_reporter'
3
- require 'rollbar/request_data_extractor'
1
+ require 'rollbar/middleware/rack'
4
2
 
5
3
  module Rollbar
6
4
  module Middleware
7
- class Sinatra
8
- include ::Rollbar::ExceptionReporter
9
- include RequestDataExtractor
10
-
11
- def initialize(app)
12
- @app = app
13
- end
14
-
15
- def call(env)
16
- Rollbar.reset_notifier!
17
-
18
- Rollbar.scoped(fetch_scope(env)) do
19
- begin
20
- response = @app.call(env)
21
- report_exception_to_rollbar(env, framework_error(env)) if framework_error(env)
22
- response
23
- rescue Exception => e
24
- report_exception_to_rollbar(env, e)
25
- raise
26
- end
27
- end
28
- end
29
-
30
- def fetch_scope(env)
31
- {
32
- :request => proc { extract_request_data_from_rack(env) },
33
- :person => person_data_proc(env)
34
- }
35
- rescue Exception => e
36
- report_exception_to_rollbar(env, e)
37
- raise
38
- end
39
-
40
- def person_data_proc(env)
41
- proc { extract_person_data_from_controller(env) }
42
- end
43
-
5
+ class Sinatra < Rollbar::Middleware::Rack
44
6
  def framework_error(env)
45
7
  env['sinatra.error']
46
8
  end
@@ -0,0 +1,75 @@
1
+ module Rollbar
2
+ class Notifier
3
+ class TraceWithBindings # :nodoc:
4
+ attr_reader :frames, :exception_frames
5
+
6
+ def initialize
7
+ reset
8
+ end
9
+
10
+ def reset
11
+ @frames = []
12
+ @exception_frames = []
13
+ @exception_signature = nil
14
+ end
15
+
16
+ def enable
17
+ reset
18
+ trace_point.enable if defined?(TracePoint)
19
+ end
20
+
21
+ def disable
22
+ trace_point.disable if defined?(TracePoint)
23
+ end
24
+
25
+ private
26
+
27
+ def exception_signature(trace)
28
+ # use the exception backtrace to detect reraised exception.
29
+ trace.raised_exception.backtrace.first
30
+ end
31
+
32
+ def detect_reraise(trace)
33
+ @exception_signature == exception_signature(trace)
34
+ end
35
+
36
+ def trace_point
37
+ return unless defined?(TracePoint)
38
+
39
+ @trace_point ||= TracePoint.new(:call, :return, :b_call, :b_return, :c_call,
40
+ :c_return, :raise) do |tp|
41
+ case tp.event
42
+ when :call, :b_call, :c_call, :class
43
+ frames.push frame(tp)
44
+ when :return, :b_return, :c_return, :end
45
+ frames.pop
46
+ when :raise
47
+ unless detect_reraise(tp) # ignore reraised exceptions
48
+ # may be possible to optimize better than #dup
49
+ @exception_frames = @frames.dup
50
+ @exception_signature = exception_signature(tp)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def frame(trace)
57
+ {
58
+ :binding => binding(trace),
59
+ :defined_class => trace.defined_class,
60
+ :method_id => trace.method_id,
61
+ :path => trace.path,
62
+ :lineno => trace.lineno
63
+ }
64
+ end
65
+
66
+ def binding(trace)
67
+ trace.binding
68
+ rescue StandardError
69
+ # Ruby internals will raise if we're on a Fiber,
70
+ # since bindings aren't valid on Fibers.
71
+ nil
72
+ end
73
+ end
74
+ end
75
+ end