goliath 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of goliath might be problematic. Click here for more details.
- data/.gitignore +1 -0
- data/HISTORY +50 -0
- data/README.md +2 -0
- data/examples/activerecord/srv.rb +1 -3
- data/examples/async_aroundware_demo.rb +81 -0
- data/examples/async_upload.rb +1 -2
- data/examples/auth_and_rate_limit.rb +143 -0
- data/examples/chunked_streaming.rb +37 -0
- data/examples/conf_test.rb +1 -3
- data/examples/config/auth_and_rate_limit.rb +30 -0
- data/examples/config/template.rb +8 -0
- data/examples/content_stream.rb +1 -3
- data/examples/echo.rb +8 -6
- data/examples/env_use_statements.rb +17 -0
- data/examples/gziped.rb +1 -3
- data/examples/public/stylesheets/style.css +296 -0
- data/examples/rack_routes.rb +65 -3
- data/examples/rasterize/rasterize.js +15 -0
- data/examples/rasterize/rasterize.rb +36 -0
- data/examples/rasterize/rasterize_and_shorten.rb +37 -0
- data/examples/stream.rb +2 -2
- data/examples/template.rb +48 -0
- data/examples/test_rig.rb +125 -0
- data/examples/valid.rb +4 -2
- data/examples/views/debug.haml +4 -0
- data/examples/views/joke.markdown +13 -0
- data/examples/views/layout.erb +12 -0
- data/examples/views/layout.haml +39 -0
- data/examples/views/root.haml +28 -0
- data/goliath.gemspec +10 -3
- data/lib/goliath.rb +0 -36
- data/lib/goliath/api.rb +137 -26
- data/lib/goliath/application.rb +71 -21
- data/lib/goliath/connection.rb +4 -2
- data/lib/goliath/constants.rb +1 -0
- data/lib/goliath/env.rb +40 -1
- data/lib/goliath/goliath.rb +30 -15
- data/lib/goliath/headers.rb +2 -2
- data/lib/goliath/plugins/latency.rb +8 -2
- data/lib/goliath/rack.rb +18 -0
- data/lib/goliath/rack/async_aroundware.rb +56 -0
- data/lib/goliath/rack/async_middleware.rb +93 -0
- data/lib/goliath/rack/builder.rb +42 -0
- data/lib/goliath/rack/default_response_format.rb +3 -15
- data/lib/goliath/rack/formatters.rb +11 -0
- data/lib/goliath/rack/formatters/html.rb +2 -18
- data/lib/goliath/rack/formatters/json.rb +2 -17
- data/lib/goliath/rack/formatters/plist.rb +32 -0
- data/lib/goliath/rack/formatters/xml.rb +23 -31
- data/lib/goliath/rack/formatters/yaml.rb +27 -0
- data/lib/goliath/rack/jsonp.rb +1 -13
- data/lib/goliath/rack/params.rb +55 -27
- data/lib/goliath/rack/render.rb +13 -22
- data/lib/goliath/rack/templates.rb +357 -0
- data/lib/goliath/rack/tracer.rb +11 -12
- data/lib/goliath/rack/validation.rb +12 -0
- data/lib/goliath/rack/validation/default_params.rb +0 -2
- data/lib/goliath/rack/validation/numeric_range.rb +11 -2
- data/lib/goliath/rack/validation/request_method.rb +3 -2
- data/lib/goliath/rack/validation/required_param.rb +13 -11
- data/lib/goliath/rack/validation/required_value.rb +11 -15
- data/lib/goliath/rack/validator.rb +51 -0
- data/lib/goliath/request.rb +34 -20
- data/lib/goliath/response.rb +3 -2
- data/lib/goliath/runner.rb +5 -11
- data/lib/goliath/server.rb +2 -1
- data/lib/goliath/synchrony/mongo_receiver.rb +64 -0
- data/lib/goliath/synchrony/response_receiver.rb +64 -0
- data/lib/goliath/test_helper.rb +39 -21
- data/lib/goliath/validation.rb +2 -0
- data/lib/goliath/{rack/validation_error.rb → validation/error.rb} +0 -16
- data/lib/goliath/validation/standard_http_errors.rb +31 -0
- data/lib/goliath/version.rb +1 -1
- data/spec/integration/http_log_spec.rb +16 -16
- data/spec/integration/rack_routes_spec.rb +144 -0
- data/spec/integration/reloader_spec.rb +4 -4
- data/spec/integration/template_spec.rb +54 -0
- data/spec/integration/trace_spec.rb +23 -0
- data/spec/integration/valid_spec.rb +21 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/unit/api_spec.rb +30 -0
- data/spec/unit/rack/builder_spec.rb +40 -0
- data/spec/unit/rack/formatters/plist_spec.rb +51 -0
- data/spec/unit/rack/formatters/yaml_spec.rb +53 -0
- data/spec/unit/rack/params_spec.rb +22 -0
- data/spec/unit/rack/render_spec.rb +10 -5
- data/spec/unit/rack/validation/numeric_range_spec.rb +8 -1
- data/spec/unit/rack/validation/request_method_spec.rb +8 -8
- data/spec/unit/rack/validation/required_param_spec.rb +19 -15
- data/spec/unit/rack/validation/required_value_spec.rb +10 -13
- data/spec/unit/server_spec.rb +4 -4
- data/spec/unit/validation/standard_http_errors_spec.rb +21 -0
- metadata +177 -35
- data/spec/unit/rack/validation_error_spec.rb +0 -40
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
require 'yajl'
|
6
|
+
|
7
|
+
class EnvUseStatements < Goliath::API
|
8
|
+
if Goliath.dev?
|
9
|
+
use Goliath::Rack::Render, 'json'
|
10
|
+
elsif Goliath.prod?
|
11
|
+
use Goliath::Rack::Render, 'xml'
|
12
|
+
end
|
13
|
+
|
14
|
+
def response(env)
|
15
|
+
[200, {}, {'Test' => 'Response'}]
|
16
|
+
end
|
17
|
+
end
|
data/examples/gziped.rb
CHANGED
@@ -27,9 +27,7 @@ class Gziped < Goliath::API
|
|
27
27
|
end
|
28
28
|
|
29
29
|
use Goliath::Rack::Params # parse & merge query and body parameters
|
30
|
-
use Goliath::Rack::
|
31
|
-
use Goliath::Rack::Render # auto-negotiate response format
|
32
|
-
use Goliath::Rack::ValidationError # catch and render validation errors
|
30
|
+
use Goliath::Rack::Render, 'json' # auto-negotiate response format
|
33
31
|
|
34
32
|
use Goliath::Rack::Validation::RequestMethod, %w(GET) # allow GET requests only
|
35
33
|
use Goliath::Rack::Validation::RequiredParam, {:key => 'echo'} # must provide ?echo= query or body param
|
@@ -0,0 +1,296 @@
|
|
1
|
+
|
2
|
+
/* ==== Scroll down to find where to put your styles :) ==== */
|
3
|
+
|
4
|
+
/* HTML5 - Boilerplate */
|
5
|
+
|
6
|
+
html, body, div, span, object, iframe,
|
7
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
8
|
+
abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
|
9
|
+
small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
|
10
|
+
fieldset, form, label, legend,
|
11
|
+
table, caption, tbody, tfoot, thead, tr, th, td,
|
12
|
+
article, aside, canvas, details, figcaption, figure,
|
13
|
+
footer, header, hgroup, menu, nav, section, summary,
|
14
|
+
time, mark, audio, video {
|
15
|
+
margin: 0;
|
16
|
+
padding: 0;
|
17
|
+
border: 0;
|
18
|
+
font-size: 100%;
|
19
|
+
font: inherit;
|
20
|
+
vertical-align: baseline;
|
21
|
+
}
|
22
|
+
|
23
|
+
article, aside, details, figcaption, figure,
|
24
|
+
footer, header, hgroup, menu, nav, section {
|
25
|
+
display: block;
|
26
|
+
}
|
27
|
+
|
28
|
+
blockquote, q { quotes: none; }
|
29
|
+
blockquote:before, blockquote:after,
|
30
|
+
q:before, q:after { content: ''; content: none; }
|
31
|
+
ins { background-color: #ff9; color: #000; text-decoration: none; }
|
32
|
+
mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
|
33
|
+
del { text-decoration: line-through; }
|
34
|
+
abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
|
35
|
+
table { border-collapse: collapse; border-spacing: 0; }
|
36
|
+
hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
|
37
|
+
input, select { vertical-align: middle; }
|
38
|
+
|
39
|
+
body { font:13px/1.231 sans-serif; *font-size:small; }
|
40
|
+
select, input, textarea, button { font:99% sans-serif; }
|
41
|
+
pre, code, kbd, samp { font-family: monospace, sans-serif; }
|
42
|
+
|
43
|
+
html { overflow-y: scroll; }
|
44
|
+
a:hover, a:active { outline: none; }
|
45
|
+
ul, ol { margin-left: 2em; }
|
46
|
+
ol { list-style-type: decimal; }
|
47
|
+
nav ul, nav li { margin: 0; list-style:none; list-style-image: none; }
|
48
|
+
small { font-size: 85%; }
|
49
|
+
strong, th { font-weight: bold; }
|
50
|
+
td { vertical-align: top; }
|
51
|
+
|
52
|
+
sub, sup { font-size: 75%; line-height: 0; position: relative; }
|
53
|
+
sup { top: -0.5em; }
|
54
|
+
sub { bottom: -0.25em; }
|
55
|
+
|
56
|
+
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 15px; }
|
57
|
+
textarea { overflow: auto; }
|
58
|
+
.ie6 legend, .ie7 legend { margin-left: -7px; }
|
59
|
+
input[type="radio"] { vertical-align: text-bottom; }
|
60
|
+
input[type="checkbox"] { vertical-align: bottom; }
|
61
|
+
.ie7 input[type="checkbox"] { vertical-align: baseline; }
|
62
|
+
.ie6 input { vertical-align: text-bottom; }
|
63
|
+
label, input[type="button"], input[type="submit"], input[type="image"], button { cursor: pointer; }
|
64
|
+
button, input, select, textarea { margin: 0; }
|
65
|
+
input:valid, textarea:valid { }
|
66
|
+
input:invalid, textarea:invalid { border-radius: 1px; -moz-box-shadow: 0px 0px 5px red; -webkit-box-shadow: 0px 0px 5px red; box-shadow: 0px 0px 5px red; }
|
67
|
+
.no-boxshadow input:invalid, .no-boxshadow textarea:invalid { background-color: #f0dddd; }
|
68
|
+
|
69
|
+
::-moz-selection{ background: #eFdEe9; color:#fff; text-shadow: none; }
|
70
|
+
::selection { background:#eFdEe9; color:#fff; text-shadow: none; }
|
71
|
+
a:link { -webkit-tap-highlight-color: #eFdEe9; }
|
72
|
+
|
73
|
+
button { width: auto; overflow: visible; }
|
74
|
+
.ie7 img { -ms-interpolation-mode: bicubic; }
|
75
|
+
|
76
|
+
body, select, input, textarea { color: #444; }
|
77
|
+
h1, h2, h3, h4, h5, h6 { font-weight: bold; }
|
78
|
+
a, a:active, a:visited { color: #607890; }
|
79
|
+
a:hover { color: #036; }
|
80
|
+
|
81
|
+
/*
|
82
|
+
// ========================================== \\
|
83
|
+
|| ||
|
84
|
+
|| Your styles ! ||
|
85
|
+
|| ||
|
86
|
+
\\ ========================================== //
|
87
|
+
*/
|
88
|
+
|
89
|
+
|
90
|
+
body{
|
91
|
+
font-family:Helvetica, Helvetica Neue, Arial, sans-serif;
|
92
|
+
}
|
93
|
+
|
94
|
+
.wrapper{
|
95
|
+
margin:auto;
|
96
|
+
width:960px;
|
97
|
+
}
|
98
|
+
|
99
|
+
#logo {
|
100
|
+
float: left;
|
101
|
+
margin-top: 10px;
|
102
|
+
margin-right: 20px;
|
103
|
+
}
|
104
|
+
|
105
|
+
#header-container{
|
106
|
+
background-color:#e4edf6;
|
107
|
+
height:80px;
|
108
|
+
border-bottom:20px solid #f1e5d9;
|
109
|
+
margin-bottom:50px;
|
110
|
+
}
|
111
|
+
|
112
|
+
#title{
|
113
|
+
font-weight:normal;
|
114
|
+
font-size: 50px;
|
115
|
+
color:white;
|
116
|
+
padding: 15px 5px 10px 0;
|
117
|
+
float:left;
|
118
|
+
clear: none;
|
119
|
+
}
|
120
|
+
#title a{ text-decoration: none }
|
121
|
+
|
122
|
+
h1 { font-size: 185%; padding-top: 14px; padding-bottom: 5px; }
|
123
|
+
h2 { font-size: 154%; padding-top: 20px; padding-bottom: 4px; }
|
124
|
+
h3 { font-size: 139%; padding-top: 6px; padding-bottom: 4px; }
|
125
|
+
h4 { font-size: 116%; padding-top: 4px; padding-bottom: 2px; }
|
126
|
+
|
127
|
+
nav{
|
128
|
+
float:right;
|
129
|
+
margin-top:10px;
|
130
|
+
}
|
131
|
+
|
132
|
+
nav ul, nav ul li{
|
133
|
+
display:inline;
|
134
|
+
}
|
135
|
+
|
136
|
+
nav a, nav a:visited, nav a:active{
|
137
|
+
padding:10px 20px;
|
138
|
+
color:#666;
|
139
|
+
text-decoration:none;
|
140
|
+
background-color:#d4dde6;
|
141
|
+
}
|
142
|
+
|
143
|
+
aside{
|
144
|
+
color:#444;
|
145
|
+
padding:20px;
|
146
|
+
float:right;
|
147
|
+
height:500px;
|
148
|
+
width:200px;
|
149
|
+
background-color:#e4edf6;
|
150
|
+
border-bottom:20px solid #e44d26;
|
151
|
+
margin-bottom:50px;
|
152
|
+
}
|
153
|
+
|
154
|
+
#main {
|
155
|
+
min-height: 550px;
|
156
|
+
}
|
157
|
+
|
158
|
+
#main p{
|
159
|
+
font:16px/26px Helvetica, Helvetica Neue, Arial;
|
160
|
+
width:620px;
|
161
|
+
text-shadow:none;
|
162
|
+
}
|
163
|
+
|
164
|
+
#main header h2{
|
165
|
+
padding-bottom:30px;
|
166
|
+
}
|
167
|
+
|
168
|
+
article header{
|
169
|
+
margin-bottom:50px;
|
170
|
+
padding-bottom:30px;
|
171
|
+
width:700px;
|
172
|
+
}
|
173
|
+
|
174
|
+
#footer-container{
|
175
|
+
background-color:#e4edf6;
|
176
|
+
height:240px;
|
177
|
+
border-top:40px solid #e4edf6;
|
178
|
+
margin-top:50px;
|
179
|
+
}
|
180
|
+
|
181
|
+
#footer-container footer{
|
182
|
+
color:#888;
|
183
|
+
text-align:right;
|
184
|
+
}
|
185
|
+
#footer-container footer a, #footer-container footer a:active, #footer-container footer a:visited { color: #88a; }
|
186
|
+
|
187
|
+
.info{
|
188
|
+
position:absolute;
|
189
|
+
top:5px;
|
190
|
+
background-color:white;
|
191
|
+
padding:10px;
|
192
|
+
}
|
193
|
+
|
194
|
+
#jquery-test{
|
195
|
+
top:45px;
|
196
|
+
}
|
197
|
+
|
198
|
+
.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; }
|
199
|
+
.hidden { display: none; visibility: hidden; }
|
200
|
+
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
|
201
|
+
.visuallyhidden.focusable:active,
|
202
|
+
.visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
|
203
|
+
.invisible { visibility: hidden; }
|
204
|
+
.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
|
205
|
+
.clearfix:after { clear: both; }
|
206
|
+
.clearfix { zoom: 1; }
|
207
|
+
|
208
|
+
|
209
|
+
.meter {
|
210
|
+
margin: 3em;
|
211
|
+
background-color: #eee;
|
212
|
+
padding: 2em;
|
213
|
+
font-size: 154%;
|
214
|
+
}
|
215
|
+
|
216
|
+
|
217
|
+
/* Nice table styling for greater dashboard justice */
|
218
|
+
table {
|
219
|
+
text-align: left;
|
220
|
+
}
|
221
|
+
table th, table td {
|
222
|
+
text-align: left;
|
223
|
+
}
|
224
|
+
table th {
|
225
|
+
font-weight: bold;
|
226
|
+
}
|
227
|
+
table th, table td {
|
228
|
+
min-width: 30px;
|
229
|
+
padding: 4px 0 4px 10px;
|
230
|
+
}
|
231
|
+
table th:first-child, table td:first-child {
|
232
|
+
padding-left: 0;
|
233
|
+
}
|
234
|
+
table tbody tr:hover {
|
235
|
+
background-color: #e8f0ff;
|
236
|
+
}
|
237
|
+
|
238
|
+
table.full {
|
239
|
+
width: 960px;
|
240
|
+
}
|
241
|
+
table.horizontal th {
|
242
|
+
border-bottom: 2px solid #6678b1;
|
243
|
+
}
|
244
|
+
table.horizontal th, table.horizontal td {
|
245
|
+
min-width: 70px;
|
246
|
+
}
|
247
|
+
|
248
|
+
table.vertical {
|
249
|
+
margin: 16px 0;
|
250
|
+
}
|
251
|
+
table.vertical th {
|
252
|
+
width: 180px;
|
253
|
+
padding: 4px 5px 3px 5px;
|
254
|
+
border-bottom: 1px solid #51ded8;
|
255
|
+
}
|
256
|
+
table.vertical td {
|
257
|
+
padding: 4px 0 3px 10px;
|
258
|
+
border-bottom: 1px solid #f1eee8;
|
259
|
+
}
|
260
|
+
table.vertical th:first-child {
|
261
|
+
white-space: nowrap;
|
262
|
+
}
|
263
|
+
table.vertical tr:last-child {
|
264
|
+
border: none;
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
@media all and (orientation:portrait) {
|
270
|
+
|
271
|
+
}
|
272
|
+
|
273
|
+
@media all and (orientation:landscape) {
|
274
|
+
|
275
|
+
}
|
276
|
+
|
277
|
+
@media screen and (max-device-width: 480px) {
|
278
|
+
|
279
|
+
/* html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
|
280
|
+
}
|
281
|
+
|
282
|
+
|
283
|
+
@media print {
|
284
|
+
* { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important;
|
285
|
+
-ms-filter: none !important; }
|
286
|
+
a, a:visited { color: #444 !important; text-decoration: underline; }
|
287
|
+
a[href]:after { content: " (" attr(href) ")"; }
|
288
|
+
abbr[title]:after { content: " (" attr(title) ")"; }
|
289
|
+
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
|
290
|
+
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
|
291
|
+
thead { display: table-header-group; }
|
292
|
+
tr, img { page-break-inside: avoid; }
|
293
|
+
@page { margin: 0.5cm; }
|
294
|
+
p, h2, h3 { orphans: 3; widows: 3; }
|
295
|
+
h2, h3{ page-break-after: avoid; }
|
296
|
+
}
|
data/examples/rack_routes.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
2
3
|
$:<< '../lib' << 'lib'
|
3
4
|
|
4
5
|
require 'goliath'
|
@@ -19,18 +20,59 @@ class HelloWorld < Goliath::API
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
class PostHelloWorld < Goliath::API
|
24
|
+
def response(env)
|
25
|
+
[200, {}, "hello post world!"]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class HelloNumber < Goliath::API
|
30
|
+
use Goliath::Rack::Params
|
31
|
+
def response(env)
|
32
|
+
[200, {}, "number #{params[:number]}!"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class BigNumber < Goliath::API
|
37
|
+
use Goliath::Rack::Params
|
38
|
+
def response(env)
|
39
|
+
[200, {}, "big number #{params[:number]}!"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
22
43
|
class Bonjour < Goliath::API
|
23
44
|
def response(env)
|
24
45
|
[200, {}, "bonjour!"]
|
25
46
|
end
|
26
47
|
end
|
27
48
|
|
49
|
+
class Hola < Goliath::API
|
50
|
+
use Goliath::Rack::Params
|
51
|
+
use Goliath::Rack::Validation::RequiredParam, {:key => "foo"}
|
52
|
+
|
53
|
+
def response(env)
|
54
|
+
[200, {}, "hola!"]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Aloha < Goliath::API
|
59
|
+
use Goliath::Rack::Validation::RequestMethod, %w(GET)
|
60
|
+
|
61
|
+
def response(env)
|
62
|
+
[200, {}, "Aloha"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
28
66
|
class RackRoutes < Goliath::API
|
29
67
|
map '/version' do
|
30
68
|
run Proc.new { |env| [200, {"Content-Type" => "text/html"}, ["Version 0.1"]] }
|
31
69
|
end
|
32
70
|
|
33
|
-
|
71
|
+
post "/hello_world" do
|
72
|
+
run PostHelloWorld.new
|
73
|
+
end
|
74
|
+
|
75
|
+
get "/hello_world" do
|
34
76
|
run HelloWorld.new
|
35
77
|
end
|
36
78
|
|
@@ -38,7 +80,27 @@ class RackRoutes < Goliath::API
|
|
38
80
|
run Bonjour.new
|
39
81
|
end
|
40
82
|
|
41
|
-
map
|
42
|
-
|
83
|
+
map "/hola" do
|
84
|
+
use Goliath::Rack::Validation::RequestMethod, %w(GET)
|
85
|
+
run Hola.new
|
86
|
+
end
|
87
|
+
|
88
|
+
map "/aloha", Aloha
|
89
|
+
|
90
|
+
map "/:number", :number => /\d+/ do
|
91
|
+
if params[:number].to_i > 100
|
92
|
+
run BigNumber.new
|
93
|
+
else
|
94
|
+
run HelloNumber.new
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
not_found('/') do
|
99
|
+
run Proc.new { |env| [404, {"Content-Type" => "text/html"}, ["Try /version /hello_world, /bonjour, or /hola"]] }
|
100
|
+
end
|
101
|
+
|
102
|
+
# You must use either maps or response, but never both!
|
103
|
+
def response(env)
|
104
|
+
raise RuntimeException.new("#response is ignored when using maps, so this exception won't raise. See spec/integration/rack_routes_spec.")
|
43
105
|
end
|
44
106
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
if (phantom.state.length === 0) {
|
2
|
+
if (phantom.args.length !== 2) {
|
3
|
+
console.log('Usage: rasterize.js URL filename');
|
4
|
+
phantom.exit();
|
5
|
+
} else {
|
6
|
+
var address = phantom.args[0];
|
7
|
+
phantom.state = 'rasterize';
|
8
|
+
phantom.viewportSize = { width: 800, height: 600 };
|
9
|
+
phantom.open(address);
|
10
|
+
}
|
11
|
+
} else {
|
12
|
+
var output = phantom.args[1];
|
13
|
+
phantom.render(output);
|
14
|
+
phantom.exit();
|
15
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../../lib'
|
3
|
+
require 'goliath'
|
4
|
+
require 'postrank-uri'
|
5
|
+
|
6
|
+
# Install phantomjs: http://code.google.com/p/phantomjs/wiki/QuickStart
|
7
|
+
# $> ruby rasterize.rb -sv
|
8
|
+
# $> curl http://localhost:9000/?url=http://www.google.com (or rather, visit in the browser!)
|
9
|
+
|
10
|
+
class Rasterize < Goliath::API
|
11
|
+
use Goliath::Rack::Params
|
12
|
+
|
13
|
+
use Goliath::Rack::Validation::RequestMethod, %w(GET)
|
14
|
+
use Goliath::Rack::Validation::RequiredParam, {:key => 'url'}
|
15
|
+
|
16
|
+
def response(env)
|
17
|
+
url = PostRank::URI.clean(params['url'])
|
18
|
+
hash = PostRank::URI.hash(url, :clean => false)
|
19
|
+
|
20
|
+
if !File.exists? filename(hash)
|
21
|
+
fiber = Fiber.current
|
22
|
+
EM.system('phantomjs rasterize.js ' + url.to_s + ' ' + filename(hash)) do |output, status|
|
23
|
+
env.logger.info "Phantom exit status: #{status}"
|
24
|
+
fiber.resume
|
25
|
+
end
|
26
|
+
|
27
|
+
Fiber.yield
|
28
|
+
end
|
29
|
+
|
30
|
+
[202, {'X-Phantom' => 'Goliath'}, IO.read(filename(hash))]
|
31
|
+
end
|
32
|
+
|
33
|
+
def filename(hash)
|
34
|
+
"thumb/#{hash}.png"
|
35
|
+
end
|
36
|
+
end
|