cgi-exception 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt ADDED
@@ -0,0 +1,19 @@
1
+ = CHANGES
2
+
3
+
4
+
5
+ == Release 0.2.0 (2008-02-21)
6
+
7
+ === Enhancements
8
+
9
+ * mod_ruby support
10
+
11
+ * detect whether HTTP header printed or not
12
+
13
+ * omit lines when Exception backtrace is too long
14
+
15
+
16
+
17
+ == Release 0.1.0
18
+
19
+ * first public release
data/README.txt CHANGED
@@ -1,16 +1,21 @@
1
1
  = README.txt
2
2
 
3
- Release: 0.1.0
3
+ Release: 0.2.0
4
4
 
5
- copyright(c) 2007 kuwata-lab.com all rights reserved.
5
+ copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
6
+
7
+ http://rubyforge.org/projects/cgi-exception/
6
8
 
7
9
 
8
10
  == About
9
11
 
10
- 'cgi_exception.rb' is a tiny script to show exception raised in your
12
+ 'cgi_exception.rb' is a small script to show exception raised in your
11
13
  CGI script into browser, like PHP. You don't need to look for error
12
14
  messages in Web server's log file.
13
15
 
16
+ NOTICE: cig_exception.rb works only with CGI or mod_ruby. It doesn't
17
+ support FastCGI.
18
+
14
19
 
15
20
  == Install
16
21
 
@@ -19,7 +24,11 @@ with administrator priviledge.
19
24
 
20
25
  Or, just type 'ruby setup.rb' with administrator priviledge.
21
26
 
22
- Or, copy 'lib/cgi_exception.rb' to proper directory.
27
+ Or, copy 'lib/cgi_exception.rb' to proper directory such as
28
+ '/usr/local/lib/ruby/site_ruby/1.8'.
29
+
30
+ NOTICE: It is NOT recommended to install by RubyGems, because
31
+ 'require "rubygems"' is too heavy for CGI program.
23
32
 
24
33
 
25
34
  == Usage
@@ -37,11 +46,11 @@ local variable 'user' is not initialized.
37
46
  #!/usr/bin/env ruby
38
47
  require 'cgi'
39
48
  require 'cgi_exception'
40
- html = "<pp>Hello #{user}!</p>\n"
41
- print cgi.header
49
+ html = "<p>Hello #{user}!</p>\n"
50
+ print CGI.new.header
42
51
  print html
43
52
 
44
- You'll see the following message in your browser if you access the abobe
53
+ You'll see the following message in your browser if you access the above
45
54
  CGI script.
46
55
 
