| Class | Rack::ShowExceptions |
| In: |
lib/rack/showexceptions.rb
|
| Parent: | Object |
Rack::ShowExceptions catches all exceptions raised from the app it wraps. It shows a useful backtrace with the sourcefile and clickable context, the whole Rack environment and the request data.
Be careful when you use this on public-facing sites as it could reveal information helpful to attackers.
| CONTEXT | = | 7 |
# File lib/rack/showexceptions.rb, line 17
17: def initialize(app)
18: @app = app
19: @template = ERB.new(TEMPLATE)
20: end
# File lib/rack/showexceptions.rb, line 22
22: def call(env)
23: @app.call(env)
24: rescue StandardError, LoadError, SyntaxError => e
25: backtrace = pretty(env, e)
26: [500,
27: {"Content-Type" => "text/html",
28: "Content-Length" => backtrace.join.size.to_s},
29: backtrace]
30: end
# File lib/rack/showexceptions.rb, line 32
32: def pretty(env, exception)
33: req = Rack::Request.new(env)
34: path = (req.script_name + req.path_info).squeeze("/")
35:
36: frames = exception.backtrace.map { |line|
37: frame = OpenStruct.new
38: if line =~ /(.*?):(\d+)(:in `(.*)')?/
39: frame.filename = $1
40: frame.lineno = $2.to_i
41: frame.function = $4
42:
43: begin
44: lineno = frame.lineno-1
45: lines = ::File.readlines(frame.filename)
46: frame.pre_context_lineno = [lineno-CONTEXT, 0].max
47: frame.pre_context = lines[frame.pre_context_lineno...lineno]
48: frame.context_line = lines[lineno].chomp
49: frame.post_context_lineno = [lineno+CONTEXT, lines.size].min
50: frame.post_context = lines[lineno+1..frame.post_context_lineno]
51: rescue
52: end
53:
54: frame
55: else
56: nil
57: end
58: }.compact
59:
60: env["rack.errors"].puts "#{exception.class}: #{exception.message}"
61: env["rack.errors"].puts exception.backtrace.map { |l| "\t" + l }
62: env["rack.errors"].flush
63:
64: [@template.result(binding)]
65: end