Skip to content

Commit c0b925e

Browse files
committed
back-port Rack::ShowStatus to be used with out ErrorApp (contains XSS fix see #190)
more details at rack/rack@479fe8fecad0b33b88e6a9de01
1 parent 40a4985 commit c0b925e

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
require 'erb'
2+
require 'rack/request'
3+
require 'rack/utils'
4+
5+
class JRuby::Rack::ErrorApp
6+
# Rack::ShowStatus catches all empty responses and replaces them
7+
# with a site explaining the error.
8+
#
9+
# Additional details can be put into <tt>rack.showstatus.detail</tt>
10+
# and will be shown as HTML. If such details exist, the error page
11+
# is always rendered, even if the reply was not empty.
12+
13+
class ShowStatus
14+
def initialize(app)
15+
@app = app
16+
@template = ERB.new(TEMPLATE)
17+
end
18+
19+
def call(env)
20+
status, headers, body = @app.call(env)
21+
headers = Utils::HeaderHash.new(headers)
22+
empty = headers[CONTENT_LENGTH].to_i <= 0
23+
24+
# client or server error, or explicit message
25+
if (status.to_i >= 400 && empty) || env["rack.showstatus.detail"]
26+
# This double assignment is to prevent an "unused variable" warning on
27+
# Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
28+
req = req = Rack::Request.new(env)
29+
30+
message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s
31+
32+
# This double assignment is to prevent an "unused variable" warning on
33+
# Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
34+
detail = detail = env["rack.showstatus.detail"] || message
35+
36+
body = @template.result(binding)
37+
size = Rack::Utils.bytesize(body)
38+
[status, headers.merge(CONTENT_TYPE => "text/html", CONTENT_LENGTH => size.to_s), [body]]
39+
else
40+
[status, headers, body]
41+
end
42+
end
43+
44+
def h(obj) # :nodoc:
45+
case obj
46+
when String
47+
Utils.escape_html(obj)
48+
else
49+
Utils.escape_html(obj.inspect)
50+
end
51+
end
52+
53+
# :stopdoc:
54+
55+
# adapted from Django <djangoproject.com>
56+
# Copyright (c) 2005, the Lawrence Journal-World
57+
# Used under the modified BSD license:
58+
# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
59+
TEMPLATE = <<'HTML'
60+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
61+
<html lang="en">
62+
<head>
63+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
64+
<title><%=h message %> at <%=h req.script_name + req.path_info %></title>
65+
<meta name="robots" content="NONE,NOARCHIVE" />
66+
<style type="text/css">
67+
html * { padding:0; margin:0; }
68+
body * { padding:10px 20px; }
69+
body * * { padding:0; }
70+
body { font:small sans-serif; background:#eee; }
71+
body>div { border-bottom:1px solid #ddd; }
72+
h1 { font-weight:normal; margin-bottom:.4em; }
73+
h1 span { font-size:60%; color:#666; font-weight:normal; }
74+
table { border:none; border-collapse: collapse; width:100%; }
75+
td, th { vertical-align:top; padding:2px 3px; }
76+
th { width:12em; text-align:right; color:#666; padding-right:.5em; }
77+
#info { background:#f6f6f6; }
78+
#info ol { margin: 0.5em 4em; }
79+
#info ol li { font-family: monospace; }
80+
#summary { background: #ffc; }
81+
#explanation { background:#eee; border-bottom: 0px none; }
82+
</style>
83+
</head>
84+
<body>
85+
<div id="summary">
86+
<h1><%=h message %> <span>(<%= status.to_i %>)</span></h1>
87+
<table class="meta">
88+
<tr>
89+
<th>Request Method:</th>
90+
<td><%=h req.request_method %></td>
91+
</tr>
92+
<tr>
93+
<th>Request URL:</th>
94+
<td><%=h req.url %></td>
95+
</tr>
96+
</table>
97+
</div>
98+
<div id="info">
99+
<p><%=h detail %></p>
100+
</div>
101+
102+
<div id="explanation">
103+
<p>
104+
You're seeing this error because you use <code>Rack::ShowStatus</code>.
105+
</p>
106+
</div>
107+
</body>
108+
</html>
109+
HTML
110+
111+
# :startdoc:
112+
end
113+
end

0 commit comments

Comments
 (0)