47
56
  /var/www/cgi-bin/foo.cgi:4: undefined local variable or method `user'
@@ -55,4 +64,4 @@ public domain
55
64
 
56
65
  == Author
57
66
 
58
- makoto kuwata <kwa(at)kuwata-lab.com>
67
+ makoto kuwata <kwa.at.kuwata-lab.com>
data/lib/cgi_exception.rb CHANGED
@@ -1,25 +1,105 @@
1
1
  ##
2
- ## $Rev: 1 $
3
- ## $Release: 0.1.0 $
4
- ## copyright(c) 2007 kuwata-lab.com all rights reserved.
2
+ ## $Rev: 7 $
3
+ ## $Release: 0.2.0 $
4
+ ## copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
5
5
  ## License: public domain
6
6
  ##
7
7
 
8
+ ## escape HTML characters
8
9
  def _esc_html(s)
9
10
  s.to_s.gsub(/&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;').gsub(/"/,'&quot;')
10
11
  end
11
12
 
12
- def _print_stack_trace(ex, out=$stderr, header="Content-Type: text/html\r\n")
13
- out ||= $stderr
14
- out << header << "\r\n" if header
13
+ ## print exception in HTML format
14
+ def _print_exception(ex)
15
15
  arr = ex.backtrace
16
- out << "<pre style=\"color:#CC0000\">"
17
- out << "<b>#{_esc_html arr[0]}: #{_esc_html ex.message} (#{ex.class.name})</b>\n"
18
- arr[1..-1].each {|s| out << " from #{_esc_html s}\n" }
19
- out << "</pre>"
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)
27
+ end
28
+ print "</pre>"
20
29
  end
21
30
 
22
- at_exit do
23
- _print_stack_trace($!, $stdout) if $!
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"
24
37
  end
25
38
 
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
+ end
48
+
49
+ if defined?(MOD_RUBY)
50
+
51
+ def _print_http_header() # don't use alias
52
+ _print_http_header_for_modruby()
53
+ end
54
+
55
+ class ::Apache::RubyRun # :nodoc:
56
+ ## if 'alias _handler_orig handler' statement is evaluated
57
+ ## more than twice, handler() will cause stack over flow.
58
+ unless self.method_defined?(:_handler_orig)
59
+ alias _handler_orig handler
60
+ end
61
+ ## override handler() to catch and exception it to browser
62
+ def handler(r)
63
+ return _handler_orig(r)
64
+ rescue Exception => ex
65
+ _print_http_header()
66
+ _print_exception(ex)
67
+ #raise ex
68
+ $stderr.write "#{ex.backtrace[0]}: #{ex.message} (#{ex.class.name})\n"
69
+ return ::Apache::OK
70
+ end
71
+ ## original
72
+ #def handler(r)
73
+ # status = check_request(r)
74
+ # return status if status != OK
75
+ # filename = setup(r)
76
+ # load(filename, true)
77
+ # return OK
78
+ #end
79
+ end
80
+
81
+ else
82
+
83
+ def _print_http_header() # don't use alias
84
+ _print_http_header_for_cgi()
85
+ end
86
+
87
+ ## override $stdout.write() to detect whether HTTP header printed or not
88
+ class << $stdout
89
+ def write(*args)
90
+ $_header_printed = true
91
+ super(*args)
92
+ end
93
+ end
94
+
95
+ $_header_printed = false
96
+
97
+ ## when process exit, print exception if exception raised
98
+ at_exit do
99
+ if $!
100
+ _print_http_header() unless $_header_printed
101
+ _print_exception($!)
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,163 @@
1
+ ###
2
+ ### $Rev: 7 $
3
+ ### $Release: 0.2.0 $
4
+ ### copyright(c) 2007-2008 kuwata-lab.com all rights reserved.
5
+ ###
6
+
7
+ require 'test/unit'
8
+ LIBDIR = File.dirname(__FILE__) + '/../lib'
9
+
10
+
11
+ class CGIExceptionTest < Test::Unit::TestCase
12
+
13
+
14
+ def _test
15
+ @name = (name() =~ /^test_(.*)\(.*\)$/) && $1
16
+ filename = (@filename ||= "#{@name}.rb")
17
+ begin
18
+ #preamble = "$: << #{LIBDIR.inspect}\n"
19
+ #File.open(filename, 'w') {|f| f << preamble << @script }
20
+ #output = `ruby #{filename} 2>/dev/null`
21
+ File.open(filename, 'w') {|f| f << @script }
22
+ command = "ruby -I #{LIBDIR} #{filename} 2>/dev/null"
23
+ output = `#{command}`
24
+ expected = @expected
25
+ expected = @expected2 if @expected2 && @expected2 == output
26
+ assert_equal(expected, output)
27
+ ensure
28
+ File.unlink(filename) if File.exist?(filename) unless $DEBUG
29
+ end
30
+ end
31
+
32
+
33
+ def test_when_no_header_printed
34
+ @script = <<'END'
35
+ require 'cgi_exception'
36
+ def build_html
37
+ return "<p>Hello #{name}</p>"
38
+ end
39
+ html = build_html
40
+ print "Content-Type: text/html\r\n"
41
+ print html
42
+ END
43
+ @expected = <<END
44
+ Status: 500 Internal Error\r
45
+ Content-Type: text/html\r
46
+ X-CGI-Exception: 0.2.0\r
47
+ \r
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
+ from when_no_header_printed.rb:5
50
+ </pre>
51
+ END
52
+ @expected.chomp!
53
+ _test
54
+ end
55
+
56
+
57
+ def test_when_header_already_printed
58
+ @script = <<'END'
59
+ require 'cgi_exception'
60
+ def build_html
61
+ return "<p>Hello #{name}</p>"
62
+ end
63
+ print "Content-Type: text/html\r\n"
64
+ print "\r\n"
65
+ print "<html>\n"
66
+ print build_html
67
+ print "</html>\n"
68
+ END
69
+ @expected = <<END
70
+ Content-Type: text/html\r
71
+ \r
72
+ <html>
73
+ <pre style="color:#CC0000"><b>when_header_already_printed.rb:3:in `build_html': undefined local variable or method `name' for main:Object (NameError)</b>
74
+ from when_header_already_printed.rb:8
75
+ </pre>
76
+ END
77
+ @expected.chomp!
78
+ _test
79
+ end
80
+
81
+
82
+ def test_when_error_backtrace_is_too_long
83
+ @script = <<'END'
84
+ require 'cgi_exception'
85
+ def build_html
86
+ return f(100).to_s
87
+ end
88
+ def f(n)
89
+ return n + g(n-1)
90
+ end
91
+ def g(n)
92
+ return n + f(n-1)
93
+ end
94
+ html = build_html()
95
+ print "Content-Type: text/html\r\n"
96
+ print "\r\n"
97
+ print html
98
+ END
99
+ @expected = <<END
100
+ Status: 500 Internal Error\r
101
+ Content-Type: text/html\r
102
+ X-CGI-Exception: 0.2.0\r
103
+ \r
104
+ <pre style="color:#CC0000"><b>when_error_backtrace_is_too_long.rb:6:in `f': stack level too deep (SystemStackError)</b>
105
+ from when_error_backtrace_is_too_long.rb:9:in `g'
106
+ from when_error_backtrace_is_too_long.rb:6:in `f'
107
+ from when_error_backtrace_is_too_long.rb:9:in `g'
108
+ from when_error_backtrace_is_too_long.rb:6:in `f'
109
+ from when_error_backtrace_is_too_long.rb:9:in `g'
110
+ from when_error_backtrace_is_too_long.rb:6:in `f'
111
+ from when_error_backtrace_is_too_long.rb:9:in `g'
112
+ from when_error_backtrace_is_too_long.rb:6:in `f'
113
+ from when_error_backtrace_is_too_long.rb:9:in `g'
114
+ from when_error_backtrace_is_too_long.rb:6:in `f'
115
+ from when_error_backtrace_is_too_long.rb:9:in `g'
116
+ from when_error_backtrace_is_too_long.rb:6:in `f'
117
+ from when_error_backtrace_is_too_long.rb:9:in `g'
118
+ from when_error_backtrace_is_too_long.rb:6:in `f'
119
+ from when_error_backtrace_is_too_long.rb:9:in `g'
120
+ ...
121
+ from when_error_backtrace_is_too_long.rb:6:in `f'
122
+ from when_error_backtrace_is_too_long.rb:9:in `g'
123
+ from when_error_backtrace_is_too_long.rb:6:in `f'
124
+ from when_error_backtrace_is_too_long.rb:3:in `build_html'
125
+ from when_error_backtrace_is_too_long.rb:11
126
+ </pre>
127
+ END
128
+ @expected.chomp!
129
+ @expected2 = <<END
130
+ Status: 500 Internal Error\r
131
+ Content-Type: text/html\r
132
+ X-CGI-Exception: 0.2.0\r
133
+ \r
134
+ <pre style="color:#CC0000"><b>when_error_backtrace_is_too_long.rb:9:in `g': stack level too deep (SystemStackError)</b>
135
+ from when_error_backtrace_is_too_long.rb:6:in `f'
136
+ from when_error_backtrace_is_too_long.rb:9:in `g'
137
+ from when_error_backtrace_is_too_long.rb:6:in `f'
138
+ from when_error_backtrace_is_too_long.rb:9:in `g'
139
+ from when_error_backtrace_is_too_long.rb:6:in `f'
140
+ from when_error_backtrace_is_too_long.rb:9:in `g'
141
+ from when_error_backtrace_is_too_long.rb:6:in `f'
142
+ from when_error_backtrace_is_too_long.rb:9:in `g'
143
+ from when_error_backtrace_is_too_long.rb:6:in `f'
144
+ from when_error_backtrace_is_too_long.rb:9:in `g'
145
+ from when_error_backtrace_is_too_long.rb:6:in `f'
146
+ from when_error_backtrace_is_too_long.rb:9:in `g'
147
+ from when_error_backtrace_is_too_long.rb:6:in `f'
148
+ from when_error_backtrace_is_too_long.rb:9:in `g'
149
+ from when_error_backtrace_is_too_long.rb:6:in `f'
150
+ ...
151
+ from when_error_backtrace_is_too_long.rb:6:in `f'
152
+ from when_error_backtrace_is_too_long.rb:9:in `g'
153
+ from when_error_backtrace_is_too_long.rb:6:in `f'
154
+ from when_error_backtrace_is_too_long.rb:3:in `build_html'
155
+ from when_error_backtrace_is_too_long.rb:11
156
+ </pre>
157
+ END
158
+ @expected2.chomp!
159
+ _test
160
+ end
161
+
162
+
163
+ end
metadata CHANGED
@@ -1,48 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
3
- specification_version: 1
4
2
  name: cgi-exception
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2007-12-24 00:00:00 +09:00
8
- summary: Utility to display what and where exception raised in CGI script
9
- require_paths:
10
- - lib
11
- email:
12
- homepage: http://cgi-exception.rubyforge.org/
13
- rubyforge_project:
14
- description: cgi-exception.rb is a tiny utility to display what and where exception raised in CGI script just like PHP. You don't need to look for error message in web server's log file.
15
- autorequire:
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: false
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 0.2.0
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - makoto kuwata
31
- files:
32
- - lib/cgi_exception.rb
33
- - README.txt
34
- - setup.rb
35
- test_files: []
36
-
37
- rdoc_options: []
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
38
11
 
39
- extra_rdoc_files: []
12
+ date: 2008-02-22 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
40
15
 
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
41
18
  executables: []
42
19
 
43
20
  extensions: []
44
21
 
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/cgi_exception.rb
26
+ - test/test_cgi_exception.rb
27
+ - README.txt
28
+ - CHANGES.txt
29
+ - setup.rb
30
+ has_rdoc: false
31
+ homepage: http://cgi-exception.rubyforge.org/
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
45
49
  requirements: []
46
50
 
47
- dependencies: []
51
+ rubyforge_project: cgi-exception
52
+ rubygems_version: 1.0.1
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Utility to display what and at where exception raised in CGI script
56
+ test_files: []
48
57