better_errors 2.5.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 832f46e8977908b469e6b527edbaf770541b66dfafcc3f8c1b292c0c6c25838c
4
- data.tar.gz: 4584adc6e2870f40a5bd3eb0d7f18b693380e6a1c04716217f00c9190766f3e7
3
+ metadata.gz: 10f7411145be495cf17cbebdf087e1bb21fe8c6fc8c07397fa406e7fc1f9f917
4
+ data.tar.gz: 3b14b75eaa97285c3ad5f685671348694aa7174cc43e52826e49e21a2f139b0d
5
5
  SHA512:
6
- metadata.gz: 844ecf262fdeee48a8165e201a189fcd7812db7bf437bf8e5e11ba80f63edeaa841015fcbc21a11b291e9705c8751fa382eba94e86b90d350828c662fffdbf0b
7
- data.tar.gz: 82ff2fbb24fcbd5dafefe1776125da521cf5813461bca58700060d9be41aa7c138fe95d98b3056289aab5976adc48b83b7dc204521500fc85fe6ee8eb141d09b
6
+ metadata.gz: 141e1056c402ed7b0aa0965278018096ca1d2bc4032072692c1f146ad09d6848d87792d665ecc6dcb41322594e91d9a5e27955edc560bb665a2995f150c0be4e
7
+ data.tar.gz: 03a94aa9fdcd0340b1fdf913a52978437692587efabe196ebb119087712086cc304289ec1c684ab4efbdece115a4bd1298b57bf58699a0d672f76f6aa196793b
@@ -1,9 +1,5 @@
1
- sudo: false
2
1
  language: ruby
3
2
  cache: bundler
4
- before_install:
5
- - gem update --system
6
- - gem update bundler
7
3
  notifications:
8
4
  webhooks:
9
5
  # With COVERALLS_PARALLEL, coverage information sent to coveralls will not be processed until
@@ -12,23 +8,28 @@ notifications:
12
8
  - secure: "YnHYbTq51ySistjvOxsuNhyg4GLuUffEJstTYeGYXiBF7HG5h43IVYo8KNuLzwkgsOYBcNo+YMdQX7qCqJffSbhsr1FZRSzBmjFFxcyD4hu+ukM2theZ4mePVAZiePscYvQPRNY4hIb4d3egStJEytkalDhB3sOebF57tIaCssg="
13
9
  rvm:
14
10
  - 2.2.10
15
- - 2.3.7
16
- - 2.4.4
17
- - 2.5.1
11
+ - 2.3.8
12
+ - 2.4.9
13
+ - 2.5.7
14
+ - 2.6.5
15
+ - 2.7.0
18
16
  - ruby-head
19
17
  gemfile:
20
18
  - gemfiles/rails42.gemfile
21
19
  - gemfiles/rails50.gemfile
22
20
  - gemfiles/rails51.gemfile
23
21
  - gemfiles/rails52.gemfile
22
+ - gemfiles/rails60.gemfile
24
23
  - gemfiles/rails42_haml.gemfile
25
24
  - gemfiles/rails50_haml.gemfile
26
25
  - gemfiles/rails51_haml.gemfile
27
26
  - gemfiles/rails52_haml.gemfile
27
+ - gemfiles/rails60_haml.gemfile
28
28
  - gemfiles/rails42_boc.gemfile
29
29
  - gemfiles/rails50_boc.gemfile
30
30
  - gemfiles/rails51_boc.gemfile
31
31
  - gemfiles/rails52_boc.gemfile
32
+ - gemfiles/rails60_boc.gemfile
32
33
  - gemfiles/rack.gemfile
33
34
  - gemfiles/rack_boc.gemfile
34
35
  - gemfiles/pry09.gemfile
@@ -41,15 +42,57 @@ matrix:
41
42
  - gemfile: gemfiles/pry010.gemfile
42
43
  - gemfile: gemfiles/pry011.gemfile
43
44
  exclude:
44
- - rvm: 2.4.4
45
+ - rvm: 2.2.10
46
+ gemfile: gemfiles/rails60.gemfile
47
+ - rvm: 2.2.10
48
+ gemfile: gemfiles/rails60_boc.gemfile
49
+ - rvm: 2.2.10
50
+ gemfile: gemfiles/rails60_haml.gemfile
51
+ - rvm: 2.3.8
45
52
  gemfile: gemfiles/rails42.gemfile
