On Wed, Jul 30, 2003 at 11:05:52AM +0900, Jesper Olsen wrote:
> Is there a way to configure the ruby cgi module to give
> trace back information incase of errors in the script?
> 
> Similar to pythons cgitb (cgitb.enable())...

You can just trap the exception and display it.

The attached code uses the ruby-fcgi library (which I recommend anyway -
your application then runs either as cgi or fcgi with no modification), but
you can just extract the begin-rescue-end bit for your use.

Regards,

Brian.
# Trivial CGI/FCGI application framework. Runs 'handle' for each request
# and has a last-ditch exception catcher

# TODO:
# - Allow stylesheet customisation of error page
# - Hook to allow logging of exceptions (or logging in general)

require 'fcgi'

module FCGIApp
class Base
  def initialize(cgi)
    @cgi = cgi
    @done_header = false
  end

  def header(*args)
    return if @done_header
    print @cgi.header(*args)
    @done_header = true
  end

  def end_request
    throw :end_request
  end

  def param(name)
    @cgi.params[name][0]   # works under both 1.6/1.8 without warnings
  end

  def env(name)
    @cgi.env_table[name]
  end

  REDIRECT_PAGE = <<EOS
<html>
<head><title>Moved</title></head>
<body>
Please click here to continue
<body>
</html>
EOS

  def redirect(url, status='301 Moved Temporarily')
    header( 'Status'=>status, 'Location'=>url )
    printf( REDIRECT_PAGE, url )
    end_request
  end

  # def handle: virtual (does the actual work of processing one request)

  def self.run(*htmlgen)
    FCGI.each_cgi(*htmlgen) do |cgi|
      begin
        app = self.new(cgi)
        catch(:end_request) do
          app.handle
        end
      rescue Exception => detail
        app ? app.header : (print cgi.header)
        print <<EOS
<html>
<head><title>Internal error in #{$0}</title></head>
<body>
<h1>Internal error in #{$0}</h1>
<b>#{CGI.escapeHTML(detail.message.to_s)}</b>
EOS
        puts "<pre>#{CGI.escapeHTML(detail.backtrace.join("\n"))}</pre>" if detail.backtrace
        puts "</body></html>"
      end
    end
  end
end # class Base
end # module FCGIAPP
#!/usr/local/bin/ruby -w

# Simple application which makes no use of templates or cookies.
# When run under fastcgi you will see the run counter incrementing,
# proving that it's a persistent process.

$:.unshift('../lib')
require 'fcgiapp/base'

class MyApp < FCGIApp::Base
  @@runcount = 0

  def handle
    @@runcount += 1
    #cmd = @cgi['command'][0]	# ruby 1.6/1.8, but warns under 1.8
    #cmd = @cgi['command']	# ruby 1.8 only
    cmd = param('command')	# portable but a tad less efficient

    case cmd
    when nil
      header
      puts "<html><body>"
      puts "I am PID #{Process.pid} and have run #{@@runcount} times<br />"
      puts "<form method=get>"
      puts "<input type=text name=v1>"
      puts "<input type=text name=v2>"
      puts "<input type=submit name=command value=add>"
      puts "<input type=submit name=command value=news>"
      puts "</form></body></html>"

    when 'add'
      ans = param('v1').to_i + param('v2').to_i
      header
      puts "<html><body>The answer is #{ans}</body></html>"

    when 'news'
      redirect "http://news.bbc.co.uk/"

    else
      header
      puts "<html><body>Sorry, unknown command #{CGI.escapeHTML(cmd)}</body></html>"
    end
  end
end

MyApp.run