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.
- data/CHANGES.txt +12 -0
- data/README.txt +55 -16
- data/cgi-exception.gemspec +46 -0
- data/lib/cgi_exception.rb +78 -52
- data/test/test_cgi_exception.rb +4 -4
- metadata +5 -4
data/CHANGES.txt
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
17
|
-
|
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
|
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
|
-
|
50
|
-
print CGI.new.header
|
51
|
-
print
|
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:
|
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
|
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
|
data/lib/cgi_exception.rb
CHANGED
@@ -1,57 +1,82 @@
|
|
1
1
|
##
|
2
|
-
## $Rev:
|
3
|
-
## $Release: 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
|
-
|
9
|
-
def _esc_html(s)
|
10
|
-
s.to_s.gsub(/&/,'&').gsub(/</,'<').gsub(/>/,'>').gsub(/"/,'"')
|
11
|
-
end
|
8
|
+
class CGIExceptionPrinter
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
15
|
+
attr_accessor :skip_header, :out
|
16
|
+
|
17
|
+
## escape HTML characters
|
18
|
+
def escape_html(s)
|
19
|
+
s.to_s.gsub(/&/,'&').gsub(/</,'<').gsub(/>/,'>').gsub(/"/,'"')
|
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
|
-
|
52
|
-
|
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(
|
63
|
-
return _handler_orig(
|
87
|
+
def handler(request)
|
88
|
+
return _handler_orig(request)
|
64
89
|
rescue Exception => ex
|
65
|
-
|
66
|
-
|
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
|
-
|
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
|
-
|
101
|
-
|
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
|
|
data/test/test_cgi_exception.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
###
|
2
2
|
### $Rev: 7 $
|
3
|
-
### $Release: 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.
|
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.
|
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.
|
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.
|
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-
|
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
|
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
|
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
|