cgi-exception 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,18 @@
1
1
  = CHANGES
2
2
 
3
3
 
4
+ == Release 0.3.0 (2008-07-19)
5
+
6
+ === Enhancements
7
+
8
+ * Re-writed entirely
9
+
10
+ * EditorKicker support to invoke TextMate or Emacs automatically
11
+ when an error raised.
12
+
13
+ * Add example script for FastCGI
14
+
15
+
4
16
 
5
17
  == Release 0.2.0 (2008-02-21)
6
18
 
data/README.txt CHANGED
@@ -1,20 +1,24 @@
1
1
  = README.txt
2
2
 
3
- Release: 0.2.0
4
-
5
- copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
3
+ Release: 0.3.0
6
4
 
5
+ http://cgi-exception.rubyforge.org/
7
6
  http://rubyforge.org/projects/cgi-exception/
8
7
 
9
8
 
10
9
  == About
11
10
 
12
- 'cgi_exception.rb' is a small script to show exception raised in your
11
+ CGI-Exception is a small script to show exception raised in your
13
12
  CGI script into browser, like PHP. You don't need to look for error
14
13
  messages in Web server's log file.
15
14
 
16
- NOTICE: cig_exception.rb works only with CGI or mod_ruby. It doesn't
17
- support FastCGI.
15
+ In addition, CGI-Exception supports EditorKicker which is a pretty
16
+ tool to invoke your favorite editor and open errored file when an
17
+ exception raised on your script.
18
+ See http://editorkicker.rubyforge.org/ for details.
19
+
20
+ NOTICE: CGI-Exception supports CGI and mod_ruby, and it is easy
21
+ to use it in FastCGI (see blow for detail).
18
22
 
19
23
 
20
24
  == Install
@@ -27,8 +31,10 @@ Or, just type 'ruby setup.rb' with administrator priviledge.
27
31
  Or, copy 'lib/cgi_exception.rb' to proper directory such as
28
32
  '/usr/local/lib/ruby/site_ruby/1.8'.
29
33
 
34
+ It is recommended to install EditorKicker as well as CGI-Exception.
35
+
30
36
  NOTICE: It is NOT recommended to install by RubyGems, because
31
- 'require "rubygems"' is too heavy for CGI program.
37
+ 'require "rubygems"' is too heavy operation for CGI program.
32
38
 
33
39
 
34
40
  == Usage
@@ -37,25 +43,56 @@ All you have to do is to require 'cgi_exception'.
37
43
  If you do so and exception raised, what and where exception raised will
38
44
  be shown in browser.
39
45
 
46
+ In addition, if you installed and required EditorKicker, TextMate or
47
+ Emacs will be invoked automatically when you got exceptions.
48
+ See README of EditorKicker for details.
49
+
40
50
 
41
51
  == Example
42
52
 
43
- For example, the following code will raise exception at line 4, because
53
+ For example, the following code will raise exception at line 5, because
44
54
  local variable 'user' is not initialized.
45
55
 
46
- #!/usr/bin/env ruby
47
- require 'cgi'
48
- require 'cgi_exception'
49
- html = "<p>Hello #{user}!</p>\n"
50
- print CGI.new.header
51
- print html
56
+ 1: #!/usr/bin/env ruby
57
+ 2: require 'cgi'
58
+ 3: require 'cgi_exception'
59
+ 4: require 'editor_kicker' if ENV['SERVER_NAME'] == 'localhost'
60
+ 5: print CGI.new.header('text/html')
61
+ 6: print " <h1>Example</h1>\n"
62
+ 7: print " <p>Hello #{user}</p>\n" # ERROR!
63
+ 8: print " <p>unreachable</p>\n"
52
64
 
53
65
  You'll see the following message in your browser if you access the above
54
66
  CGI script.
55
67
 
56
- /var/www/cgi-bin/foo.cgi:4: undefined local variable or method `user'
68
+ /var/www/cgi-bin/foo.cgi:7: undefined local variable or method `user'
57
69
  for main:Object (NameError)
58
70
 
