-
Notifications
You must be signed in to change notification settings - Fork 26
/
handler.rb
96 lines (86 loc) · 3.16 KB
/
handler.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class RailsExceptionHandler::Handler
def initialize(env, exception)
@exception = exception
@env = env
@request = ActionDispatch::Request.new(@env)
@parsed_error = nil
if(@env['action_controller.instance'])
@controller = @env['action_controller.instance']
else
# A routing error has occurred and no controller instance exists. Here I am firing off a
# request to a dummy action that goes through the whole action dispatch stack, which will
# hopefully make sure that any authentication mechanism are properly initialized so that
# we may get the current_user object later.
@controller = ErrorResponseController.new
@controller.request = @request
@controller.response = ActionDispatch::Response.new
@controller.process(:dummy_action)
end
end
def handle_exception
@parsed_error = RailsExceptionHandler::Parser.new(@env, @request, @exception, @controller)
store_error unless(@parsed_error.ignore?)
return response
end
private
def store_error
RailsExceptionHandler.configuration.storage_strategies.each do |strategy|
if(strategy.class == Symbol)
RailsExceptionHandler::Storage.send(strategy, @parsed_error.external_info)
elsif(strategy.class == Hash && strategy[:remote_url])
RailsExceptionHandler::Storage.remote_url(strategy[:remote_url][:target],@parsed_error.external_info)
elsif(strategy.class == Hash && strategy[:email])
RailsExceptionHandler::Storage.email(strategy[:email][:recipients],@parsed_error.external_info)
else
raise "RailsExceptionHandler: Unknown storage strategy #{strategy.inspect}"
end
end
end
def response
@env['exception_handler.layout'] = response_layout
@env['exception_handler.response'] = response_text
response = ErrorResponseController.action(:index).call(@env)
if @parsed_error.routing_error?
response[0] = 404
file = "#{Rails.root}/public/404.html"
response = override_body_with_file_if_exists(response, file)
else
response[0] = 500
file = "#{Rails.root}/public/500.html"
response = override_body_with_file_if_exists(response, file)
end
return response
end
def override_body_with_file_if_exists(response, file)
return response unless File.exists?(file)
if defined? response[2].body=()
response[2].body = File.read(file)
else # Rails >= 4.2.0
response[2] = [File.read(file)]
end
return response
end
def response_layout
if(@request.xhr?)
false
else
if Rails::VERSION::MAJOR > 4
default_layout = @controller.send(:_default_layout, [:html])
else
default_layout = @controller.send(:_default_layout)
end
if(default_layout.class.to_s == "ActionView::Template")
layout = default_layout.virtual_path
else
layout = default_layout
end
layout || RailsExceptionHandler.configuration.fallback_layout
end
end
def response_text
config = RailsExceptionHandler.configuration
klass = @parsed_error.internal_info[:error_class]
key = config.response_mapping[klass] || :default
return config.responses[key]
end
end