~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/actionpack/lib/action_controller/failsafe.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
require 'erb'
2
 
 
3
 
module ActionController
4
 
  # The Failsafe middleware is usually the top-most middleware in the Rack
5
 
  # middleware chain. It returns the underlying middleware's response, but if
6
 
  # the underlying middle raises an exception then Failsafe will log the
7
 
  # exception into the Rails log file, and will attempt to return an error
8
 
  # message response.
9
 
  #
10
 
  # Failsafe is a last resort for logging errors and for telling the HTTP
11
 
  # client that something went wrong. Do not confuse this with the
12
 
  # ActionController::Rescue module, which is responsible for catching
13
 
  # exceptions at deeper levels. Unlike Failsafe, which is as simple as
14
 
  # possible, Rescue provides features that allow developers to hook into
15
 
  # the error handling logic, and can customize the error message response
16
 
  # based on the HTTP client's IP.
17
 
  class Failsafe
18
 
    cattr_accessor :error_file_path
19
 
    self.error_file_path = Rails.public_path if defined?(Rails.public_path)
20
 
 
21
 
    def initialize(app)
22
 
      @app = app
23
 
    end
24
 
 
25
 
    def call(env)
26
 
      @app.call(env)
27
 
    rescue Exception => exception
28
 
      # Reraise exception in test environment
29
 
      if defined?(Rails) && Rails.env.test?
30
 
        raise exception
31
 
      else
32
 
        failsafe_response(exception)
33
 
      end
34
 
    end
35
 
 
36
 
    private
37
 
      def failsafe_response(exception)
38
 
        log_failsafe_exception(exception)
39
 
        [500, {'Content-Type' => 'text/html'}, [failsafe_response_body]]
40
 
      rescue Exception => failsafe_error # Logger or IO errors
41
 
        $stderr.puts "Error during failsafe response: #{failsafe_error}"
42
 
      end
43
 
 
44
 
      def failsafe_response_body
45
 
        error_template_path = "#{self.class.error_file_path}/500.html"
46
 
        if File.exist?(error_template_path)
47
 
          begin
48
 
            result = render_template(error_template_path)
49
 
          rescue Exception
50
 
            result = nil
51
 
          end
52
 
        else
53
 
          result = nil
54
 
        end
55
 
        if result.nil?
56
 
          result = "<html><body><h1>500 Internal Server Error</h1>" <<
57
 
            "If you are the administrator of this website, then please read this web " <<
58
 
            "application's log file to find out what went wrong.</body></html>"
59
 
        end
60
 
        result
61
 
      end
62
 
      
63
 
      # The default 500.html uses the h() method.
64
 
      def h(text) # :nodoc:
65
 
        ERB::Util.h(text)
66
 
      end
67
 
      
68
 
      def render_template(filename)
69
 
        ERB.new(File.read(filename)).result(binding)
70
 
      end
71
 
 
72
 
      def log_failsafe_exception(exception)
73
 
        message = "/!\\ FAILSAFE /!\\  #{Time.now}\n  Status: 500 Internal Server Error\n"
74
 
        message << "  #{exception}\n    #{exception.backtrace.join("\n    ")}" if exception
75
 
        failsafe_logger.fatal(message)
76
 
      end
77
 
 
78
 
      def failsafe_logger
79
 
        if defined?(Rails) && Rails.logger
80
 
          Rails.logger
81
 
        else
82
 
          Logger.new($stderr)
83
 
        end
84
 
      end
85
 
  end
86
 
end