better_errors 0.6.0 → 0.7.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.
Potentially problematic release.
This version of better_errors might be problematic. Click here for more details.
- data/.travis.yml +3 -0
- data/README.md +22 -2
- data/Rakefile +3 -0
- data/better_errors.gemspec +2 -0
- data/lib/better_errors.rb +2 -0
- data/lib/better_errors/middleware.rb +31 -18
- data/lib/better_errors/version.rb +1 -1
- data/spec/better_errors/middleware_spec.rb +17 -11
- metadata +8 -3
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -21,8 +21,6 @@ group :development do
|
|
21
21
|
end
|
22
22
|
```
|
23
23
|
|
24
|
-
**NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.**
|
25
|
-
|
26
24
|
If you would like to use Better Errors' **advanced features** (REPL, local/instance variable inspection, pretty stack frame names), you need to add the [`binding_of_caller`](https://github.com/banister/binding_of_caller) gem by [@banisterfiend](http://twitter.com/banisterfiend) to your Gemfile:
|
27
25
|
|
28
26
|
```ruby
|
@@ -31,6 +29,28 @@ gem "binding_of_caller"
|
|
31
29
|
|
32
30
|
This is an optional dependency however, and Better Errors will work without it.
|
33
31
|
|
32
|
+
## Security
|
33
|
+
|
34
|
+
**NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.**
|
35
|
+
|
36
|
+
You will notice that the only machine that gets the Better Errors page is localhost, which means you get the default error page if you are developing on a remote host (or a virtually remote host, such as a Vagrant box). Obviously, the REPL is not something you want to expose to the public, but there may also be other pieces of sensitive information available in the backtrace.
|
37
|
+
|
38
|
+
To poke selective holes in this security mechanism, you can add a line like this to your startup (for example, on Rails it would be `config/environments/development.rb`)
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP']
|
42
|
+
```
|
43
|
+
|
44
|
+
Then run Rails like this:
|
45
|
+
|
46
|
+
```shell
|
47
|
+
TRUSTED_IP=66.68.96.220 rails s
|
48
|
+
```
|
49
|
+
|
50
|
+
Note that the `allow_ip!` is actually backed by a `Set`, so you can add more than one IP address or subnet.
|
51
|
+
|
52
|
+
**Tip:** You can find your apparent IP by hitting the old error page's "Show env dump" and looking at "REMOTE_ADDR".
|
53
|
+
|
34
54
|
## Usage
|
35
55
|
|
36
56
|
If you're using Rails, there's nothing else you need to do.
|
data/Rakefile
CHANGED
data/better_errors.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
+
s.required_ruby_version = ">= 1.9.2"
|
21
|
+
|
20
22
|
s.add_development_dependency "rake"
|
21
23
|
s.add_development_dependency "rspec", "~> 2.12.0"
|
22
24
|
s.add_development_dependency "binding_of_caller"
|
data/lib/better_errors.rb
CHANGED
@@ -91,6 +91,8 @@ module BetterErrors
|
|
91
91
|
self.editor = "subl://open?url=file://%{file}&line=%{line}"
|
92
92
|
when :macvim, :mvim
|
93
93
|
self.editor = proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" }
|
94
|
+
when :emacs
|
95
|
+
self.editor = "emacs://open?url=file://%{file}&line=%{line}"
|
94
96
|
when String
|
95
97
|
self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } }
|
96
98
|
else
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require "json"
|
2
2
|
require "ipaddr"
|
3
|
+
require "set"
|
3
4
|
|
4
5
|
module BetterErrors
|
5
6
|
# Better Errors' error handling middleware. Including this in your middleware
|
6
7
|
# stack will show a Better Errors error page for exceptions raised below this
|
7
8
|
# middleware.
|
8
|
-
#
|
9
|
-
# If you are using Ruby on Rails, you do not need to manually insert this
|
9
|
+
#
|
10
|
+
# If you are using Ruby on Rails, you do not need to manually insert this
|
10
11
|
# middleware into your middleware stack.
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# @example Sinatra
|
13
14
|
# require "better_errors"
|
14
|
-
#
|
15
|
+
#
|
15
16
|
# if development?
|
16
17
|
# use BetterErrors::Middleware
|
17
18
|
# end
|
@@ -21,39 +22,51 @@ module BetterErrors
|
|
21
22
|
# if ENV["RACK_ENV"] == "development"
|
22
23
|
# use BetterErrors::Middleware
|
23
24
|
# end
|
24
|
-
#
|
25
|
+
#
|
25
26
|
class Middleware
|
27
|
+
# The set of IP addresses that are allowed to access Better Errors.
|
28
|
+
#
|
29
|
+
# Set to `{ "127.0.0.1/8", "::1/128" }` by default.
|
30
|
+
ALLOWED_IPS = Set.new
|
31
|
+
|
32
|
+
# Adds an address to the set of IP addresses allowed to access Better
|
33
|
+
# Errors.
|
34
|
+
def self.allow_ip!(addr)
|
35
|
+
ALLOWED_IPS << IPAddr.new(addr)
|
36
|
+
end
|
37
|
+
|
38
|
+
allow_ip! "127.0.0.0/8"
|
39
|
+
allow_ip! "::1/128"
|
40
|
+
|
26
41
|
# A new instance of BetterErrors::Middleware
|
27
|
-
#
|
42
|
+
#
|
28
43
|
# @param app The Rack app/middleware to wrap with Better Errors
|
29
44
|
# @param handler The error handler to use.
|
30
45
|
def initialize(app, handler = ErrorPage)
|
31
46
|
@app = app
|
32
47
|
@handler = handler
|
33
48
|
end
|
34
|
-
|
49
|
+
|
35
50
|
# Calls the Better Errors middleware
|
36
|
-
#
|
51
|
+
#
|
37
52
|
# @param [Hash] env
|
38
53
|
# @return [Array]
|
39
54
|
def call(env)
|
40
|
-
if
|
55
|
+
if allow_ip? env
|
41
56
|
better_errors_call env
|
42
57
|
else
|
43
58
|
@app.call env
|
44
59
|
end
|
45
60
|
end
|
46
|
-
|
61
|
+
|
47
62
|
private
|
48
|
-
IPV4_LOCAL = IPAddr.new("127.0.0.0/8")
|
49
|
-
IPV6_LOCAL = IPAddr.new("::1/128")
|
50
63
|
|
51
|
-
def
|
64
|
+
def allow_ip?(env)
|
52
65
|
# REMOTE_ADDR is not in the rack spec, so some application servers do
|
53
66
|
# not provide it.
|
54
67
|
return true unless env["REMOTE_ADDR"]
|
55
68
|
ip = IPAddr.new env["REMOTE_ADDR"]
|
56
|
-
|
69
|
+
ALLOWED_IPS.any? { |subnet| subnet.include? ip }
|
57
70
|
end
|
58
71
|
|
59
72
|
def better_errors_call(env)
|
@@ -93,18 +106,18 @@ module BetterErrors
|
|
93
106
|
env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" ||
|
94
107
|
!env["HTTP_ACCEPT"].to_s.include?('html')
|
95
108
|
end
|
96
|
-
|
109
|
+
|
97
110
|
def log_exception
|
98
111
|
return unless BetterErrors.logger
|
99
|
-
|
112
|
+
|
100
113
|
message = "\n#{@error_page.exception.class} - #{@error_page.exception.message}:\n"
|
101
114
|
@error_page.backtrace_frames.each do |frame|
|
102
115
|
message << " #{frame}\n"
|
103
116
|
end
|
104
|
-
|
117
|
+
|
105
118
|
BetterErrors.logger.fatal message
|
106
119
|
end
|
107
|
-
|
120
|
+
|
108
121
|
def internal_call(env, opts)
|
109
122
|
if opts[:oid].to_i != @error_page.object_id
|
110
123
|
return [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(error: "Session expired")]]
|
@@ -23,48 +23,54 @@ module BetterErrors
|
|
23
23
|
app.call("REMOTE_ADDR" => "1.2.3.4")
|
24
24
|
end
|
25
25
|
|
26
|
+
it "should show to a whitelisted IP" do
|
27
|
+
BetterErrors::Middleware.allow_ip! '77.55.33.11'
|
28
|
+
app.should_receive :better_errors_call
|
29
|
+
app.call("REMOTE_ADDR" => "77.55.33.11")
|
30
|
+
end
|
31
|
+
|
26
32
|
context "when requesting the /__better_errors manually" do
|
27
33
|
let(:app) { Middleware.new(->env { ":)" }) }
|
28
|
-
|
34
|
+
|
29
35
|
it "should show that no errors have been recorded" do
|
30
36
|
status, headers, body = app.call("PATH_INFO" => "/__better_errors")
|
31
37
|
body.join.should match /No errors have been recorded yet./
|
32
38
|
end
|
33
39
|
end
|
34
|
-
|
40
|
+
|
35
41
|
context "when handling an error" do
|
36
42
|
let(:app) { Middleware.new(->env { raise "oh no :(" }) }
|
37
|
-
|
43
|
+
|
38
44
|
it "should return status 500" do
|
39
45
|
status, headers, body = app.call({})
|
40
|
-
|
46
|
+
|
41
47
|
status.should == 500
|
42
48
|
end
|
43
|
-
|
49
|
+
|
44
50
|
it "should return UTF-8 error pages" do
|
45
51
|
status, headers, body = app.call({})
|
46
|
-
|
52
|
+
|
47
53
|
headers["Content-Type"].should match /charset=utf-8/
|
48
54
|
end
|
49
55
|
|
50
56
|
it "should return text pages by default" do
|
51
57
|
status, headers, body = app.call({})
|
52
|
-
|
58
|
+
|
53
59
|
headers["Content-Type"].should match /text\/plain/
|
54
60
|
end
|
55
|
-
|
61
|
+
|
56
62
|
it "should return HTML pages by default" do
|
57
63
|
# Chrome's 'Accept' header looks similar this.
|
58
64
|
status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*")
|
59
|
-
|
65
|
+
|
60
66
|
headers["Content-Type"].should match /text\/html/
|
61
67
|
end
|
62
|
-
|
68
|
+
|
63
69
|
it "should log the exception" do
|
64
70
|
logger = Object.new
|
65
71
|
logger.should_receive :fatal
|
66
72
|
BetterErrors.stub!(:logger).and_return(logger)
|
67
|
-
|
73
|
+
|
68
74
|
app.call({})
|
69
75
|
end
|
70
76
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_errors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -165,6 +165,7 @@ extensions: []
|
|
165
165
|
extra_rdoc_files: []
|
166
166
|
files:
|
167
167
|
- .gitignore
|
168
|
+
- .travis.yml
|
168
169
|
- .yardopts
|
169
170
|
- CONTRIBUTING.md
|
170
171
|
- Gemfile
|
@@ -211,13 +212,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
211
212
|
requirements:
|
212
213
|
- - '>='
|
213
214
|
- !ruby/object:Gem::Version
|
214
|
-
version:
|
215
|
+
version: 1.9.2
|
215
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
217
|
none: false
|
217
218
|
requirements:
|
218
219
|
- - '>='
|
219
220
|
- !ruby/object:Gem::Version
|
220
221
|
version: '0'
|
222
|
+
segments:
|
223
|
+
- 0
|
224
|
+
hash: -156735969867517913
|
221
225
|
requirements: []
|
222
226
|
rubyforge_project:
|
223
227
|
rubygems_version: 1.8.25
|
@@ -235,3 +239,4 @@ test_files:
|
|
235
239
|
- spec/better_errors/support/my_source.rb
|
236
240
|
- spec/better_errors_spec.rb
|
237
241
|
- spec/spec_helper.rb
|
242
|
+
has_rdoc:
|