46
- - rvm: 2.4.4
53
+ - rvm: 2.3.8
47
54
  gemfile: gemfiles/rails42_boc.gemfile
48
- - rvm: 2.4.4
55
+ - rvm: 2.3.8
49
56
  gemfile: gemfiles/rails42_haml.gemfile
50
- - rvm: 2.5.1
57
+ - rvm: 2.3.8
58
+ gemfile: gemfiles/rails60.gemfile
59
+ - rvm: 2.3.8
60
+ gemfile: gemfiles/rails60_boc.gemfile
61
+ - rvm: 2.3.8
62
+ gemfile: gemfiles/rails60_haml.gemfile
63
+ - rvm: 2.4.9
51
64
  gemfile: gemfiles/rails42.gemfile
52
- - rvm: 2.5.1
65
+ - rvm: 2.4.9
53
66
  gemfile: gemfiles/rails42_boc.gemfile
54
- - rvm: 2.5.1
67
+ - rvm: 2.4.9
68
+ gemfile: gemfiles/rails42_haml.gemfile
69
+ - rvm: 2.4.9
70
+ gemfile: gemfiles/rails60.gemfile
71
+ - rvm: 2.4.9
72
+ gemfile: gemfiles/rails60_boc.gemfile
73
+ - rvm: 2.4.9
74
+ gemfile: gemfiles/rails60_haml.gemfile
75
+ - rvm: 2.5.7
76
+ gemfile: gemfiles/rails42.gemfile
77
+ - rvm: 2.5.7
78
+ gemfile: gemfiles/rails42_boc.gemfile
79
+ - rvm: 2.5.7
80
+ gemfile: gemfiles/rails42_haml.gemfile
81
+ - rvm: 2.6.5
82
+ gemfile: gemfiles/rails42.gemfile
83
+ - rvm: 2.6.5
84
+ gemfile: gemfiles/rails42_boc.gemfile
85
+ - rvm: 2.6.5
86
+ gemfile: gemfiles/rails42_haml.gemfile
87
+ - rvm: 2.7.0
88
+ gemfile: gemfiles/rails42.gemfile
89
+ - rvm: 2.7.0
90
+ gemfile: gemfiles/rails42_boc.gemfile
91
+ - rvm: 2.7.0
92
+ gemfile: gemfiles/rails42_haml.gemfile
93
+ - rvm: ruby-head
94
+ gemfile: gemfiles/rails42.gemfile
95
+ - rvm: ruby-head
96
+ gemfile: gemfiles/rails42_boc.gemfile
97
+ - rvm: ruby-head
55
98
  gemfile: gemfiles/rails42_haml.gemfile
data/Gemfile CHANGED
@@ -3,3 +3,4 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  # gem "pry-byebug"
6
+ gem 'simplecov', require: false
data/README.md CHANGED
@@ -35,6 +35,28 @@ end
35
35
 
36
36
  _Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._
37
37
 
