aldebaran 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +13 -0
- data/.travis.yml +16 -0
- data/.yardopts +4 -0
- data/AUTHORS +4 -0
- data/Gemfile +77 -0
- data/KNOWN_ISSUES +5 -0
- data/LICENSE +22 -0
- data/README.rdoc +1900 -0
- data/Rakefile +175 -0
- data/aldebaran.gemspec +19 -0
- data/lib/aldebaran.rb +7 -0
- data/lib/aldebaran/base.rb +1600 -0
- data/lib/aldebaran/images/404.png +0 -0
- data/lib/aldebaran/images/500.png +0 -0
- data/lib/aldebaran/main.rb +28 -0
- data/lib/aldebaran/showexceptions.rb +340 -0
- data/lib/aldebaran/version.rb +3 -0
- data/test/aldebaran_test.rb +17 -0
- data/test/base_test.rb +160 -0
- data/test/builder_test.rb +95 -0
- data/test/coffee_test.rb +92 -0
- data/test/contest.rb +98 -0
- data/test/creole_test.rb +65 -0
- data/test/delegator_test.rb +162 -0
- data/test/encoding_test.rb +20 -0
- data/test/erb_test.rb +104 -0
- data/test/extensions_test.rb +100 -0
- data/test/filter_test.rb +397 -0
- data/test/haml_test.rb +101 -0
- data/test/helper.rb +115 -0
- data/test/helpers_test.rb +1192 -0
- data/test/less_test.rb +67 -0
- data/test/liquid_test.rb +59 -0
- data/test/mapped_error_test.rb +259 -0
- data/test/markaby_test.rb +80 -0
- data/test/markdown_test.rb +81 -0
- data/test/middleware_test.rb +68 -0
- data/test/nokogiri_test.rb +69 -0
- data/test/public/favicon.ico +0 -0
- data/test/radius_test.rb +59 -0
- data/test/rdoc_test.rb +65 -0
- data/test/readme_test.rb +136 -0
- data/test/request_test.rb +45 -0
- data/test/response_test.rb +61 -0
- data/test/result_test.rb +98 -0
- data/test/route_added_hook_test.rb +59 -0
- data/test/routing_test.rb +1096 -0
- data/test/sass_test.rb +115 -0
- data/test/scss_test.rb +88 -0
- data/test/server_test.rb +48 -0
- data/test/settings_test.rb +493 -0
- data/test/slim_test.rb +98 -0
- data/test/static_test.rb +178 -0
- data/test/streaming_test.rb +100 -0
- data/test/templates_test.rb +298 -0
- data/test/textile_test.rb +65 -0
- data/test/views/a/in_a.str +1 -0
- data/test/views/ascii.erb +2 -0
- data/test/views/b/in_b.str +1 -0
- data/test/views/calc.html.erb +1 -0
- data/test/views/error.builder +3 -0
- data/test/views/error.erb +3 -0
- data/test/views/error.haml +3 -0
- data/test/views/error.sass +2 -0
- data/test/views/explicitly_nested.str +1 -0
- data/test/views/foo/hello.test +1 -0
- data/test/views/hello.builder +1 -0
- data/test/views/hello.coffee +1 -0
- data/test/views/hello.creole +1 -0
- data/test/views/hello.erb +1 -0
- data/test/views/hello.haml +1 -0
- data/test/views/hello.less +5 -0
- data/test/views/hello.liquid +1 -0
- data/test/views/hello.mab +1 -0
- data/test/views/hello.md +1 -0
- data/test/views/hello.nokogiri +1 -0
- data/test/views/hello.radius +1 -0
- data/test/views/hello.rdoc +1 -0
- data/test/views/hello.sass +2 -0
- data/test/views/hello.scss +3 -0
- data/test/views/hello.slim +1 -0
- data/test/views/hello.str +1 -0
- data/test/views/hello.test +1 -0
- data/test/views/hello.textile +1 -0
- data/test/views/layout2.builder +3 -0
- data/test/views/layout2.erb +2 -0
- data/test/views/layout2.haml +2 -0
- data/test/views/layout2.liquid +2 -0
- data/test/views/layout2.mab +2 -0
- data/test/views/layout2.nokogiri +3 -0
- data/test/views/layout2.radius +2 -0
- data/test/views/layout2.slim +3 -0
- data/test/views/layout2.str +2 -0
- data/test/views/layout2.test +1 -0
- data/test/views/nested.str +1 -0
- data/test/views/utf8.erb +2 -0
- metadata +231 -0
Binary file
|
Binary file
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'aldebaran/base'
|
2
|
+
|
3
|
+
module Aldebaran
|
4
|
+
class Application < Base
|
5
|
+
|
6
|
+
# we assume that the first file that requires 'aldebaran' is the
|
7
|
+
# app_file. all other path related options are calculated based
|
8
|
+
# on this path by default.
|
9
|
+
set :app_file, caller_files.first || $0
|
10
|
+
|
11
|
+
set :run, Proc.new { $0 == app_file }
|
12
|
+
|
13
|
+
if run? && ARGV.any?
|
14
|
+
require 'optparse'
|
15
|
+
OptionParser.new { |op|
|
16
|
+
op.on('-x') { set :lock, true }
|
17
|
+
op.on('-e env') { |val| set :environment, val.to_sym }
|
18
|
+
op.on('-s server') { |val| set :server, val }
|
19
|
+
op.on('-p port') { |val| set :port, Integer(val) }
|
20
|
+
op.on('-o addr') { |val| set :bind, val }
|
21
|
+
}.parse!(ARGV.dup)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
at_exit { Application.run! if $!.nil? && Application.run? }
|
26
|
+
end
|
27
|
+
|
28
|
+
include Aldebaran::Delegator
|
@@ -0,0 +1,340 @@
|
|
1
|
+
require 'rack/showexceptions'
|
2
|
+
|
3
|
+
module Aldebaran
|
4
|
+
# Aldebaran::ShowExceptions catches all exceptions raised from the app it
|
5
|
+
# wraps. It shows a useful backtrace with the sourcefile and clickable
|
6
|
+
# context, the whole Rack environment and the request data.
|
7
|
+
#
|
8
|
+
# Be careful when you use this on public-facing sites as it could reveal
|
9
|
+
# information helpful to attackers.
|
10
|
+
class ShowExceptions < Rack::ShowExceptions
|
11
|
+
@@eats_errors = Object.new
|
12
|
+
def @@eats_errors.flush(*) end
|
13
|
+
def @@eats_errors.puts(*) end
|
14
|
+
|
15
|
+
def initialize(app)
|
16
|
+
@app = app
|
17
|
+
@template = ERB.new(TEMPLATE)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
@app.call(env)
|
22
|
+
rescue Exception => e
|
23
|
+
errors, env["rack.errors"] = env["rack.errors"], @@eats_errors
|
24
|
+
|
25
|
+
if respond_to?(:prefers_plain_text?) and prefers_plain_text?(env)
|
26
|
+
content_type = "text/plain"
|
27
|
+
body = [dump_exception(e)]
|
28
|
+
else
|
29
|
+
content_type = "text/html"
|
30
|
+
body = pretty(env, e)
|
31
|
+
end
|
32
|
+
|
33
|
+
env["rack.errors"] = errors
|
34
|
+
|
35
|
+
[500,
|
36
|
+
{"Content-Type" => content_type,
|
37
|
+
"Content-Length" => Rack::Utils.bytesize(body.join).to_s},
|
38
|
+
body]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def frame_class(frame)
|
44
|
+
if frame.filename =~ /lib\/aldebaran.*\.rb/
|
45
|
+
"framework"
|
46
|
+
elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
|
47
|
+
frame.filename =~ /\/bin\/(\w+)$/
|
48
|
+
"system"
|
49
|
+
else
|
50
|
+
"app"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
TEMPLATE = <<-HTML # :nodoc:
|
55
|
+
<!DOCTYPE html>
|
56
|
+
<html>
|
57
|
+
<head>
|
58
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
59
|
+
<title><%=h exception.class %> at <%=h path %></title>
|
60
|
+
|
61
|
+
<script type="text/javascript">
|
62
|
+
//<!--
|
63
|
+
function toggle(id) {
|
64
|
+
var pre = document.getElementById("pre-" + id);
|
65
|
+
var post = document.getElementById("post-" + id);
|
66
|
+
var context = document.getElementById("context-" + id);
|
67
|
+
|
68
|
+
if (pre.style.display == 'block') {
|
69
|
+
pre.style.display = 'none';
|
70
|
+
post.style.display = 'none';
|
71
|
+
context.style.background = "none";
|
72
|
+
} else {
|
73
|
+
pre.style.display = 'block';
|
74
|
+
post.style.display = 'block';
|
75
|
+
context.style.background = "#fffed9";
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
function toggleBacktrace(){
|
80
|
+
var bt = document.getElementById("backtrace");
|
81
|
+
var toggler = document.getElementById("expando");
|
82
|
+
|
83
|
+
if (bt.className == 'condensed') {
|
84
|
+
bt.className = 'expanded';
|
85
|
+
toggler.innerHTML = "(condense)";
|
86
|
+
} else {
|
87
|
+
bt.className = 'condensed';
|
88
|
+
toggler.innerHTML = "(expand)";
|
89
|
+
}
|
90
|
+
}
|
91
|
+
//-->
|
92
|
+
</script>
|
93
|
+
|
94
|
+
<style type="text/css" media="screen">
|
95
|
+
* {margin: 0; padding: 0; border: 0; outline: 0;}
|
96
|
+
div.clear {clear: both;}
|
97
|
+
body {background: #EEEEEE; margin: 0; padding: 0;
|
98
|
+
font-family: 'Lucida Grande', 'Lucida Sans Unicode',
|
99
|
+
'Garuda';}
|
100
|
+
code {font-family: 'Lucida Console', monospace;
|
101
|
+
font-size: 12px;}
|
102
|
+
li {height: 18px;}
|
103
|
+
ul {list-style: none; margin: 0; padding: 0;}
|
104
|
+
ol:hover {cursor: pointer;}
|
105
|
+
ol li {white-space: pre;}
|
106
|
+
#explanation {font-size: 12px; color: #666666;
|
107
|
+
margin: 20px 0 0 100px;}
|
108
|
+
/* WRAP */
|
109
|
+
#wrap {width: 1000px; background: #FFFFFF; margin: 0 auto;
|
110
|
+
padding: 30px 50px 20px 50px;
|
111
|
+
border-left: 1px solid #DDDDDD;
|
112
|
+
border-right: 1px solid #DDDDDD;}
|
113
|
+
/* HEADER */
|
114
|
+
#header {margin: 0 auto 25px auto;}
|
115
|
+
#header img {float: left;}
|
116
|
+
#header #summary {float: left; margin: 12px 0 0 20px; width:660px;
|
117
|
+
font-family: 'Lucida Grande', 'Lucida Sans Unicode';}
|
118
|
+
h1 {margin: 0; font-size: 36px; color: #981919;}
|
119
|
+
h2 {margin: 0; font-size: 22px; color: #333333;}
|
120
|
+
#header ul {margin: 0; font-size: 12px; color: #666666;}
|
121
|
+
#header ul li strong{color: #444444;}
|
122
|
+
#header ul li {display: inline; padding: 0 10px;}
|
123
|
+
#header ul li.first {padding-left: 0;}
|
124
|
+
#header ul li.last {border: 0; padding-right: 0;}
|
125
|
+
/* BODY */
|
126
|
+
#backtrace,
|
127
|
+
#get,
|
128
|
+
#post,
|
129
|
+
#cookies,
|
130
|
+
#rack {width: 980px; margin: 0 auto 10px auto;}
|
131
|
+
p#nav {float: right; font-size: 14px;}
|
132
|
+
/* BACKTRACE */
|
133
|
+
a#expando {float: left; padding-left: 5px; color: #666666;
|
134
|
+
font-size: 14px; text-decoration: none; cursor: pointer;}
|
135
|
+
a#expando:hover {text-decoration: underline;}
|
136
|
+
h3 {float: left; width: 100px; margin-bottom: 10px;
|
137
|
+
color: #981919; font-size: 14px; font-weight: bold;}
|
138
|
+
#nav a {color: #666666; text-decoration: none; padding: 0 5px;}
|
139
|
+
#backtrace li.frame-info {background: #f7f7f7; padding-left: 10px;
|
140
|
+
font-size: 12px; color: #333333;}
|
141
|
+
#backtrace ul {list-style-position: outside; border: 1px solid #E9E9E9;
|
142
|
+
border-bottom: 0;}
|
143
|
+
#backtrace ol {width: 920px; margin-left: 50px;
|
144
|
+
font: 10px 'Lucida Console', monospace; color: #666666;}
|
145
|
+
#backtrace ol li {border: 0; border-left: 1px solid #E9E9E9;
|
146
|
+
padding: 2px 0;}
|
147
|
+
#backtrace ol code {font-size: 10px; color: #555555; padding-left: 5px;}
|
148
|
+
#backtrace-ul li {border-bottom: 1px solid #E9E9E9; height: auto;
|
149
|
+
padding: 3px 0;}
|
150
|
+
#backtrace-ul .code {padding: 6px 0 4px 0;}
|
151
|
+
#backtrace.condensed .system,
|
152
|
+
#backtrace.condensed .framework {display:none;}
|
153
|
+
/* REQUEST DATA */
|
154
|
+
p.no-data {padding-top: 2px; font-size: 12px; color: #666666;}
|
155
|
+
table.req {width: 980px; text-align: left; font-size: 12px;
|
156
|
+
color: #666666; padding: 0; border-spacing: 0;
|
157
|
+
border: 1px solid #EEEEEE; border-bottom: 0;
|
158
|
+
border-left: 0;
|
159
|
+
clear:both}
|
160
|
+
table.req tr th {padding: 2px 10px; font-weight: bold;
|
161
|
+
background: #F7F7F7; border-bottom: 1px solid #EEEEEE;
|
162
|
+
border-left: 1px solid #EEEEEE;}
|
163
|
+
table.req tr td {padding: 2px 20px 2px 10px;
|
164
|
+
border-bottom: 1px solid #EEEEEE;
|
165
|
+
border-left: 1px solid #EEEEEE;}
|
166
|
+
/* HIDE PRE/POST CODE AT START */
|
167
|
+
.pre-context,
|
168
|
+
.post-context {display: none;}
|
169
|
+
|
170
|
+
table td.code {width:750px}
|
171
|
+
table td.code div {width:750px;overflow:hidden}
|
172
|
+
</style>
|
173
|
+
</head>
|
174
|
+
<body>
|
175
|
+
<div id="wrap">
|
176
|
+
<div id="header">
|
177
|
+
<img src="<%= env['SCRIPT_NAME'] %>/__aldebaran__/500.png" alt="application error" height="161" width="313" />
|
178
|
+
<div id="summary">
|
179
|
+
<h1><strong><%=h exception.class %></strong> at <strong><%=h path %>
|
180
|
+
</strong></h1>
|
181
|
+
<h2><%=h exception.message %></h2>
|
182
|
+
<ul>
|
183
|
+
<li class="first"><strong>file:</strong> <code>
|
184
|
+
<%=h frames.first.filename.split("/").last %></code></li>
|
185
|
+
<li><strong>location:</strong> <code><%=h frames.first.function %>
|
186
|
+
</code></li>
|
187
|
+
<li class="last"><strong>line:
|
188
|
+
</strong> <%=h frames.first.lineno %></li>
|
189
|
+
</ul>
|
190
|
+
</div>
|
191
|
+
<div class="clear"></div>
|
192
|
+
</div>
|
193
|
+
|
194
|
+
<div id="backtrace" class='condensed'>
|
195
|
+
<h3>BACKTRACE</h3>
|
196
|
+
<p><a href="#" id="expando"
|
197
|
+
onclick="toggleBacktrace(); return false">(expand)</a></p>
|
198
|
+
<p id="nav"><strong>JUMP TO:</strong>
|
199
|
+
<a href="#get-info">GET</a>
|
200
|
+
<a href="#post-info">POST</a>
|
201
|
+
<a href="#cookie-info">COOKIES</a>
|
202
|
+
<a href="#env-info">ENV</a>
|
203
|
+
</p>
|
204
|
+
<div class="clear"></div>
|
205
|
+
|
206
|
+
<ul id="backtrace-ul">
|
207
|
+
|
208
|
+
<% id = 1 %>
|
209
|
+
<% frames.each do |frame| %>
|
210
|
+
<% if frame.context_line && frame.context_line != "#" %>
|
211
|
+
|
212
|
+
<li class="frame-info <%= frame_class(frame) %>">
|
213
|
+
<code><%=h frame.filename %></code> in
|
214
|
+
<code><strong><%=h frame.function %></strong></code>
|
215
|
+
</li>
|
216
|
+
|
217
|
+
<li class="code <%= frame_class(frame) %>">
|
218
|
+
<% if frame.pre_context %>
|
219
|
+
<ol start="<%=h frame.pre_context_lineno + 1 %>"
|
220
|
+
class="pre-context" id="pre-<%= id %>"
|
221
|
+
onclick="toggle(<%= id %>);">
|
222
|
+
<% frame.pre_context.each do |line| %>
|
223
|
+
<li class="pre-context-line"><code><%=h line %></code></li>
|
224
|
+
<% end %>
|
225
|
+
</ol>
|
226
|
+
<% end %>
|
227
|
+
|
228
|
+
<ol start="<%= frame.lineno %>" class="context" id="<%= id %>"
|
229
|
+
onclick="toggle(<%= id %>);">
|
230
|
+
<li class="context-line" id="context-<%= id %>"><code><%=
|
231
|
+
h frame.context_line %></code></li>
|
232
|
+
</ol>
|
233
|
+
|
234
|
+
<% if frame.post_context %>
|
235
|
+
<ol start="<%=h frame.lineno + 1 %>" class="post-context"
|
236
|
+
id="post-<%= id %>" onclick="toggle(<%= id %>);">
|
237
|
+
<% frame.post_context.each do |line| %>
|
238
|
+
<li class="post-context-line"><code><%=h line %></code></li>
|
239
|
+
<% end %>
|
240
|
+
</ol>
|
241
|
+
<% end %>
|
242
|
+
<div class="clear"></div>
|
243
|
+
</li>
|
244
|
+
|
245
|
+
<% end %>
|
246
|
+
|
247
|
+
<% id += 1 %>
|
248
|
+
<% end %>
|
249
|
+
|
250
|
+
</ul>
|
251
|
+
</div> <!-- /BACKTRACE -->
|
252
|
+
|
253
|
+
<div id="get">
|
254
|
+
<h3 id="get-info">GET</h3>
|
255
|
+
<% if req.GET and not req.GET.empty? %>
|
256
|
+
<table class="req">
|
257
|
+
<tr>
|
258
|
+
<th>Variable</th>
|
259
|
+
<th>Value</th>
|
260
|
+
</tr>
|
261
|
+
<% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
262
|
+
<tr>
|
263
|
+
<td><%=h key %></td>
|
264
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
265
|
+
</tr>
|
266
|
+
<% } %>
|
267
|
+
</table>
|
268
|
+
<% else %>
|
269
|
+
<p class="no-data">No GET data.</p>
|
270
|
+
<% end %>
|
271
|
+
<div class="clear"></div>
|
272
|
+
</div> <!-- /GET -->
|
273
|
+
|
274
|
+
<div id="post">
|
275
|
+
<h3 id="post-info">POST</h3>
|
276
|
+
<% if req.POST and not req.POST.empty? %>
|
277
|
+
<table class="req">
|
278
|
+
<tr>
|
279
|
+
<th>Variable</th>
|
280
|
+
<th>Value</th>
|
281
|
+
</tr>
|
282
|
+
<% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
283
|
+
<tr>
|
284
|
+
<td><%=h key %></td>
|
285
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
286
|
+
</tr>
|
287
|
+
<% } %>
|
288
|
+
</table>
|
289
|
+
<% else %>
|
290
|
+
<p class="no-data">No POST data.</p>
|
291
|
+
<% end %>
|
292
|
+
<div class="clear"></div>
|
293
|
+
</div> <!-- /POST -->
|
294
|
+
|
295
|
+
<div id="cookies">
|
296
|
+
<h3 id="cookie-info">COOKIES</h3>
|
297
|
+
<% unless req.cookies.empty? %>
|
298
|
+
<table class="req">
|
299
|
+
<tr>
|
300
|
+
<th>Variable</th>
|
301
|
+
<th>Value</th>
|
302
|
+
</tr>
|
303
|
+
<% req.cookies.each { |key, val| %>
|
304
|
+
<tr>
|
305
|
+
<td><%=h key %></td>
|
306
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
307
|
+
</tr>
|
308
|
+
<% } %>
|
309
|
+
</table>
|
310
|
+
<% else %>
|
311
|
+
<p class="no-data">No cookie data.</p>
|
312
|
+
<% end %>
|
313
|
+
<div class="clear"></div>
|
314
|
+
</div> <!-- /COOKIES -->
|
315
|
+
|
316
|
+
<div id="rack">
|
317
|
+
<h3 id="env-info">Rack ENV</h3>
|
318
|
+
<table class="req">
|
319
|
+
<tr>
|
320
|
+
<th>Variable</th>
|
321
|
+
<th>Value</th>
|
322
|
+
</tr>
|
323
|
+
<% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
324
|
+
<tr>
|
325
|
+
<td><%=h key %></td>
|
326
|
+
<td class="code"><div><%=h val %></div></td>
|
327
|
+
</tr>
|
328
|
+
<% } %>
|
329
|
+
</table>
|
330
|
+
<div class="clear"></div>
|
331
|
+
</div> <!-- /RACK ENV -->
|
332
|
+
|
333
|
+
<p id="explanation">You're seeing this error because you have
|
334
|
+
enabled the <code>show_exceptions</code> setting.</p>
|
335
|
+
</div> <!-- /WRAP -->
|
336
|
+
</body>
|
337
|
+
</html>
|
338
|
+
HTML
|
339
|
+
end
|
340
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class AldebaranTest < Test::Unit::TestCase
|
4
|
+
it 'creates a new aldebaran::Base subclass on new' do
|
5
|
+
app =
|
6
|
+
aldebaran.new do
|
7
|
+
get '/' do
|
8
|
+
'Hello World'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
assert_same aldebaran::Base, app.superclass
|
12
|
+
end
|
13
|
+
|
14
|
+
it "responds to #template_cache" do
|
15
|
+
assert_kind_of Tilt::Cache, aldebaran::Base.new!.template_cache
|
16
|
+
end
|
17
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class BaseTest < Test::Unit::TestCase
|
4
|
+
def test_default
|
5
|
+
assert true
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'aldebaran::Base subclasses' do
|
9
|
+
class TestApp < aldebaran::Base
|
10
|
+
get '/' do
|
11
|
+
'Hello World'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'include Rack::Utils' do
|
16
|
+
assert TestApp.included_modules.include?(Rack::Utils)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'processes requests with #call' do
|
20
|
+
assert TestApp.respond_to?(:call)
|
21
|
+
|
22
|
+
request = Rack::MockRequest.new(TestApp)
|
23
|
+
response = request.get('/')
|
24
|
+
assert response.ok?
|
25
|
+
assert_equal 'Hello World', response.body
|
26
|
+
end
|
27
|
+
|
28
|
+
class TestApp < aldebaran::Base
|
29
|
+
get '/state' do
|
30
|
+
@foo ||= "new"
|
31
|
+
body = "Foo: #{@foo}"
|
32
|
+
@foo = 'discard'
|
33
|
+
body
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not maintain state between requests' do
|
38
|
+
request = Rack::MockRequest.new(TestApp)
|
39
|
+
2.times do
|
40
|
+
response = request.get('/state')
|
41
|
+
assert response.ok?
|
42
|
+
assert_equal 'Foo: new', response.body
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "passes the subclass to configure blocks" do
|
47
|
+
ref = nil
|
48
|
+
TestApp.configure { |app| ref = app }
|
49
|
+
assert_equal TestApp, ref
|
50
|
+
end
|
51
|
+
|
52
|
+
it "allows the configure block arg to be omitted and does not change context" do
|
53
|
+
context = nil
|
54
|
+
TestApp.configure { context = self }
|
55
|
+
assert_equal self, context
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "aldebaran::Base as Rack middleware" do
|
60
|
+
app = lambda { |env|
|
61
|
+
headers = {'X-Downstream' => 'true'}
|
62
|
+
headers['X-Route-Missing'] = env['aldebaran.route-missing'] || ''
|
63
|
+
[210, headers, ['Hello from downstream']] }
|
64
|
+
|
65
|
+
class TestMiddleware < aldebaran::Base
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'creates a middleware that responds to #call with .new' do
|
69
|
+
middleware = TestMiddleware.new(app)
|
70
|
+
assert middleware.respond_to?(:call)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'exposes the downstream app' do
|
74
|
+
middleware = TestMiddleware.new!(app)
|
75
|
+
assert_same app, middleware.app
|
76
|
+
end
|
77
|
+
|
78
|
+
class TestMiddleware < aldebaran::Base
|
79
|
+
def route_missing
|
80
|
+
env['aldebaran.route-missing'] = '1'
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
84
|
+
get '/' do
|
85
|
+
'Hello from middleware'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
middleware = TestMiddleware.new(app)
|
90
|
+
request = Rack::MockRequest.new(middleware)
|
91
|
+
|
92
|
+
it 'intercepts requests' do
|
93
|
+
response = request.get('/')
|
94
|
+
assert response.ok?
|
95
|
+
assert_equal 'Hello from middleware', response.body
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'automatically forwards requests downstream when no matching route found' do
|
99
|
+
response = request.get('/missing')
|
100
|
+
assert_equal 210, response.status
|
101
|
+
assert_equal 'Hello from downstream', response.body
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'calls #route_missing before forwarding downstream' do
|
105
|
+
response = request.get('/missing')
|
106
|
+
assert_equal '1', response['X-Route-Missing']
|
107
|
+
end
|
108
|
+
|
109
|
+
class TestMiddleware < aldebaran::Base
|
110
|
+
get '/low-level-forward' do
|
111
|
+
app.call(env)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'can call the downstream app directly and return result' do
|
116
|
+
response = request.get('/low-level-forward')
|
117
|
+
assert_equal 210, response.status
|
118
|
+
assert_equal 'true', response['X-Downstream']
|
119
|
+
assert_equal 'Hello from downstream', response.body
|
120
|
+
end
|
121
|
+
|
122
|
+
class TestMiddleware < aldebaran::Base
|
123
|
+
get '/explicit-forward' do
|
124
|
+
response['X-Middleware'] = 'true'
|
125
|
+
res = forward
|
126
|
+
assert_nil res
|
127
|
+
assert_equal 210, response.status
|
128
|
+
assert_equal 'true', response['X-Downstream']
|
129
|
+
assert_equal ['Hello from downstream'], response.body
|
130
|
+
'Hello after explicit forward'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'forwards the request downstream and integrates the response into the current context' do
|
135
|
+
response = request.get('/explicit-forward')
|
136
|
+
assert_equal 210, response.status
|
137
|
+
assert_equal 'true', response['X-Downstream']
|
138
|
+
assert_equal 'Hello after explicit forward', response.body
|
139
|
+
assert_equal '28', response['Content-Length']
|
140
|
+
end
|
141
|
+
|
142
|
+
app_content_length = lambda {|env|
|
143
|
+
[200, {'Content-Length' => '16'}, 'From downstream!']}
|
144
|
+
|
145
|
+
class TestMiddlewareContentLength < aldebaran::Base
|
146
|
+
get '/forward' do
|
147
|
+
res = forward
|
148
|
+
'From after explicit forward!'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
|
153
|
+
request_content_length = Rack::MockRequest.new(middleware_content_length)
|
154
|
+
|
155
|
+
it "sets content length for last response" do
|
156
|
+
response = request_content_length.get('/forward')
|
157
|
+
assert_equal '28', response['Content-Length']
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|