module Roda::RodaPlugins::ExceptionPage::InstanceMethods
Public Instance Methods
Source
# File lib/roda/plugins/exception_page.rb, line 198 def exception_page(exception, opts=OPTS) message = exception_page_exception_message(exception) if opts[:json] @_response[RodaResponseHeaders::CONTENT_TYPE] = "application/json" { "exception"=>{ "class"=>exception.class.to_s, "message"=>message, "backtrace"=>exception.backtrace.map(&:to_s) } } elsif env['HTTP_ACCEPT'] =~ /text\/html/ @_response[RodaResponseHeaders::CONTENT_TYPE] = "text/html" context = opts[:context] || 7 css_file = opts[:css_file] js_file = opts[:js_file] case prefix = opts[:assets] when false css_file = false if css_file.nil? js_file = false if js_file.nil? when nil # nothing else prefix = '' if prefix == true css_file ||= "#{prefix}/exception_page.css" js_file ||= "#{prefix}/exception_page.js" end css = case css_file when nil "<style type=\"text/css\">#{exception_page_css}</style>" when false # :nothing else "<link rel=\"stylesheet\" href=\"#{h css_file}\" />" end js = case js_file when nil "<script type=\"text/javascript\">\n//<!--\n#{exception_page_js}\n//-->\n</script>" when false # :nothing else "<script type=\"text/javascript\" src=\"#{h js_file}\"></script>" end frames = exception.backtrace.map.with_index do |line, i| frame = {:id=>i} if line =~ /\A(.*?):(\d+)(?::in [`'](.*)')?\Z/ filename = frame[:filename] = $1 lineno = frame[:lineno] = $2.to_i frame[:function] = $3 begin lineno -= 1 lines = ::File.readlines(filename) if line = lines[lineno] pre_lineno = [lineno-context, 0].max if (pre_context = lines[pre_lineno...lineno]) && !pre_context.empty? frame[:pre_context_lineno] = pre_lineno frame[:pre_context] = pre_context end post_lineno = [lineno+context, lines.size].min if (post_context = lines[lineno+1..post_lineno]) && !post_context.empty? frame[:post_context_lineno] = post_lineno frame[:post_context] = post_context end frame[:context_line] = line.chomp end rescue end frame end end.compact r = @_request begin post_data = r.POST missing_post = "No POST data" rescue missing_post = "Invalid POST data" end info = lambda do |title, id, var, none| <<END <h3 id="#{id}">#{title}</h3> #{(var && !var.empty?) ? (<<END1) : "<p>#{none}</p>" <table class="req"> <thead> <tr> <th>Variable</th> <th>Value</th> </tr> </thead> <tbody> #{var.sort_by{|k, _| k.to_s}.map{|key, val| (<<END2)}.join <tr> <td>#{h key}</td> <td class="code"><div>#{h val.inspect}</div></td> </tr> END2 } </tbody> </table> END1 } END end <<END <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>#{h exception.class} at #{h r.path}</title> #{css} </head> <body> <div id="summary"> <h1>#{h exception.class} at #{h r.path}</h1> <h2>#{h message}</h2> <table><tr> <th>Ruby</th> <td> #{(first = frames.first) ? "<code>#{h first[:filename]}</code>: in <code>#{h first[:function]}</code>, line #{first[:lineno]}" : "unknown location"} </td> </tr><tr> <th>Web</th> <td><code>#{r.request_method} #{h r.host}#{h r.path}</code></td> </tr></table> <h3>Jump to:</h3> <ul id="quicklinks"> <li><a href="#get-info">GET</a></li> <li><a href="#post-info">POST</a></li> <li><a href="#cookie-info">Cookies</a></li> <li><a href="#env-info">ENV</a></li> </ul> </div> <div id="traceback"> <h2>Traceback <span>(innermost first)</span></h2> <ul class="traceback"> #{frames.map{|frame| id = frame[:id]; (<<END1)}.join <li class="frame"> <code>#{h frame[:filename]}:#{frame[:lineno]}</code> in <code>#{h frame[:function]}</code> #{frame[:context_line] ? (<<END2) : '</li>' <div class="context" id="c#{id}"> #{frame[:pre_context] ? (<<END3) : '' <ol start="#{frame[:pre_context_lineno]+1}" id="bc#{id}"> #{frame[:pre_context].map{|line| "<li>#{h line}</li>"}.join} </ol> END3 } <ol start="#{frame[:lineno]}" class="context-line"> <li>#{h frame[:context_line]}<span>...</span></li> </ol> #{frame[:post_context] ? (<<END4) : '' <ol start='#{frame[:lineno]+1}' id="ac#{id}"> #{frame[:post_context].map{|line| "<li>#{h line}</li>"}.join} </ol> END4 } </div> END2 } END1 } </ul> </div> <div id="requestinfo"> <h2>Request information</h2> #{info.call('GET', 'get-info', r.GET, 'No GET data')} #{info.call('POST', 'post-info', post_data, missing_post)} #{info.call('Cookies', 'cookie-info', r.cookies, 'No cookie data')} #{info.call('Rack ENV', 'env-info', r.env, 'No Rack env?')} </div> <div id="explanation"> <p> You're seeing this error because you use the Roda exception_page plugin. </p> </div> #{js} </body> </html> END else @_response[RodaResponseHeaders::CONTENT_TYPE] = "text/plain" "#{exception.class}: #{message}\n#{exception.backtrace.map{|l| "\t#{l}"}.join("\n")}" end end
Return a HTML page showing the exception, allowing a developer more information for debugging. Designed to be called inside an exception handler, passing in the received exception. Sets the Content-Type header in the response, and returns the string used for the body. If the Accept request header is present and text/html is accepted, return an HTML page with the backtrace with the ability to see the context for each backtrace line, as well as the GET, POST, cookie, and rack environment data. If text/html is not accepted, then just show a plain text page with the exception class, message, and backtrace.
Options:
- :assets
-
If
true
, sets :css_file to/exception_page.css
and :js_file to/exception_page.js
, assuming thatr.exception_page_assets
is called in the route block to serve the exception page assets. If a String, uses the string as a prefix, assuming thatr.exception_page_assets
is called in a nested block inside the route block. If false, doesn’t use any CSS or JS. - :context
-
The number of context lines before and after each line in the backtrace (default: 7).
- :css_file
-
A path to the external CSS file for the HTML exception page. If false, doesn’t use any CSS.
- :js_file
-
A path to the external javascript file for the HTML exception page. If false, doesn’t use any JS.
- :json
-
Return a hash of exception information. The hash will have a single key, “exception”, with a value being a hash with three keys, “class”, “message”, and “backtrace”, which contain information derived from the given exception. Designed to be used with the
json
exception, which will automatically convert the hash to JSON format.
Source
# File lib/roda/plugins/exception_page.rb, line 403 def exception_page_css ExceptionPage.css end
The CSS to use on the exception page
Source
# File lib/roda/plugins/exception_page.rb, line 408 def exception_page_js ExceptionPage.js end
The JavaScript to use on the exception page
Private Instance Methods
Source
# File lib/roda/plugins/exception_page.rb, line 415 def exception_page_exception_message(exception) exception.detailed_message(highlight: false).to_s end