38
+ ### Optional: Set `EDITOR`
39
+
40
+ For many reasons outside of Better Errors, you should have the `EDITOR` environment variable set to your preferred
41
+ editor.
42
+ Better Errors, like many other tools, will use that environment variable to show a link that opens your
43
+ editor to the file and line from the console.
44
+
45
+ By default the links will open TextMate-protocol links.
46
+
47
+ To see if your editor is supported or to set up a different editor, see [the wiki](https://github.com/BetterErrors/better_errors/wiki/Link-to-your-editor).
48
+
49
+ ### Optional: Set `BETTER_ERRORS_INSIDE_FRAME`
50
+
51
+ If your application is running inside of an iframe, or if you have a Content Security Policy that disallows links
52
+ to other protocols, the editor links will not work.
53
+
54
+ To work around this set `BETTER_ERRORS_INSIDE_FRAME=1` in the environment, and the links will include `target=_blank`,
55
+ allowing the link to open regardless of the policy.
56
+
57
+ _This works because it opens the editor from a new browser tab, escaping from the restrictions of your site._
58
+ _Unfortunately it leaves behind an empty tab each time, so only use this if needed._
59
+
38
60
  ## Security
39
61
 
40
62
  **NOTE:** It is *critical* you put better\_errors only in the **development** section of your Gemfile.
@@ -93,6 +115,16 @@ See [the wiki for instructions on configuring the editor](https://github.com/Bet
93
115
  BetterErrors.maximum_variable_inspect_size = 100_000
94
116
  ```
95
117
 
118
+ ## Ignore inspection of variables with certain classes.
119
+
120
+ ```ruby
121
+ # e.g. in config/initializers/better_errors.rb
122
+ # This will stop BetterErrors from trying to inspect objects of these classes, which can cause
123
+ # slow loading times and unneccessary database queries. Does not check inheritance chain, use
124
+ # strings not contants.
125
+ # default value: ['ActionDispatch::Request', 'ActionDispatch::Response']
126
+ BetterErrors.ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
127
+ ```
96
128
 
97
129
  ## Get in touch!
98
130
 
@@ -22,9 +22,12 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency "rake", "~> 10.0"
24
24
  s.add_development_dependency "rspec", "~> 3.5"
25
+ s.add_development_dependency "rspec-html-matchers"
25
26
  s.add_development_dependency "rspec-its"
26
27
  s.add_development_dependency "yard"
27
- s.add_development_dependency "kramdown"
28
+ # kramdown 2.1 requires Ruby 2.3+
29
+ s.add_development_dependency "kramdown", (RUBY_VERSION < '2.3' ? '< 2.0.0' : '> 2.0.0')
30
+ # simplecov and coveralls must not be included here. See the Gemfiles instead.
28
31
 
29
32
  s.add_dependency "erubi", ">= 1.0.0"
30
33
  s.add_dependency "coderay", ">= 1.0.0"
@@ -33,4 +36,12 @@ Gem::Specification.new do |s|
33
36
  # optional dependencies:
34
37
  # s.add_dependency "binding_of_caller"
35
38
  # s.add_dependency "pry"
39
+
40
+ if s.respond_to?(:metadata)
41
+ s.metadata['changelog_uri'] = 'https://github.com/BetterErrors/better_errors/releases'
42
+ s.metadata['source_code_uri'] = 'https://github.com/BetterErrors/better_errors'
43
+ s.metadata['bug_tracker_uri'] = 'https://github.com/BetterErrors/better_errors/issues'
44
+ else
45
+ puts "Your RubyGems does not support metadata. Update if you'd like to make a release."
46
+ end
36
47
  end
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 4.2.0"
4
4
  gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
6
 
6
7
  gem 'coveralls', require: false
7
8
 
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 4.2.0"
4
4
  gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
6
  gem "binding_of_caller"
6
7
 
7
8
  gem 'coveralls', require: false
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 4.2.0"
4
4
  gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
6
  gem "haml"
6
7
 
7
8
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.0.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
 
5
6
  gem 'coveralls', require: false
6
7
 
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.0.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "binding_of_caller"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.0.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "haml"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.1.0"
4
+ gem 'i18n', '< 1.5.2', require: false if RUBY_VERSION < '2.3'
4
5
 
5
6
  gem 'coveralls', require: false
6
7
 
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.1.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "binding_of_caller"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.1.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "haml"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.2.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
 
5
6
  gem 'coveralls', require: false
6
7
 
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.2.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "binding_of_caller"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 5.2.0"
4
+ gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
4
5
  gem "haml"
5
6
 
6
7
  gem 'coveralls', require: false
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+
5
+ gem 'coveralls', require: false
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+ gem "binding_of_caller"
5
+
6
+ gem 'coveralls', require: false
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+ gem "haml"
5
+
6
+ gem 'coveralls', require: false
7
+
8
+ gemspec path: "../"
@@ -21,6 +21,7 @@ module BetterErrors
21
21
  { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" },
22
22
  { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" },
23
23
  { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" },
24
+ { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" },
24
25
  { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" },
25
26
  ]
26
27
 
@@ -54,9 +55,14 @@ module BetterErrors
54
55
  # the variable won't be returned.
55
56
  # @return int
56
57
  attr_accessor :maximum_variable_inspect_size
58
+
59
+ # List of classes that are excluded from inspection.
60
+ # @return [Array]
61
+ attr_accessor :ignored_classes
57
62
  end
58
63
  @ignored_instance_variables = []
59
64
  @maximum_variable_inspect_size = 100_000
65
+ @ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
60
66
 
61
67
  # Returns a proc, which when called with a filename and line number argument,
62
68
  # returns a URL to open the filename and line in the selected editor.
@@ -26,8 +26,13 @@ module BetterErrors
26
26
  @id ||= SecureRandom.hex(8)
27
27
  end
28
28
 
29
- def render(template_name = "main")
29
+ def render(template_name = "main", csrf_token = nil)
30
30
  binding.eval(self.class.template(template_name).src)
31
+ rescue => e
32
+ # Fix the backtrace, which doesn't identify the template that failed (within Better Errors).
33
+ # We don't know the line number, so just injecting the template path has to be enough.
34
+ e.backtrace.unshift "#{self.class.template_path(template_name)}:0"
35
+ raise
31
36
  end
32
37
 
33
38
  def do_variables(opts)
@@ -59,7 +64,19 @@ module BetterErrors
59
64
  end
60
65
 
61
66
  def exception_message
62
- exception.message.lstrip
67
+ exception.message.strip.gsub(/(\r?\n\s*\r?\n)+/, "\n")
68
+ end
69
+
70
+ def active_support_actions
71
+ return [] unless defined?(ActiveSupport::ActionableError)
72
+
73
+ ActiveSupport::ActionableError.actions(exception.type)
74
+ end
75
+
76
+ def action_dispatch_action_endpoint
77
+ return unless defined?(ActionDispatch::ActionableExceptions)
78
+
79
+ ActionDispatch::ActionableExceptions.endpoint
63
80
  end
64
81
 
65
82
  def application_frames
@@ -105,11 +122,17 @@ module BetterErrors
105
122
  end
106
123
 
107
124
  def inspect_value(obj)
108
- InspectableValue.new(obj).to_html
125
+ if BetterErrors.ignored_classes.include? obj.class.name
126
+ "<span class='unsupported'>(Instance of ignored class. "\
127
+ "#{obj.class.name ? "Remove #{CGI.escapeHTML(obj.class.name)} from" : "Modify"}"\
128
+ " BetterErrors.ignored_classes if you need to see it.)</span>"
129
+ else
130
+ InspectableValue.new(obj).to_html
131
+ end
109
132
  rescue BetterErrors::ValueLargerThanConfiguredMaximum
110
- "<span class='unsupported'>(object too large. "\
111
- "Modify #{CGI.escapeHTML(obj.class.name)}#inspect "\
112
- "or adjust BetterErrors.maximum_variable_inspect_size)</span>"
133
+ "<span class='unsupported'>(Object too large. "\
134
+ "#{obj.class.name ? "Modify #{CGI.escapeHTML(obj.class.name)}#inspect or a" : "A"}"\
135
+ "djust BetterErrors.maximum_variable_inspect_size if you need to see it.)</span>"
113
136
  rescue Exception => e
114
137
  "<span class='unsupported'>(exception #{CGI.escapeHTML(e.class.to_s)} was raised in inspect)</span>"
115
138
  end
@@ -1,5 +1,6 @@
1
1
  require "json"
2
2
  require "ipaddr"
3
+ require "securerandom"
3
4
  require "set"
4
5
  require "rack"
5
6
 
@@ -33,12 +34,14 @@ module BetterErrors
33
34
  # Adds an address to the set of IP addresses allowed to access Better
34
35
  # Errors.
35
36
  def self.allow_ip!(addr)
36
- ALLOWED_IPS << IPAddr.new(addr)
37
+ ALLOWED_IPS << (addr.is_a?(IPAddr) ? addr : IPAddr.new(addr))
37
38
  end
38
39
 
39
40
  allow_ip! "127.0.0.0/8"
40
41
  allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support
41
42
 
43
+ CSRF_TOKEN_COOKIE_NAME = 'BetterErrors-CSRF-Token'
44
+
42
45
  # A new instance of BetterErrors::Middleware
43
46
  #
44
47
  # @param app The Rack app/middleware to wrap with Better Errors
@@ -72,7 +75,7 @@ module BetterErrors
72
75
  def better_errors_call(env)
73
76
  case env["PATH_INFO"]
74
77
  when %r{/__better_errors/(?<id>.+?)/(?<method>\w+)\z}
75
- internal_call env, $~
78
+ internal_call(env, $~[:id], $~[:method])
76
79
  when %r{/__better_errors/?\z}
77
80
  show_error_page env
78
81
  else
@@ -89,11 +92,14 @@ module BetterErrors
89
92
  end
90
93
 
91
94
  def show_error_page(env, exception=nil)
95
+ request = Rack::Request.new(env)
96
+ csrf_token = request.cookies[CSRF_TOKEN_COOKIE_NAME] || SecureRandom.uuid
97
+
92
98
  type, content = if @error_page
93
99
  if text?(env)
94
100
  [ 'plain', @error_page.render('text') ]
95
101
  else
96
- [ 'html', @error_page.render ]
102
+ [ 'html', @error_page.render('main', csrf_token) ]
97
103
  end
98
104
  else
99
105
  [ 'html', no_errors_page ]
@@ -104,12 +110,22 @@ module BetterErrors
104
110
  status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
105
111
  end
106
112
 
107
- [status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }, [content]]
113
+ response = Rack::Response.new(content, status_code, { "Content-Type" => "text/#{type}; charset=utf-8" })
114
+
115
+ unless request.cookies[CSRF_TOKEN_COOKIE_NAME]
116
+ response.set_cookie(CSRF_TOKEN_COOKIE_NAME, value: csrf_token, httponly: true, same_site: :strict)
117
+ end
118
+
119
+ # In older versions of Rack, the body returned here is actually a Rack::BodyProxy which seems to be a bug.
120
+ # (It contains status, headers and body and does not act like an array of strings.)
121
+ # Since we already have status code and body here, there's no need to use the ones in the Rack::Response.
122
+ (_status_code, headers, _body) = response.finish
123
+ [status_code, headers, [content]]
108
124
  end
109
125
 
110
126
  def text?(env)
111
127
  env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" ||
112
- !env["HTTP_ACCEPT"].to_s.include?('html')
128
+ !env["HTTP_ACCEPT"].to_s.include?('html')
113
129
  end
114
130
 
115
131
  def log_exception
@@ -129,13 +145,22 @@ module BetterErrors
129
145
  end
130
146
  end
131
147
 
132
- def internal_call(env, opts)
148
+ def internal_call(env, id, method)
149
+ return not_found_json_response unless %w[variables eval].include?(method)
133
150
  return no_errors_json_response unless @error_page
134
- return invalid_error_json_response if opts[:id] != @error_page.id
151
+ return invalid_error_json_response if id != @error_page.id
152
+
153
+ request = Rack::Request.new(env)
154
+ return invalid_csrf_token_json_response unless request.cookies[CSRF_TOKEN_COOKIE_NAME]
155
+
156
+ request.body.rewind
157
+ body = JSON.parse(request.body.read)
158
+ return invalid_csrf_token_json_response unless request.cookies[CSRF_TOKEN_COOKIE_NAME] == body['csrfToken']
159
+
160
+ return not_acceptable_json_response unless request.content_type == 'application/json'
135
161
 
136
- env["rack.input"].rewind
137
- response = @error_page.send("do_#{opts[:method]}", JSON.parse(env["rack.input"].read))
138
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(response)]]
162
+ response = @error_page.send("do_#{method}", body)
163
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(response)]]
139
164
  end
140
165
 
141
166
  def no_errors_page
@@ -157,18 +182,40 @@ module BetterErrors
157
182
  "The application has been restarted since this page loaded, " +
158
183
  "or the framework is reloading all gems before each request "
159
184
  end
160
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(
185
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
161
186
  error: 'No exception information available',
162
187
  explanation: explanation,
163
188
  )]]
164
189
  end
165
190
 
166
191
  def invalid_error_json_response
167
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(
192
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
168
193
  error: "Session expired",
169
194
  explanation: "This page was likely opened from a previous exception, " +
170
195
  "and the exception is no longer available in memory.",
171
196
  )]]
172
197
  end
198
+
199
+ def invalid_csrf_token_json_response
200
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
201
+ error: "Invalid CSRF Token",
202
+ explanation: "The browser session might have been cleared, " +
203
+ "or something went wrong.",
204
+ )]]
205
+ end
206
+
207
+ def not_found_json_response
208
+ [404, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
209
+ error: "Not found",
210
+ explanation: "Not a recognized internal call.",
211
+ )]]
212
+ end
213
+
214
+ def not_acceptable_json_response
215
+ [406, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
216
+ error: "Request not acceptable",
217
+ explanation: "The internal request did not match an acceptable content type.",
218
+ )]]
219
+ end
173
220
  end
174
221
  end
@@ -4,9 +4,8 @@ module BetterErrors
4
4
  attr_reader :exception, :message, :backtrace
5
5
 
6
6
  def initialize(exception)
7
- if exception.respond_to?(:cause)
8
- exception = exception.cause if exception.cause
9
- elsif exception.respond_to?(:original_exception) && exception.original_exception
7
+ if exception.respond_to?(:original_exception) && exception.original_exception
8
+ # This supports some specific Rails exceptions, and is not intended to act the same as `#cause`.
10
9
  exception = exception.original_exception
11
10
  end
12
11
 
@@ -36,8 +35,13 @@ module BetterErrors
36
35
 
37
36
  def setup_backtrace_from_bindings
38
37
  @backtrace = exception.__better_errors_bindings_stack.map { |binding|
39
- file = binding.eval "__FILE__"
40
- line = binding.eval "__LINE__"
38
+ if binding.respond_to?(:source_location) # Ruby >= 2.6
39
+ file = binding.source_location[0]
40
+ line = binding.source_location[1]
41
+ else
42
+ file = binding.eval "__FILE__"
43
+ line = binding.eval "__LINE__"
44
+ end
41
45
  name = binding.frame_description
42
46
  StackFrame.new(file, line, name, binding)
43
47
  }
@@ -53,6 +57,10 @@ module BetterErrors
53
57
 
54
58
  def massage_syntax_error
55
59
  case exception.class.to_s
60
+ when "ActionView::Template::Error"
61
+ if exception.respond_to?(:file_name) && exception.respond_to?(:line_number)
62
+ backtrace.unshift(StackFrame.new(exception.file_name, exception.line_number.to_i, "view template"))
63
+ end
56
64
  when "Haml::SyntaxError", "Sprockets::Coffeelint::Error"
57
65
  if /\A(.+?):(\d+)/ =~ exception.backtrace.first
58
66
  backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
@@ -69,7 +69,10 @@ module BetterErrors
69
69
  def local_variables
70
70
  return {} unless frame_binding
71
71
 
72
- frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
72
+ lv = frame_binding.eval("local_variables")
73
+ return {} unless lv
74
+
75
+ lv.each_with_object({}) do |name, hash|
73
76
  # Ruby 2.2's local_variables will include the hidden #$! variable if
74
77
  # called from within a rescue context. This is not a valid variable name,
75
78
  # so the local_variable_get method complains. This should probably be
@@ -94,7 +97,10 @@ module BetterErrors
94
97
  end
95
98
 
96
99
  def visible_instance_variables
97
- frame_binding.eval("instance_variables") - BetterErrors.ignored_instance_variables
100
+ iv = frame_binding.eval("instance_variables")
101
+ return {} unless iv
102
+
103
+ iv - BetterErrors.ignored_instance_variables
98
104
  end
99
105
 
100
106
  def to_s
@@ -146,6 +146,14 @@
146
146
  }
147
147
 
148
148
  /* Heading */
149
+ header.exception .fix-actions {
150
+ margin-top: .5em;
151
+ }
152
+
153
+ header.exception .fix-actions input[type=submit] {
154
+ font-weight: bold;
155
+ }
156
+
149
157
  header.exception h2 {
150
158
  font-weight: 200;
151
159
  font-size: 11pt;
@@ -153,7 +161,7 @@
153
161
 
154
162
  header.exception h2,
155
163
  header.exception p {
156
- line-height: 1.4em;
164
+ line-height: 1.5em;
157
165
  overflow: hidden;
158
166
  white-space: pre;
159
167
  text-overflow: ellipsis;
@@ -166,7 +174,7 @@
166
174
 
167
175
  header.exception p {
168
176
  font-weight: 200;
169
- font-size: 20pt;
177
+ font-size: 17pt;
170
178
  color: white;
171
179
  }
172
180
 
@@ -744,6 +752,18 @@
744
752
  <header class="exception">
745
753
  <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
746
754
  <p><%= exception_message %></p>
755
+ <% unless active_support_actions.empty? %>
756
+ <div class='fix-actions'>
757
+ <% active_support_actions.each do |action, _| %>
758
+ <form class="button_to" method="post" action="<%= action_dispatch_action_endpoint %>">
759
+ <input type="submit" value="<%= action %>">
760
+ <input type="hidden" name="action" value="<%= action %>">
761
+ <input type="hidden" name="error" value="<%= exception_type %>">
762
+ <input type="hidden" name="location" value="<%= request_path %>">
763
+ </form>
764
+ <% end %>
765
+ </div>
766
+ <% end %>
747
767
  </header>
748
768
  </div>
749
769
 
@@ -780,6 +800,7 @@
780
800
  (function() {
781
801
 
782
802
  var OID = "<%= id %>";
803
+ var csrfToken = "<%= csrf_token %>";
783
804
 
784
805
  var previousFrame = null;
785
806
  var previousFrameInfo = null;
@@ -790,6 +811,7 @@
790
811
  var req = new XMLHttpRequest();
791
812
  req.open("POST", "//" + window.location.host + <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
792
813
  req.setRequestHeader("Content-Type", "application/json");
814
+ opts.csrfToken = csrfToken;
793
815
  req.send(JSON.stringify(opts));
794
816
  req.onreadystatechange = function() {
795
817
  if(req.readyState == 4) {
@@ -1,7 +1,14 @@
1
1
  <header class="trace_info clearfix">
2
2
  <div class="title">
3
3
  <h2 class="name"><%= @frame.name %></h2>
4
- <div class="location"><span class="filename"><a href="<%= editor_url(@frame) %>"><%= @frame.pretty_path %></a></span></div>
4
+ <div class="location">
5
+ <span class="filename">
6
+ <a
7
+ href="<%= editor_url(@frame) %>"
8
+ <%= ENV.key?('BETTER_ERRORS_INSIDE_FRAME') ? "target=_blank" : '' %>
9
+ ><%= @frame.pretty_path %></a>
10
+ </span>
11
+ </div>
5
12
  </div>
6
13
  <div class="code_block clearfix">
7
14
  <%== html_formatted_code_block @frame %>
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.5.0"
2
+ VERSION = "2.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-27 00:00:00.000000000 Z
11
+ date: 2020-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec-its
42
+ name: rspec-html-matchers
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: yard
56
+ name: rspec-its
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: kramdown
70
+ name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: kramdown
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: erubi
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +171,9 @@ files:
157
171
  - gemfiles/rails52.gemfile
158
172
  - gemfiles/rails52_boc.gemfile
159
173
  - gemfiles/rails52_haml.gemfile
174
+ - gemfiles/rails60.gemfile
175
+ - gemfiles/rails60_boc.gemfile
176
+ - gemfiles/rails60_haml.gemfile
160
177
  - lib/better_errors.rb
161
178
  - lib/better_errors/code_formatter.rb
162
179
  - lib/better_errors/code_formatter/html.rb
@@ -178,7 +195,10 @@ files:
178
195
  homepage: https://github.com/BetterErrors/better_errors
179
196
  licenses:
180
197
  - MIT
181
- metadata: {}
198
+ metadata:
199
+ changelog_uri: https://github.com/BetterErrors/better_errors/releases
200
+ source_code_uri: https://github.com/BetterErrors/better_errors
201
+ bug_tracker_uri: https://github.com/BetterErrors/better_errors/issues
182
202
  post_install_message:
183
203
  rdoc_options: []
184
204
  require_paths:
@@ -194,8 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
214
  - !ruby/object:Gem::Version
195
215
  version: '0'
196
216
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.7.6
217
+ rubygems_version: 3.1.2
199
218
  signing_key:
200
219
  specification_version: 4
201
220
  summary: Better error page for Rails and other Rack apps