71
+ If you are using FastCGI, try the following code:
72
+
73
+ #!/usr/bin/env ruby
74
+ require 'cgi'
75
+ require 'fcgi'
76
+ require 'cgi_exception'
77
+
78
+ FCGI.each do |cgi|
79
+ begin
80
+ print cgi.header('text/html')
81
+ print " <h1>Example</h1>\n"
82
+ print " <p>Hello #{user}</p>\n" # ERROR!
83
+ print " <p>unreachable</p>\n"
84
+ rescue Exception => ex
85
+ CGIExceptionPrinter.new(false).handle(ex)
86
+ ## invoke Emacs automatically only when on localhost
87
+ if cgi.env_table['SERVER_NAME'] == 'localhost'
88
+ require 'editor_kicker'
89
+ ENV['EDITOR_KICKER'] = \
90
+ "emacsclient -n -s /tmp/emacs501/server +%s '%s'"
91
+ EditorKicker.handle(ex)
92
+ end
93
+ end
94
+ end
95
+
59
96
 
60
97
  == License
61
98
 
@@ -64,4 +101,6 @@ public domain
64
101
 
65
102
  == Author
66
103
 
67
- makoto kuwata <kwa.at.kuwata-lab.com>
104
+ makoto kuwata <kwa(at)kuwata-lab.com>
105
+
106
+ copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/ruby
2
+
3
+ ###
4
+ ### $Rev: 17 $
5
+ ### $Release: 0.3.0 $
6
+ ### copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
7
+ ###
8
+
9
+ require 'rubygems'
10
+
11
+ spec = Gem::Specification.new do |s|
12
+ ## package information
13
+ s.name = "cgi-exception"
14
+ s.author = "makoto kuwata"
15
+ s.email = "kwa(at)kuwata-lab.com"
16
+ s.rubyforge_project = 'cgi-exception'
17
+ s.version = "0.3.0"
18
+ s.platform = Gem::Platform::RUBY
19
+ s.homepage = "http://cgi-exception.rubyforge.org/"
20
+ s.summary = "Utility to display what and at where exception raised in CGI script"
21
+ s.description = <<-'END'
22
+ cgi-exception.rb is a tiny utility to display what and at where exception raised in CGI script just like PHP.
23
+ You don't need to look for error message in web server's log file.
24
+ END
25
+
26
+ ## files
27
+ files = []
28
+ files += Dir.glob('lib/**/*.rb')
29
+ files += Dir.glob('test/**/*.rb')
30
+ files += %W[README.txt CHANGES.txt setup.rb #{s.name}.gemspec]
31
+ s.files = files
32
+ end
33
+
34
+ # Quick fix for Ruby 1.8.3 / YAML bug (thanks to Ross Bamford)
35
+ if (RUBY_VERSION == '1.8.3')
36
+ def spec.to_yaml
37
+ out = super
38
+ out = '--- ' + out unless out =~ /^---/
39
+ out
40
+ end
41
+ end
42
+
43
+ if $0 == __FILE__
44
+ Gem::manage_gems
45
+ Gem::Builder.new(spec).build
46
+ end
@@ -1,57 +1,82 @@
1
1
  ##
2
- ## $Rev: 7 $
3
- ## $Release: 0.2.0 $
2
+ ## $Rev: 16 $
3
+ ## $Release: 0.3.0 $
4
4
  ## copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
5
5
  ## License: public domain
6
6
  ##
7
7
 
8
- ## escape HTML characters
9
- def _esc_html(s)
10
- s.to_s.gsub(/&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
11
- end
8
+ class CGIExceptionPrinter
12
9
 
13
- ## print exception in HTML format
14
- def _print_exception(ex)
15
- arr = ex.backtrace
16
- print "<pre style=\"color:#CC0000\">"
17
- print "<b>#{_esc_html arr[0]}: #{_esc_html ex.message} (#{ex.class.name})</b>\n"
18
- block = proc {|s| print " from #{_esc_html s}\n" }
19
- max = 20
20
- if arr.length <= max
21
- arr[1..-1].each(&block)
22
- else
23
- n = 5
24
- arr[1..(max-n)].each(&block)
25
- print " ...\n"
26
- arr[-n..-1].each(&block)
10
+ def initialize(skip_header=false, out=$stdout)
11
+ @skip_header = skip_header
12
+ @out = out
27
13
  end
28
- print "</pre>"
29
- end
30
14
 
31
- ## print HTTP header (for CGI program)
32
- def _print_http_header_for_cgi()
33
- print "Status: 500 Internal Error\r\n"
34
- print "Content-Type: text/html\r\n"
35
- print "X-CGI-Exception: 0.2.0\r\n"
36
- print "\r\n"
37
- end
15
+ attr_accessor :skip_header, :out
16
+
17
+ ## escape HTML characters
18
+ def escape_html(s)
19
+ s.to_s.gsub(/&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
20
+ end
21
+
22
+ alias h escape_html
23
+
24
+ ## print http header
25
+ def print_header()
26
+ @out.print "Status: 500 Internal Error\r\n"
27
+ @out.print "Content-Type: text/html\r\n"
28
+ @out.print "X-CGI-Exception: 0.3.0\r\n"
29
+ @out.print "\r\n"
30
+ end
31
+
32
+ ## print exception in HTML format
33
+ def print_exception(ex)
34
+ arr = ex.backtrace
35
+ @out.print "<pre style=\"color:#CC0000\">"
36
+ @out.print "<b>#{h(arr[0])}: #{h(ex.message)} (#{h(ex.class.name)})</b>\n"
37
+ block = proc {|s| @out.print " from #{h(s)}\n" }
38
+ max = 20
39
+ if arr.length <= max
40
+ arr[1..-1].each(&block)
41
+ else
42
+ n = 5
43
+ arr[1..(max-n)].each(&block)
44
+ @out.print " ...\n"
45
+ arr[-n..-1].each(&block)
46
+ end
47
+ @out.print "</pre>"
48
+ end
49
+
50
+ def handle(exception)
51
+ print_header() unless @skip_header
52
+ print_exception(exception)
53
+ end
38
54
 
39
- ## print HTTP header (for mod_ruby)
40
- def _print_http_header_for_modruby()
41
- request = Apache::request
42
- request.status = 500
43
- request.status_line = '500 Internal Error'
44
- request.content_type = 'text/html'
45
- request.headers_out['X-CGI-Exception'] = '0.2.0'
46
- request.send_http_header
47
55
  end
48
56
 
49
- if defined?(MOD_RUBY)
50
57
 
51
- def _print_http_header() # don't use alias
52
- _print_http_header_for_modruby()
58
+ class ModRubyExceptionPrinter < CGIExceptionPrinter
59
+
60
+ ## print HTTP header (for mod_ruby)
61
+ def print_header
62
+ request = Apache::request
63
+ request.status = 500
64
+ request.status_line = '500 Internal Error'
65
+ request.content_type = 'text/html'
66
+ request.headers_out['X-CGI-Exception'] = '0.3.0'
67
+ request.send_http_header
68
+ end
69
+
70
+ def print_exception(ex)
71
+ super
72
+ $stderr.write "#{ex.backtrace[0]}: #{ex.message} (#{ex.class.name})\n"
53
73
  end
54
74
 
75
+ end
76
+
77
+
78
+ if defined?(MOD_RUBY)
79
+
55
80
  class ::Apache::RubyRun # :nodoc:
56
81
  ## if 'alias _handler_orig handler' statement is evaluated
57
82
  ## more than twice, handler() will cause stack over flow.
@@ -59,13 +84,15 @@ if defined?(MOD_RUBY)
59
84
  alias _handler_orig handler
60
85
  end
61
86
  ## override handler() to catch and exception it to browser
62
- def handler(r)
63
- return _handler_orig(r)
87
+ def handler(request)
88
+ return _handler_orig(request)
64
89
  rescue Exception => ex
65
- _print_http_header()
66
- _print_exception(ex)
90
+ #Apache.request.set_cgi_env unless ENV.key?("GATEWAY_INTERFACE")
91
+ ModRubyExceptionPrinter.new().handle(ex)
92
+ if defined?(EditorKicker)
93
+ EditorKicker.handle(ex) #if ENV['EDITOR_KICKER']
94
+ end
67
95
  #raise ex
68
- $stderr.write "#{ex.backtrace[0]}: #{ex.message} (#{ex.class.name})\n"
69
96
  return ::Apache::OK
70
97
  end
71
98
  ## original
@@ -80,9 +107,7 @@ if defined?(MOD_RUBY)
80
107
 
81
108
  else
82
109
 
83
- def _print_http_header() # don't use alias
84
- _print_http_header_for_cgi()
85
- end
110
+ $_header_printed = false
86
111
 
87
112
  ## override $stdout.write() to detect whether HTTP header printed or not
88
113
  class << $stdout
@@ -92,13 +117,14 @@ else
92
117
  end
93
118
  end
94
119
 
95
- $_header_printed = false
96
-
97
120
  ## when process exit, print exception if exception raised
98
121
  at_exit do
99
122
  if $!
100
- _print_http_header() unless $_header_printed
101
- _print_exception($!)
123
+ ex = $!
124
+ CGIExceptionPrinter.new($_header_printed).handle(ex)
125
+ if defined?(EditorKicker)
126
+ EditorKicker.handle(ex) #if ENV['EDITOR_KICKER']
127
+ end
102
128
  end
103
129
  end
104
130
 
@@ -1,6 +1,6 @@
1
1
  ###
2
2
  ### $Rev: 7 $
3
- ### $Release: 0.2.0 $
3
+ ### $Release: 0.3.0 $
4
4
  ### copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
5
5
  ###
6
6
 
@@ -43,7 +43,7 @@ END
43
43
  @expected = <<END
44
44
  Status: 500 Internal Error\r
45
45
  Content-Type: text/html\r
46
- X-CGI-Exception: 0.2.0\r
46
+ X-CGI-Exception: 0.3.0\r
47
47
  \r
48
48
  <pre style="color:#CC0000"><b>when_no_header_printed.rb:3:in `build_html': undefined local variable or method `name' for main:Object (NameError)</b>
49
49
  from when_no_header_printed.rb:5
@@ -99,7 +99,7 @@ END
99
99
  @expected = <<END
100
100
  Status: 500 Internal Error\r
101
101
  Content-Type: text/html\r
102
- X-CGI-Exception: 0.2.0\r
102
+ X-CGI-Exception: 0.3.0\r
103
103
  \r
104
104
  <pre style="color:#CC0000"><b>when_error_backtrace_is_too_long.rb:6:in `f': stack level too deep (SystemStackError)</b>
105
105
  from when_error_backtrace_is_too_long.rb:9:in `g'
@@ -129,7 +129,7 @@ END
129
129
  @expected2 = <<END
130
130
  Status: 500 Internal Error\r
131
131
  Content-Type: text/html\r
132
- X-CGI-Exception: 0.2.0\r
132
+ X-CGI-Exception: 0.3.0\r
133
133
  \r
134
134
  <pre style="color:#CC0000"><b>when_error_backtrace_is_too_long.rb:9:in `g': stack level too deep (SystemStackError)</b>
135
135
  from when_error_backtrace_is_too_long.rb:6:in `f'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cgi-exception
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - makoto kuwata
@@ -9,12 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-22 00:00:00 +09:00
12
+ date: 2008-07-19 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description: cgi-exception.rb is a tiny utility to display what and at where exception raised in CGI script just like PHP. You don't need to look for error message in web server's log file.
17
- email: kwa@kuwata-lab.com
17
+ email: kwa(at)kuwata-lab.com
18
18
  executables: []
19
19
 
20
20
  extensions: []
@@ -27,6 +27,7 @@ files:
27
27
  - README.txt
28
28
  - CHANGES.txt
29
29
  - setup.rb
30
+ - cgi-exception.gemspec
30
31
  has_rdoc: false
31
32
  homepage: http://cgi-exception.rubyforge.org/
32
33
  post_install_message:
@@ -49,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
50
  requirements: []
50
51
 
51
52
  rubyforge_project: cgi-exception
52
- rubygems_version: 1.0.1
53
+ rubygems_version: 1.2.0
53
54
  signing_key:
54
55
  specification_version: 2
55
56
  summary: Utility to display what and at where exception raised in CGI script