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 +19 -0
- data/README.txt +17 -8
- data/lib/cgi_exception.rb +92 -12
- data/test/test_cgi_exception.rb +163 -0
- metadata +42 -33
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.
|
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
|
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 = "<
|
41
|
-
print
|
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
|
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
|
67
|
+
makoto kuwata <kwa.at.kuwata-lab.com>
|
data/lib/cgi_exception.rb
CHANGED
@@ -1,25 +1,105 @@
|
|
1
1
|
##
|
2
|
-
## $Rev:
|
3
|
-
## $Release: 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(/&/,'&').gsub(/</,'<').gsub(/>/,'>').gsub(/"/,'"')
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
out << header << "\r\n" if header
|
13
|
+
## print exception in HTML format
|
14
|
+
def _print_exception(ex)
|
15
15
|
arr = ex.backtrace
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
23
|
-
|
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.
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
- setup.rb
|
35
|
-
test_files: []
|
36
|
-
|
37
|
-
rdoc_options: []
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
38
11
|
|
39
|
-
|
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
|
-
|
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
|
|