sinatra 1.4.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/AUTHORS.md +5 -2
- data/{CHANGES → CHANGELOG.md} +126 -46
- data/CONTRIBUTING.md +100 -0
- data/Gemfile +12 -17
- data/LICENSE +5 -2
- data/MAINTENANCE.md +42 -0
- data/README.de.md +711 -466
- data/README.es.md +206 -171
- data/README.fr.md +370 -344
- data/README.hu.md +44 -10
- data/README.ja.md +300 -210
- data/README.ko.md +230 -191
- data/README.md +675 -528
- data/README.pt-br.md +149 -115
- data/README.pt-pt.md +65 -65
- data/README.ru.md +198 -97
- data/README.zh.md +1943 -1237
- data/Rakefile +72 -49
- data/SECURITY.md +35 -0
- data/lib/sinatra/base.rb +141 -207
- data/lib/sinatra/indifferent_hash.rb +150 -0
- data/lib/sinatra/main.rb +1 -0
- data/lib/sinatra/show_exceptions.rb +70 -56
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +19 -7
- metadata +32 -163
- data/test/asciidoctor_test.rb +0 -72
- data/test/base_test.rb +0 -167
- data/test/builder_test.rb +0 -91
- data/test/coffee_test.rb +0 -96
- data/test/compile_test.rb +0 -183
- data/test/contest.rb +0 -91
- data/test/creole_test.rb +0 -65
- data/test/delegator_test.rb +0 -160
- data/test/encoding_test.rb +0 -20
- data/test/erb_test.rb +0 -116
- data/test/extensions_test.rb +0 -98
- data/test/filter_test.rb +0 -487
- data/test/haml_test.rb +0 -109
- data/test/helper.rb +0 -132
- data/test/helpers_test.rb +0 -1917
- data/test/integration/app.rb +0 -79
- data/test/integration_helper.rb +0 -236
- data/test/integration_test.rb +0 -104
- data/test/less_test.rb +0 -69
- data/test/liquid_test.rb +0 -77
- data/test/mapped_error_test.rb +0 -285
- data/test/markaby_test.rb +0 -80
- data/test/markdown_test.rb +0 -85
- data/test/mediawiki_test.rb +0 -68
- data/test/middleware_test.rb +0 -68
- data/test/nokogiri_test.rb +0 -67
- data/test/public/favicon.ico +0 -0
- data/test/rabl_test.rb +0 -89
- data/test/rack_test.rb +0 -45
- data/test/radius_test.rb +0 -59
- data/test/rdoc_test.rb +0 -66
- data/test/readme_test.rb +0 -130
- data/test/request_test.rb +0 -100
- data/test/response_test.rb +0 -63
- data/test/result_test.rb +0 -76
- data/test/route_added_hook_test.rb +0 -59
- data/test/routing_test.rb +0 -1412
- data/test/sass_test.rb +0 -115
- data/test/scss_test.rb +0 -88
- data/test/server_test.rb +0 -56
- data/test/settings_test.rb +0 -582
- data/test/sinatra_test.rb +0 -12
- data/test/slim_test.rb +0 -102
- data/test/static_test.rb +0 -236
- data/test/streaming_test.rb +0 -149
- data/test/stylus_test.rb +0 -90
- data/test/templates_test.rb +0 -382
- data/test/textile_test.rb +0 -65
- data/test/views/a/in_a.str +0 -1
- data/test/views/ascii.erb +0 -2
- data/test/views/b/in_b.str +0 -1
- data/test/views/calc.html.erb +0 -1
- data/test/views/error.builder +0 -3
- data/test/views/error.erb +0 -3
- data/test/views/error.haml +0 -3
- data/test/views/error.sass +0 -2
- data/test/views/explicitly_nested.str +0 -1
- data/test/views/foo/hello.test +0 -1
- data/test/views/hello.asciidoc +0 -1
- data/test/views/hello.builder +0 -1
- data/test/views/hello.coffee +0 -1
- data/test/views/hello.creole +0 -1
- data/test/views/hello.erb +0 -1
- data/test/views/hello.haml +0 -1
- data/test/views/hello.less +0 -5
- data/test/views/hello.liquid +0 -1
- data/test/views/hello.mab +0 -1
- data/test/views/hello.md +0 -1
- data/test/views/hello.mediawiki +0 -1
- data/test/views/hello.nokogiri +0 -1
- data/test/views/hello.rabl +0 -2
- data/test/views/hello.radius +0 -1
- data/test/views/hello.rdoc +0 -1
- data/test/views/hello.sass +0 -2
- data/test/views/hello.scss +0 -3
- data/test/views/hello.slim +0 -1
- data/test/views/hello.str +0 -1
- data/test/views/hello.styl +0 -2
- data/test/views/hello.test +0 -1
- data/test/views/hello.textile +0 -1
- data/test/views/hello.wlang +0 -1
- data/test/views/hello.yajl +0 -1
- data/test/views/layout2.builder +0 -3
- data/test/views/layout2.erb +0 -2
- data/test/views/layout2.haml +0 -2
- data/test/views/layout2.liquid +0 -2
- data/test/views/layout2.mab +0 -2
- data/test/views/layout2.nokogiri +0 -3
- data/test/views/layout2.rabl +0 -3
- data/test/views/layout2.radius +0 -2
- data/test/views/layout2.slim +0 -3
- data/test/views/layout2.str +0 -2
- data/test/views/layout2.test +0 -1
- data/test/views/layout2.wlang +0 -2
- data/test/views/nested.str +0 -1
- data/test/views/utf8.erb +0 -2
- data/test/wlang_test.rb +0 -87
- data/test/yajl_test.rb +0 -86
data/README.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# Sinatra
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://secure.travis-ci.org/sinatra/sinatra.svg)](http://travis-ci.org/sinatra/sinatra)
|
4
|
+
|
5
|
+
Sinatra is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for
|
4
6
|
quickly creating web applications in Ruby with minimal effort:
|
5
7
|
|
6
|
-
```
|
8
|
+
```ruby
|
7
9
|
# myapp.rb
|
8
10
|
require 'sinatra'
|
9
11
|
|
@@ -14,17 +16,17 @@ end
|
|
14
16
|
|
15
17
|
Install the gem:
|
16
18
|
|
17
|
-
```
|
19
|
+
```shell
|
18
20
|
gem install sinatra
|
19
21
|
```
|
20
22
|
|
21
23
|
And run with:
|
22
24
|
|
23
|
-
```
|
25
|
+
```shell
|
24
26
|
ruby myapp.rb
|
25
27
|
```
|
26
28
|
|
27
|
-
View at: http://localhost:4567
|
29
|
+
View at: [http://localhost:4567](http://localhost:4567)
|
28
30
|
|
29
31
|
It is recommended to also run `gem install thin`, which Sinatra will
|
30
32
|
pick up if available.
|
@@ -73,6 +75,9 @@ pick up if available.
|
|
73
75
|
* [Filters](#filters)
|
74
76
|
* [Helpers](#helpers)
|
75
77
|
* [Using Sessions](#using-sessions)
|
78
|
+
* [Session Secret Security](#session-secret-security)
|
79
|
+
* [Session Config](#session-config)
|
80
|
+
* [Choosing Your Own Session Middleware](#choosing-your-own-session-middleware)
|
76
81
|
* [Halting](#halting)
|
77
82
|
* [Passing](#passing)
|
78
83
|
* [Triggering Another Route](#triggering-another-route)
|
@@ -109,11 +114,10 @@ pick up if available.
|
|
109
114
|
* [Request/Instance Scope](#requestinstance-scope)
|
110
115
|
* [Delegation Scope](#delegation-scope)
|
111
116
|
* [Command Line](#command-line)
|
117
|
+
* [Multi-threading](#multi-threading)
|
112
118
|
* [Requirement](#requirement)
|
113
119
|
* [The Bleeding Edge](#the-bleeding-edge)
|
114
120
|
* [With Bundler](#with-bundler)
|
115
|
-
* [Roll Your Own](#roll-your-own)
|
116
|
-
* [Install Globally](#install-globally)
|
117
121
|
* [Versioning](#versioning)
|
118
122
|
* [Further Reading](#further-reading)
|
119
123
|
|
@@ -122,7 +126,7 @@ pick up if available.
|
|
122
126
|
In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
|
123
127
|
Each route is associated with a block:
|
124
128
|
|
125
|
-
```
|
129
|
+
```ruby
|
126
130
|
get '/' do
|
127
131
|
.. show something ..
|
128
132
|
end
|
@@ -159,10 +163,18 @@ end
|
|
159
163
|
Routes are matched in the order they are defined. The first route that
|
160
164
|
matches the request is invoked.
|
161
165
|
|
166
|
+
Routes with trailing slashes are different from the ones without:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
get '/foo' do
|
170
|
+
# Does not match "GET /foo/"
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
162
174
|
Route patterns may include named parameters, accessible via the
|
163
175
|
`params` hash:
|
164
176
|
|
165
|
-
```
|
177
|
+
```ruby
|
166
178
|
get '/hello/:name' do
|
167
179
|
# matches "GET /hello/foo" and "GET /hello/bar"
|
168
180
|
# params['name'] is 'foo' or 'bar'
|
@@ -172,7 +184,7 @@ end
|
|
172
184
|
|
173
185
|
You can also access named parameters via block parameters:
|
174
186
|
|
175
|
-
```
|
187
|
+
```ruby
|
176
188
|
get '/hello/:name' do |n|
|
177
189
|
# matches "GET /hello/foo" and "GET /hello/bar"
|
178
190
|
# params['name'] is 'foo' or 'bar'
|
@@ -184,7 +196,7 @@ end
|
|
184
196
|
Route patterns may also include splat (or wildcard) parameters, accessible
|
185
197
|
via the `params['splat']` array:
|
186
198
|
|
187
|
-
```
|
199
|
+
```ruby
|
188
200
|
get '/say/*/to/*' do
|
189
201
|
# matches /say/hello/to/world
|
190
202
|
params['splat'] # => ["hello", "world"]
|
@@ -198,7 +210,7 @@ end
|
|
198
210
|
|
199
211
|
Or with block parameters:
|
200
212
|
|
201
|
-
```
|
213
|
+
```ruby
|
202
214
|
get '/download/*.*' do |path, ext|
|
203
215
|
[path, ext] # => ["path/to/file", "xml"]
|
204
216
|
end
|
@@ -206,15 +218,15 @@ end
|
|
206
218
|
|
207
219
|
Route matching with Regular Expressions:
|
208
220
|
|
209
|
-
```
|
210
|
-
get
|
221
|
+
```ruby
|
222
|
+
get /\/hello\/([\w]+)/ do
|
211
223
|
"Hello, #{params['captures'].first}!"
|
212
224
|
end
|
213
225
|
```
|
214
226
|
|
215
227
|
Or with a block parameter:
|
216
228
|
|
217
|
-
```
|
229
|
+
```ruby
|
218
230
|
get %r{/hello/([\w]+)} do |c|
|
219
231
|
# Matches "GET /meta/hello/world", "GET /hello/world/1234" etc.
|
220
232
|
"Hello, #{c}!"
|
@@ -223,15 +235,15 @@ end
|
|
223
235
|
|
224
236
|
Route patterns may have optional parameters:
|
225
237
|
|
226
|
-
```
|
227
|
-
get '/posts
|
228
|
-
# matches "GET /posts" and any extension "GET /posts
|
238
|
+
```ruby
|
239
|
+
get '/posts/:format?' do
|
240
|
+
# matches "GET /posts/" and any extension "GET /posts/json", "GET /posts/xml" etc
|
229
241
|
end
|
230
242
|
```
|
231
243
|
|
232
244
|
Routes may also utilize query parameters:
|
233
245
|
|
234
|
-
```
|
246
|
+
```ruby
|
235
247
|
get '/posts' do
|
236
248
|
# matches "GET /posts?title=foo&author=bar"
|
237
249
|
title = params['title']
|
@@ -240,14 +252,29 @@ get '/posts' do
|
|
240
252
|
end
|
241
253
|
```
|
242
254
|
|
243
|
-
By the way, unless you disable the path traversal attack protection (see
|
244
|
-
the request path might be modified before matching against your
|
255
|
+
By the way, unless you disable the path traversal attack protection (see
|
256
|
+
below), the request path might be modified before matching against your
|
257
|
+
routes.
|
258
|
+
|
259
|
+
You may customize the Mustermann options used for a given route by passing in a
|
260
|
+
`:mustermann_opts` hash:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
get '\A/posts\z', :mustermann_opts => { :type => :regexp, :check_anchors => false } do
|
264
|
+
# matches /posts exactly, with explicit anchoring
|
265
|
+
"If you match an anchored pattern clap your hands!"
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
It looks like a [condition](#conditions), but it isn't one! These options will
|
270
|
+
be merged into the global `:mustermann_opts` hash described
|
271
|
+
[below](#available-settings).
|
245
272
|
|
246
273
|
## Conditions
|
247
274
|
|
248
275
|
Routes may include a variety of matching conditions, such as the user agent:
|
249
276
|
|
250
|
-
```
|
277
|
+
```ruby
|
251
278
|
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
|
252
279
|
"You're using Songbird version #{params['agent'][0]}"
|
253
280
|
end
|
@@ -259,7 +286,7 @@ end
|
|
259
286
|
|
260
287
|
Other available conditions are `host_name` and `provides`:
|
261
288
|
|
262
|
-
```
|
289
|
+
```ruby
|
263
290
|
get '/', :host_name => /^admin\./ do
|
264
291
|
"Admin Area, Access denied!"
|
265
292
|
end
|
@@ -276,7 +303,7 @@ end
|
|
276
303
|
|
277
304
|
You can easily define your own conditions:
|
278
305
|
|
279
|
-
```
|
306
|
+
```ruby
|
280
307
|
set(:probability) { |value| condition { rand <= value } }
|
281
308
|
|
282
309
|
get '/win_a_car', :probability => 0.1 do
|
@@ -290,7 +317,7 @@ end
|
|
290
317
|
|
291
318
|
For a condition that takes multiple values use a splat:
|
292
319
|
|
293
|
-
```
|
320
|
+
```ruby
|
294
321
|
set(:auth) do |*roles| # <- notice the splat here
|
295
322
|
condition do
|
296
323
|
unless logged_in? && roles.any? {|role| current_user.in_role? role }
|
@@ -310,10 +337,10 @@ end
|
|
310
337
|
|
311
338
|
## Return Values
|
312
339
|
|
313
|
-
The return value of a route block determines at least the response body
|
314
|
-
on to the HTTP client, or at least the next middleware in the
|
315
|
-
Most commonly, this is a string, as in the above examples.
|
316
|
-
also accepted.
|
340
|
+
The return value of a route block determines at least the response body
|
341
|
+
passed on to the HTTP client, or at least the next middleware in the
|
342
|
+
Rack stack. Most commonly, this is a string, as in the above examples.
|
343
|
+
But other values are also accepted.
|
317
344
|
|
318
345
|
You can return any object that would either be a valid Rack response, Rack
|
319
346
|
body object or HTTP status code:
|
@@ -328,7 +355,7 @@ body object or HTTP status code:
|
|
328
355
|
|
329
356
|
That way we can, for instance, easily implement a streaming example:
|
330
357
|
|
331
|
-
```
|
358
|
+
```ruby
|
332
359
|
class Stream
|
333
360
|
def each
|
334
361
|
100.times { |i| yield "#{i}\n" }
|
@@ -338,16 +365,16 @@ end
|
|
338
365
|
get('/') { Stream.new }
|
339
366
|
```
|
340
367
|
|
341
|
-
You can also use the `stream` helper method (described below) to reduce
|
342
|
-
plate and embed the streaming logic in the route.
|
368
|
+
You can also use the `stream` helper method (described below) to reduce
|
369
|
+
boiler plate and embed the streaming logic in the route.
|
343
370
|
|
344
371
|
## Custom Route Matchers
|
345
372
|
|
346
|
-
As shown above, Sinatra ships with built-in support for using String
|
347
|
-
and regular expressions as route matches. However, it does not
|
348
|
-
can easily define your own matchers:
|
373
|
+
As shown above, Sinatra ships with built-in support for using String
|
374
|
+
patterns and regular expressions as route matches. However, it does not
|
375
|
+
stop there. You can easily define your own matchers:
|
349
376
|
|
350
|
-
```
|
377
|
+
```ruby
|
351
378
|
class AllButPattern
|
352
379
|
Match = Struct.new(:captures)
|
353
380
|
|
@@ -373,7 +400,7 @@ end
|
|
373
400
|
Note that the above example might be over-engineered, as it can also be
|
374
401
|
expressed as:
|
375
402
|
|
376
|
-
```
|
403
|
+
```ruby
|
377
404
|
get // do
|
378
405
|
pass if request.path_info == "/index"
|
379
406
|
# ...
|
@@ -382,8 +409,8 @@ end
|
|
382
409
|
|
383
410
|
Or, using negative look ahead:
|
384
411
|
|
385
|
-
```
|
386
|
-
get %r{
|
412
|
+
```ruby
|
413
|
+
get %r{(?!/index)} do
|
387
414
|
# ...
|
388
415
|
end
|
389
416
|
```
|
@@ -393,7 +420,7 @@ end
|
|
393
420
|
Static files are served from the `./public` directory. You can specify
|
394
421
|
a different location by setting the `:public_folder` option:
|
395
422
|
|
396
|
-
```
|
423
|
+
```ruby
|
397
424
|
set :public_folder, File.dirname(__FILE__) + '/static'
|
398
425
|
```
|
399
426
|
|
@@ -409,7 +436,7 @@ Use the `:static_cache_control` setting (see below) to add
|
|
409
436
|
Each template language is exposed via its own rendering method. These
|
410
437
|
methods simply return a string:
|
411
438
|
|
412
|
-
```
|
439
|
+
```ruby
|
413
440
|
get '/' do
|
414
441
|
erb :index
|
415
442
|
end
|
@@ -420,7 +447,7 @@ This renders `views/index.erb`.
|
|
420
447
|
Instead of a template name, you can also just pass in the template content
|
421
448
|
directly:
|
422
449
|
|
423
|
-
```
|
450
|
+
```ruby
|
424
451
|
get '/' do
|
425
452
|
code = "<%= Time.now %>"
|
426
453
|
erb code
|
@@ -429,7 +456,7 @@ end
|
|
429
456
|
|
430
457
|
Templates take a second argument, the options hash:
|
431
458
|
|
432
|
-
```
|
459
|
+
```ruby
|
433
460
|
get '/' do
|
434
461
|
erb :index, :layout => :post
|
435
462
|
end
|
@@ -441,7 +468,7 @@ This will render `views/index.erb` embedded in the
|
|
441
468
|
Any options not understood by Sinatra will be passed on to the template
|
442
469
|
engine:
|
443
470
|
|
444
|
-
```
|
471
|
+
```ruby
|
445
472
|
get '/' do
|
446
473
|
haml :index, :format => :html5
|
447
474
|
end
|
@@ -449,7 +476,7 @@ end
|
|
449
476
|
|
450
477
|
You can also set options per template language in general:
|
451
478
|
|
452
|
-
```
|
479
|
+
```ruby
|
453
480
|
set :haml, :format => :html5
|
454
481
|
|
455
482
|
get '/' do
|
@@ -493,15 +520,17 @@ Available Options:
|
|
493
520
|
|
494
521
|
<dt>scope</dt>
|
495
522
|
<dd>
|
496
|
-
Scope to render template under. Defaults to the application
|
497
|
-
change this, instance variables and helper methods
|
523
|
+
Scope to render template under. Defaults to the application
|
524
|
+
instance. If you change this, instance variables and helper methods
|
525
|
+
will not be available.
|
498
526
|
</dd>
|
499
527
|
|
500
528
|
<dt>layout_engine</dt>
|
501
529
|
<dd>
|
502
|
-
Template engine to use for rendering the layout. Useful for
|
503
|
-
do not support layouts otherwise. Defaults to the
|
504
|
-
template. Example: <tt>set :rdoc, :layout_engine
|
530
|
+
Template engine to use for rendering the layout. Useful for
|
531
|
+
languages that do not support layouts otherwise. Defaults to the
|
532
|
+
engine used for the template. Example: <tt>set :rdoc, :layout_engine
|
533
|
+
=> :erb</tt>
|
505
534
|
</dd>
|
506
535
|
|
507
536
|
<dt>layout_options</dt>
|
@@ -511,36 +540,44 @@ Available Options:
|
|
511
540
|
</dd>
|
512
541
|
</dl>
|
513
542
|
|
514
|
-
Templates are assumed to be located directly under the `./views`
|
515
|
-
use a different views directory:
|
543
|
+
Templates are assumed to be located directly under the `./views`
|
544
|
+
directory. To use a different views directory:
|
516
545
|
|
517
|
-
```
|
546
|
+
```ruby
|
518
547
|
set :views, settings.root + '/templates'
|
519
548
|
```
|
520
549
|
|
521
550
|
|
522
|
-
One important thing to remember is that you always have to reference
|
523
|
-
with symbols, even if they're in a subdirectory (in this case,
|
524
|
-
`:'subdir/template'` or `'subdir/template'.to_sym`). You must use a
|
525
|
-
because otherwise rendering methods will render any strings
|
526
|
-
directly.
|
551
|
+
One important thing to remember is that you always have to reference
|
552
|
+
templates with symbols, even if they're in a subdirectory (in this case,
|
553
|
+
use: `:'subdir/template'` or `'subdir/template'.to_sym`). You must use a
|
554
|
+
symbol because otherwise rendering methods will render any strings
|
555
|
+
passed to them directly.
|
527
556
|
|
528
557
|
### Literal Templates
|
529
558
|
|
530
|
-
```
|
559
|
+
```ruby
|
531
560
|
get '/' do
|
532
561
|
haml '%div.title Hello World'
|
533
562
|
end
|
534
563
|
```
|
535
564
|
|
536
|
-
Renders the template string.
|
565
|
+
Renders the template string. You can optionally specify `:path` and
|
566
|
+
`:line` for a clearer backtrace if there is a filesystem path or line
|
567
|
+
associated with that string:
|
568
|
+
|
569
|
+
```ruby
|
570
|
+
get '/' do
|
571
|
+
haml '%div.title Hello World', :path => 'examples/file.haml', :line => 3
|
572
|
+
end
|
573
|
+
```
|
537
574
|
|
538
575
|
### Available Template Languages
|
539
576
|
|
540
577
|
Some languages have multiple implementations. To specify what implementation
|
541
578
|
to use (and to be thread-safe), you should simply require it first:
|
542
579
|
|
543
|
-
```
|
580
|
+
```ruby
|
544
581
|
require 'rdiscount' # or require 'bluecloth'
|
545
582
|
get('/') { markdown :index }
|
546
583
|
```
|
@@ -608,7 +645,7 @@ It also takes a block for inline templates (see example).
|
|
608
645
|
<table>
|
609
646
|
<tr>
|
610
647
|
<td>Dependency</td>
|
611
|
-
<td><a href="http://nokogiri.org/" title="nokogiri">nokogiri</a></td>
|
648
|
+
<td><a href="http://www.nokogiri.org/" title="nokogiri">nokogiri</a></td>
|
612
649
|
</tr>
|
613
650
|
<tr>
|
614
651
|
<td>File Extension</td>
|
@@ -661,7 +698,7 @@ It also takes a block for inline templates (see example).
|
|
661
698
|
<table>
|
662
699
|
<tr>
|
663
700
|
<td>Dependency</td>
|
664
|
-
<td><a href="http://
|
701
|
+
<td><a href="http://lesscss.org/" title="less">less</a></td>
|
665
702
|
</tr>
|
666
703
|
<tr>
|
667
704
|
<td>File Extension</td>
|
@@ -678,7 +715,7 @@ It also takes a block for inline templates (see example).
|
|
678
715
|
<table>
|
679
716
|
<tr>
|
680
717
|
<td>Dependency</td>
|
681
|
-
<td><a href="http://
|
718
|
+
<td><a href="http://liquidmarkup.org/" title="liquid">liquid</a></td>
|
682
719
|
</tr>
|
683
720
|
<tr>
|
684
721
|
<td>File Extension</td>
|
@@ -700,7 +737,7 @@ template, you almost always want to pass locals to it.
|
|
700
737
|
<td>Dependency</td>
|
701
738
|
<td>
|
702
739
|
Anyone of:
|
703
|
-
<a href="https://github.com/
|
740
|
+
<a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
|
704
741
|
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
|
705
742
|
<a href="http://deveiate.org/projects/BlueCloth" title="BlueCloth">BlueCloth</a>,
|
706
743
|
<a href="http://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
|
@@ -717,17 +754,18 @@ template, you almost always want to pass locals to it.
|
|
717
754
|
</tr>
|
718
755
|
</table>
|
719
756
|
|
720
|
-
It is not possible to call methods from
|
757
|
+
It is not possible to call methods from Markdown, nor to pass locals to it.
|
721
758
|
You therefore will usually use it in combination with another rendering
|
722
759
|
engine:
|
723
760
|
|
724
|
-
```
|
761
|
+
```ruby
|
725
762
|
erb :overview, :locals => { :text => markdown(:introduction) }
|
726
763
|
```
|
727
764
|
|
728
|
-
Note that you may also call the `markdown` method from within other
|
765
|
+
Note that you may also call the `markdown` method from within other
|
766
|
+
templates:
|
729
767
|
|
730
|
-
```
|
768
|
+
```ruby
|
731
769
|
%h1 Hello From Haml!
|
732
770
|
%p= markdown(:greetings)
|
733
771
|
```
|
@@ -753,16 +791,17 @@ template than for the layout by passing the `:layout_engine` option.
|
|
753
791
|
</tr>
|
754
792
|
</table>
|
755
793
|
|
756
|
-
It is not possible to call methods from
|
757
|
-
therefore will usually use it in combination with another
|
794
|
+
It is not possible to call methods from Textile, nor to pass locals to
|
795
|
+
it. You therefore will usually use it in combination with another
|
796
|
+
rendering engine:
|
758
797
|
|
759
|
-
```
|
798
|
+
```ruby
|
760
799
|
erb :overview, :locals => { :text => textile(:introduction) }
|
761
800
|
```
|
762
801
|
|
763
802
|
Note that you may also call the `textile` method from within other templates:
|
764
803
|
|
765
|
-
```
|
804
|
+
```ruby
|
766
805
|
%h1 Hello From Haml!
|
767
806
|
%p= textile(:greetings)
|
768
807
|
```
|
@@ -788,16 +827,16 @@ template than for the layout by passing the `:layout_engine` option.
|
|
788
827
|
</tr>
|
789
828
|
</table>
|
790
829
|
|
791
|
-
It is not possible to call methods from
|
830
|
+
It is not possible to call methods from RDoc, nor to pass locals to it. You
|
792
831
|
therefore will usually use it in combination with another rendering engine:
|
793
832
|
|
794
|
-
```
|
833
|
+
```ruby
|
795
834
|
erb :overview, :locals => { :text => rdoc(:introduction) }
|
796
835
|
```
|
797
836
|
|
798
837
|
Note that you may also call the `rdoc` method from within other templates:
|
799
838
|
|
800
|
-
```
|
839
|
+
```ruby
|
801
840
|
%h1 Hello From Haml!
|
802
841
|
%p= rdoc(:greetings)
|
803
842
|
```
|
@@ -843,15 +882,15 @@ almost always want to pass locals to it.
|
|
843
882
|
</tr>
|
844
883
|
</table>
|
845
884
|
|
846
|
-
Since you cannot call Ruby methods directly from a Radius template, you
|
847
|
-
always want to pass locals to it.
|
885
|
+
Since you cannot call Ruby methods directly from a Radius template, you
|
886
|
+
almost always want to pass locals to it.
|
848
887
|
|
849
888
|
#### Markaby Templates
|
850
889
|
|
851
890
|
<table>
|
852
891
|
<tr>
|
853
892
|
<td>Dependency</td>
|
854
|
-
<td><a href="http://markaby.github.
|
893
|
+
<td><a href="http://markaby.github.io/" title="Markaby">Markaby</a></td>
|
855
894
|
</tr>
|
856
895
|
<tr>
|
857
896
|
<td>File Extension</td>
|
@@ -916,16 +955,16 @@ It also takes a block for inline templates (see example).
|
|
916
955
|
</tr>
|
917
956
|
</table>
|
918
957
|
|
919
|
-
It is not possible to call methods from
|
958
|
+
It is not possible to call methods from Creole, nor to pass locals to it. You
|
920
959
|
therefore will usually use it in combination with another rendering engine:
|
921
960
|
|
922
|
-
```
|
961
|
+
```ruby
|
923
962
|
erb :overview, :locals => { :text => creole(:introduction) }
|
924
963
|
```
|
925
964
|
|
926
965
|
Note that you may also call the `creole` method from within other templates:
|
927
966
|
|
928
|
-
```
|
967
|
+
```ruby
|
929
968
|
%h1 Hello From Haml!
|
930
969
|
%p= creole(:greetings)
|
931
970
|
```
|
@@ -951,17 +990,18 @@ template than for the layout by passing the `:layout_engine` option.
|
|
951
990
|
</tr>
|
952
991
|
</table>
|
953
992
|
|
954
|
-
It is not possible to call methods from MediaWiki markup, nor to pass
|
955
|
-
it. You therefore will usually use it in combination with
|
956
|
-
engine:
|
993
|
+
It is not possible to call methods from MediaWiki markup, nor to pass
|
994
|
+
locals to it. You therefore will usually use it in combination with
|
995
|
+
another rendering engine:
|
957
996
|
|
958
|
-
```
|
997
|
+
```ruby
|
959
998
|
erb :overview, :locals => { :text => mediawiki(:introduction) }
|
960
999
|
```
|
961
1000
|
|
962
|
-
Note that you may also call the `mediawiki` method from within other
|
1001
|
+
Note that you may also call the `mediawiki` method from within other
|
1002
|
+
templates:
|
963
1003
|
|
964
|
-
```
|
1004
|
+
```ruby
|
965
1005
|
%h1 Hello From Haml!
|
966
1006
|
%p= mediawiki(:greetings)
|
967
1007
|
```
|
@@ -1000,7 +1040,7 @@ template than for the layout by passing the `:layout_engine` option.
|
|
1000
1040
|
<tr>
|
1001
1041
|
<td>Dependency</td>
|
1002
1042
|
<td>
|
1003
|
-
<a href="https://github.com/
|
1043
|
+
<a href="https://github.com/forgecrafted/ruby-stylus" title="Ruby Stylus">
|
1004
1044
|
Stylus
|
1005
1045
|
</a> and a
|
1006
1046
|
<a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS">
|
@@ -1021,7 +1061,7 @@ template than for the layout by passing the `:layout_engine` option.
|
|
1021
1061
|
Before being able to use Stylus templates, you need to load `stylus` and
|
1022
1062
|
`stylus/tilt` first:
|
1023
1063
|
|
1024
|
-
```
|
1064
|
+
```ruby
|
1025
1065
|
require 'sinatra'
|
1026
1066
|
require 'stylus'
|
1027
1067
|
require 'stylus/tilt'
|
@@ -1059,7 +1099,7 @@ end
|
|
1059
1099
|
The template source is evaluated as a Ruby string, and the
|
1060
1100
|
resulting json variable is converted using `#to_json`:
|
1061
1101
|
|
1062
|
-
```
|
1102
|
+
```ruby
|
1063
1103
|
json = { :foo => 'bar' }
|
1064
1104
|
json[:baz] = key
|
1065
1105
|
```
|
@@ -1067,7 +1107,7 @@ json[:baz] = key
|
|
1067
1107
|
The `:callback` and `:variable` options can be used to decorate the rendered
|
1068
1108
|
object:
|
1069
1109
|
|
1070
|
-
```
|
1110
|
+
```javascript
|
1071
1111
|
var resource = {"foo":"bar","baz":"qux"};
|
1072
1112
|
present(resource);
|
1073
1113
|
```
|
@@ -1089,15 +1129,16 @@ present(resource);
|
|
1089
1129
|
</tr>
|
1090
1130
|
</table>
|
1091
1131
|
|
1092
|
-
Since calling ruby methods is not idiomatic in WLang, you almost always
|
1093
|
-
pass locals to it. Layouts written in WLang and `yield` are
|
1132
|
+
Since calling ruby methods is not idiomatic in WLang, you almost always
|
1133
|
+
want to pass locals to it. Layouts written in WLang and `yield` are
|
1134
|
+
supported, though.
|
1094
1135
|
|
1095
1136
|
### Accessing Variables in Templates
|
1096
1137
|
|
1097
1138
|
Templates are evaluated within the same context as route handlers. Instance
|
1098
1139
|
variables set in route handlers are directly accessible by templates:
|
1099
1140
|
|
1100
|
-
```
|
1141
|
+
```ruby
|
1101
1142
|
get '/:id' do
|
1102
1143
|
@foo = Foo.find(params['id'])
|
1103
1144
|
haml '%h1= @foo.name'
|
@@ -1106,7 +1147,7 @@ end
|
|
1106
1147
|
|
1107
1148
|
Or, specify an explicit Hash of local variables:
|
1108
1149
|
|
1109
|
-
```
|
1150
|
+
```ruby
|
1110
1151
|
get '/:id' do
|
1111
1152
|
foo = Foo.find(params['id'])
|
1112
1153
|
haml '%h1= bar.name', :locals => { :bar => foo }
|
@@ -1122,7 +1163,7 @@ A layout is usually just a template that calls `yield`.
|
|
1122
1163
|
Such a template can be used either through the `:template` option as
|
1123
1164
|
described above, or it can be rendered with a block as follows:
|
1124
1165
|
|
1125
|
-
```
|
1166
|
+
```ruby
|
1126
1167
|
erb :post, :layout => false do
|
1127
1168
|
erb :index
|
1128
1169
|
end
|
@@ -1130,9 +1171,10 @@ end
|
|
1130
1171
|
|
1131
1172
|
This code is mostly equivalent to `erb :index, :layout => :post`.
|
1132
1173
|
|
1133
|
-
Passing blocks to rendering methods is most useful for creating nested
|
1174
|
+
Passing blocks to rendering methods is most useful for creating nested
|
1175
|
+
layouts:
|
1134
1176
|
|
1135
|
-
```
|
1177
|
+
```ruby
|
1136
1178
|
erb :main_layout, :layout => false do
|
1137
1179
|
erb :admin_layout do
|
1138
1180
|
erb :user
|
@@ -1142,7 +1184,7 @@ end
|
|
1142
1184
|
|
1143
1185
|
This can also be done in fewer lines of code with:
|
1144
1186
|
|
1145
|
-
```
|
1187
|
+
```ruby
|
1146
1188
|
erb :admin_layout, :layout => :main_layout do
|
1147
1189
|
erb :user
|
1148
1190
|
end
|
@@ -1155,7 +1197,7 @@ Currently, the following rendering methods accept a block: `erb`, `haml`,
|
|
1155
1197
|
|
1156
1198
|
Templates may be defined at the end of the source file:
|
1157
1199
|
|
1158
|
-
```
|
1200
|
+
```ruby
|
1159
1201
|
require 'sinatra'
|
1160
1202
|
|
1161
1203
|
get '/' do
|
@@ -1180,7 +1222,7 @@ have inline templates in other source files.
|
|
1180
1222
|
|
1181
1223
|
Templates may also be defined using the top-level `template` method:
|
1182
1224
|
|
1183
|
-
```
|
1225
|
+
```ruby
|
1184
1226
|
template :layout do
|
1185
1227
|
"%html\n =yield\n"
|
1186
1228
|
end
|
@@ -1199,7 +1241,7 @@ is rendered. You can individually disable layouts by passing
|
|
1199
1241
|
`:layout => false` or disable them by default via
|
1200
1242
|
`set :haml, :layout => false`:
|
1201
1243
|
|
1202
|
-
```
|
1244
|
+
```ruby
|
1203
1245
|
get '/' do
|
1204
1246
|
haml :index, :layout => !request.xhr?
|
1205
1247
|
end
|
@@ -1211,7 +1253,7 @@ To associate a file extension with a template engine, use
|
|
1211
1253
|
`Tilt.register`. For instance, if you like to use the file extension
|
1212
1254
|
`tt` for Textile templates, you can do the following:
|
1213
1255
|
|
1214
|
-
```
|
1256
|
+
```ruby
|
1215
1257
|
Tilt.register :tt, Tilt[:textile]
|
1216
1258
|
```
|
1217
1259
|
|
@@ -1219,7 +1261,7 @@ Tilt.register :tt, Tilt[:textile]
|
|
1219
1261
|
|
1220
1262
|
First, register your engine with Tilt, then create a rendering method:
|
1221
1263
|
|
1222
|
-
```
|
1264
|
+
```ruby
|
1223
1265
|
Tilt.register :myat, MyAwesomeTemplateEngine
|
1224
1266
|
|
1225
1267
|
helpers do
|
@@ -1239,7 +1281,7 @@ learn more about Tilt.
|
|
1239
1281
|
To implement your own template lookup mechanism you can write your
|
1240
1282
|
own `#find_template` method:
|
1241
1283
|
|
1242
|
-
```
|
1284
|
+
```ruby
|
1243
1285
|
configure do
|
1244
1286
|
set :views [ './views/a', './views/b' ]
|
1245
1287
|
end
|
@@ -1253,11 +1295,11 @@ end
|
|
1253
1295
|
|
1254
1296
|
## Filters
|
1255
1297
|
|
1256
|
-
Before filters are evaluated before each request within the same
|
1257
|
-
|
1298
|
+
Before filters are evaluated before each request within the same context
|
1299
|
+
as the routes will be and can modify the request and response. Instance
|
1258
1300
|
variables set in filters are accessible by routes and templates:
|
1259
1301
|
|
1260
|
-
```
|
1302
|
+
```ruby
|
1261
1303
|
before do
|
1262
1304
|
@note = 'Hi!'
|
1263
1305
|
request.path_info = '/foo/bar/baz'
|
@@ -1269,24 +1311,25 @@ get '/foo/*' do
|
|
1269
1311
|
end
|
1270
1312
|
```
|
1271
1313
|
|
1272
|
-
After filters are evaluated after each request within the same context
|
1273
|
-
routes will be and can also modify the request and response.
|
1274
|
-
set in before filters and routes are accessible by
|
1314
|
+
After filters are evaluated after each request within the same context
|
1315
|
+
as the routes will be and can also modify the request and response.
|
1316
|
+
Instance variables set in before filters and routes are accessible by
|
1317
|
+
after filters:
|
1275
1318
|
|
1276
|
-
```
|
1319
|
+
```ruby
|
1277
1320
|
after do
|
1278
1321
|
puts response.status
|
1279
1322
|
end
|
1280
1323
|
```
|
1281
1324
|
|
1282
|
-
Note: Unless you use the `body` method rather than just returning a
|
1283
|
-
the routes, the body will not yet be available in the after
|
1284
|
-
generated later on.
|
1325
|
+
Note: Unless you use the `body` method rather than just returning a
|
1326
|
+
String from the routes, the body will not yet be available in the after
|
1327
|
+
filter, since it is generated later on.
|
1285
1328
|
|
1286
1329
|
Filters optionally take a pattern, causing them to be evaluated only if the
|
1287
1330
|
request path matches that pattern:
|
1288
1331
|
|
1289
|
-
```
|
1332
|
+
```ruby
|
1290
1333
|
before '/protected/*' do
|
1291
1334
|
authenticate!
|
1292
1335
|
end
|
@@ -1298,7 +1341,7 @@ end
|
|
1298
1341
|
|
1299
1342
|
Like routes, filters also take conditions:
|
1300
1343
|
|
1301
|
-
```
|
1344
|
+
```ruby
|
1302
1345
|
before :agent => /Songbird/ do
|
1303
1346
|
# ...
|
1304
1347
|
end
|
@@ -1313,7 +1356,7 @@ end
|
|
1313
1356
|
Use the top-level `helpers` method to define helper methods for use in
|
1314
1357
|
route handlers and templates:
|
1315
1358
|
|
1316
|
-
```
|
1359
|
+
```ruby
|
1317
1360
|
helpers do
|
1318
1361
|
def bar(name)
|
1319
1362
|
"#{name}bar"
|
@@ -1327,7 +1370,7 @@ end
|
|
1327
1370
|
|
1328
1371
|
Alternatively, helper methods can be separately defined in a module:
|
1329
1372
|
|
1330
|
-
```
|
1373
|
+
```ruby
|
1331
1374
|
module FooUtils
|
1332
1375
|
def foo(name) "#{name}foo" end
|
1333
1376
|
end
|
@@ -1346,7 +1389,7 @@ The effect is the same as including the modules in the application class.
|
|
1346
1389
|
A session is used to keep state during requests. If activated, you have one
|
1347
1390
|
session hash per user session:
|
1348
1391
|
|
1349
|
-
```
|
1392
|
+
```ruby
|
1350
1393
|
enable :sessions
|
1351
1394
|
|
1352
1395
|
get '/' do
|
@@ -1358,82 +1401,165 @@ get '/:value' do
|
|
1358
1401
|
end
|
1359
1402
|
```
|
1360
1403
|
|
1361
|
-
|
1362
|
-
might not always be what you want (storing lots of data will increase your
|
1363
|
-
traffic, for instance). You can use any Rack session middleware: in order to
|
1364
|
-
do so, do **not** call `enable :sessions`, but instead pull in your
|
1365
|
-
middleware of choice as you would any other middleware:
|
1404
|
+
#### Session Secret Security
|
1366
1405
|
|
1367
|
-
|
1368
|
-
|
1406
|
+
To improve security, the session data in the cookie is signed with a session
|
1407
|
+
secret using `HMAC-SHA1`. This session secret should optimally be a
|
1408
|
+
cryptographically secure random value of an appropriate length which for
|
1409
|
+
`HMAC-SHA1` is greater than or equal to 64 bytes (512 bits, 128 hex
|
1410
|
+
characters). You would be advised not to use a secret that is less than 32
|
1411
|
+
bytes of randomness (256 bits, 64 hex characters). It is therefore **very
|
1412
|
+
important** that you don't just make the secret up, but instead use a secure
|
1413
|
+
random number generator to create it. Humans are extremely bad at generating
|
1414
|
+
random values.
|
1369
1415
|
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1416
|
+
By default, a 32 byte secure random session secret is generated for you by
|
1417
|
+
Sinatra, but it will change with every restart of your application. If you
|
1418
|
+
have multiple instances of your application, and you let Sinatra generate the
|
1419
|
+
key, each instance would then have a different session key which is probably
|
1420
|
+
not what you want.
|
1373
1421
|
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1422
|
+
For better security and usability it's
|
1423
|
+
[recommended](https://12factor.net/config) that you generate a secure random
|
1424
|
+
secret and store it in an environment variable on each host running your
|
1425
|
+
application so that all of your application instances will share the same
|
1426
|
+
secret. You should periodically rotate this session secret to a new value.
|
1427
|
+
Here are some examples of how you might create a 64 byte secret and set it:
|
1428
|
+
|
1429
|
+
**Session Secret Generation**
|
1430
|
+
|
1431
|
+
```text
|
1432
|
+
$ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
|
1433
|
+
99ae8af...snip...ec0f262ac
|
1377
1434
|
```
|
1378
1435
|
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1436
|
+
**Session Secret Generation (Bonus Points)**
|
1437
|
+
|
1438
|
+
Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom) to prefer
|
1439
|
+
use of system RNG facilities to generate random values instead of
|
1440
|
+
userspace `OpenSSL` which MRI Ruby currently defaults to:
|
1441
|
+
|
1442
|
+
```text
|
1443
|
+
$ gem install sysrandom
|
1444
|
+
Building native extensions. This could take a while...
|
1445
|
+
Successfully installed sysrandom-1.x
|
1446
|
+
1 gem installed
|
1447
|
+
|
1448
|
+
$ ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
|
1449
|
+
99ae8af...snip...ec0f262ac
|
1450
|
+
```
|
1451
|
+
|
1452
|
+
**Session Secret Environment Variable**
|
1453
|
+
|
1454
|
+
Set a `SESSION_SECRET` environment variable for Sinatra to the value you
|
1455
|
+
generated. Make this value persistent across reboots of your host. Since the
|
1456
|
+
method for doing this will vary across systems this is for illustrative
|
1457
|
+
purposes only:
|
1458
|
+
|
1459
|
+
```bash
|
1460
|
+
# echo "export SESSION_SECRET=99ae8af...snip...ec0f262ac" >> ~/.bashrc
|
1461
|
+
```
|
1462
|
+
|
1463
|
+
**Session Secret App Config**
|
1464
|
+
|
1465
|
+
Setup your app config to fail-safe to a secure random secret
|
1466
|
+
if the `SESSION_SECRET` environment variable is not available.
|
1383
1467
|
|
1384
|
-
|
1385
|
-
|
1468
|
+
For bonus points use the [sysrandom
|
1469
|
+
gem](https://github.com/cryptosphere/sysrandom) here as well:
|
1470
|
+
|
1471
|
+
```ruby
|
1472
|
+
require 'securerandom'
|
1473
|
+
# -or- require 'sysrandom/securerandom'
|
1474
|
+
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
|
1386
1475
|
```
|
1387
1476
|
|
1388
|
-
|
1389
|
-
|
1477
|
+
#### Session Config
|
1478
|
+
|
1479
|
+
If you want to configure it further, you may also store a hash with options
|
1480
|
+
in the `sessions` setting:
|
1390
1481
|
|
1391
|
-
```
|
1482
|
+
```ruby
|
1392
1483
|
set :sessions, :domain => 'foo.com'
|
1393
1484
|
```
|
1394
1485
|
|
1395
1486
|
To share your session across other apps on subdomains of foo.com, prefix the
|
1396
1487
|
domain with a *.* like this instead:
|
1397
1488
|
|
1398
|
-
```
|
1489
|
+
```ruby
|
1399
1490
|
set :sessions, :domain => '.foo.com'
|
1400
1491
|
```
|
1401
1492
|
|
1493
|
+
#### Choosing Your Own Session Middleware
|
1494
|
+
|
1495
|
+
Note that `enable :sessions` actually stores all data in a cookie. This
|
1496
|
+
might not always be what you want (storing lots of data will increase your
|
1497
|
+
traffic, for instance). You can use any Rack session middleware in order to
|
1498
|
+
do so, one of the following methods can be used:
|
1499
|
+
|
1500
|
+
```ruby
|
1501
|
+
enable :sessions
|
1502
|
+
set :session_store, Rack::Session::Pool
|
1503
|
+
```
|
1504
|
+
|
1505
|
+
Or to set up sessions with a hash of options:
|
1506
|
+
|
1507
|
+
```ruby
|
1508
|
+
set :sessions, :expire_after => 2592000
|
1509
|
+
set :session_store, Rack::Session::Pool
|
1510
|
+
```
|
1511
|
+
|
1512
|
+
Another option is to **not** call `enable :sessions`, but instead pull in
|
1513
|
+
your middleware of choice as you would any other middleware.
|
1514
|
+
|
1515
|
+
It is important to note that when using this method, session based
|
1516
|
+
protection **will not be enabled by default**.
|
1517
|
+
|
1518
|
+
The Rack middleware to do that will also need to be added:
|
1519
|
+
|
1520
|
+
```ruby
|
1521
|
+
use Rack::Session::Pool, :expire_after => 2592000
|
1522
|
+
use Rack::Protection::RemoteToken
|
1523
|
+
use Rack::Protection::SessionHijacking
|
1524
|
+
```
|
1525
|
+
|
1526
|
+
See 'Configuring attack protection' for more information.
|
1527
|
+
|
1402
1528
|
### Halting
|
1403
1529
|
|
1404
1530
|
To immediately stop a request within a filter or route use:
|
1405
1531
|
|
1406
|
-
```
|
1532
|
+
```ruby
|
1407
1533
|
halt
|
1408
1534
|
```
|
1409
1535
|
|
1410
1536
|
You can also specify the status when halting:
|
1411
1537
|
|
1412
|
-
```
|
1538
|
+
```ruby
|
1413
1539
|
halt 410
|
1414
1540
|
```
|
1415
1541
|
|
1416
1542
|
Or the body:
|
1417
1543
|
|
1418
|
-
```
|
1544
|
+
```ruby
|
1419
1545
|
halt 'this will be the body'
|
1420
1546
|
```
|
1421
1547
|
|
1422
1548
|
Or both:
|
1423
1549
|
|
1424
|
-
```
|
1550
|
+
```ruby
|
1425
1551
|
halt 401, 'go away!'
|
1426
1552
|
```
|
1427
1553
|
|
1428
1554
|
With headers:
|
1429
1555
|
|
1430
|
-
```
|
1556
|
+
```ruby
|
1431
1557
|
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
|
1432
1558
|
```
|
1433
1559
|
|
1434
1560
|
It is of course possible to combine a template with `halt`:
|
1435
1561
|
|
1436
|
-
```
|
1562
|
+
```ruby
|
1437
1563
|
halt erb(:error)
|
1438
1564
|
```
|
1439
1565
|
|
@@ -1441,7 +1567,7 @@ halt erb(:error)
|
|
1441
1567
|
|
1442
1568
|
A route can punt processing to the next matching route using `pass`:
|
1443
1569
|
|
1444
|
-
```
|
1570
|
+
```ruby
|
1445
1571
|
get '/guess/:who' do
|
1446
1572
|
pass unless params['who'] == 'Frank'
|
1447
1573
|
'You got me!'
|
@@ -1457,10 +1583,10 @@ matching route. If no matching route is found, a 404 is returned.
|
|
1457
1583
|
|
1458
1584
|
### Triggering Another Route
|
1459
1585
|
|
1460
|
-
Sometimes `pass` is not what you want, instead you would like to get the
|
1461
|
-
of calling another route. Simply use `call` to achieve this:
|
1586
|
+
Sometimes `pass` is not what you want, instead you would like to get the
|
1587
|
+
result of calling another route. Simply use `call` to achieve this:
|
1462
1588
|
|
1463
|
-
```
|
1589
|
+
```ruby
|
1464
1590
|
get '/foo' do
|
1465
1591
|
status, headers, body = call env.merge("PATH_INFO" => '/bar')
|
1466
1592
|
[status, headers, body.map(&:upcase)]
|
@@ -1471,23 +1597,24 @@ get '/bar' do
|
|
1471
1597
|
end
|
1472
1598
|
```
|
1473
1599
|
|
1474
|
-
Note that in the example above, you would ease testing and increase
|
1475
|
-
by simply moving `"bar"` into a helper used by both `/foo` and
|
1600
|
+
Note that in the example above, you would ease testing and increase
|
1601
|
+
performance by simply moving `"bar"` into a helper used by both `/foo` and
|
1602
|
+
`/bar`.
|
1476
1603
|
|
1477
|
-
If you want the request to be sent to the same application instance rather
|
1478
|
-
a duplicate, use `call!` instead of `call`.
|
1604
|
+
If you want the request to be sent to the same application instance rather
|
1605
|
+
than a duplicate, use `call!` instead of `call`.
|
1479
1606
|
|
1480
1607
|
Check out the Rack specification if you want to learn more about `call`.
|
1481
1608
|
|
1482
1609
|
### Setting Body, Status Code and Headers
|
1483
1610
|
|
1484
|
-
It is possible and recommended to set the status code and response body with
|
1485
|
-
return value of the route block. However, in some scenarios you might
|
1486
|
-
set the body at an arbitrary point in the execution flow. You can do
|
1487
|
-
`body` helper method. If you do so, you can use that method from
|
1488
|
-
access the body:
|
1611
|
+
It is possible and recommended to set the status code and response body with
|
1612
|
+
the return value of the route block. However, in some scenarios you might
|
1613
|
+
want to set the body at an arbitrary point in the execution flow. You can do
|
1614
|
+
so with the `body` helper method. If you do so, you can use that method from
|
1615
|
+
there on to access the body:
|
1489
1616
|
|
1490
|
-
```
|
1617
|
+
```ruby
|
1491
1618
|
get '/foo' do
|
1492
1619
|
body "bar"
|
1493
1620
|
end
|
@@ -1502,7 +1629,7 @@ Rack handler (this can be used to implement streaming, see "Return Values").
|
|
1502
1629
|
|
1503
1630
|
Similar to the body, you can also set the status code and headers:
|
1504
1631
|
|
1505
|
-
```
|
1632
|
+
```ruby
|
1506
1633
|
get '/foo' do
|
1507
1634
|
status 418
|
1508
1635
|
headers \
|
@@ -1522,7 +1649,7 @@ the response body. In extreme examples, you want to keep sending data until
|
|
1522
1649
|
the client closes the connection. You can use the `stream` helper to avoid
|
1523
1650
|
creating your own wrapper:
|
1524
1651
|
|
1525
|
-
```
|
1652
|
+
```ruby
|
1526
1653
|
get '/' do
|
1527
1654
|
stream do |out|
|
1528
1655
|
out << "It's gonna be legen -\n"
|
@@ -1535,23 +1662,23 @@ end
|
|
1535
1662
|
```
|
1536
1663
|
|
1537
1664
|
This allows you to implement streaming APIs,
|
1538
|
-
[Server Sent Events](
|
1539
|
-
the basis for [WebSockets](
|
1540
|
-
used to increase throughput if some but not all content depends on a
|
1541
|
-
resource.
|
1665
|
+
[Server Sent Events](https://w3c.github.io/eventsource/), and can be used as
|
1666
|
+
the basis for [WebSockets](https://en.wikipedia.org/wiki/WebSocket). It can
|
1667
|
+
also be used to increase throughput if some but not all content depends on a
|
1668
|
+
slow resource.
|
1542
1669
|
|
1543
|
-
Note that the streaming behavior, especially the number of concurrent
|
1544
|
-
highly depends on the web server used to serve the application.
|
1545
|
-
|
1546
|
-
support streaming, the body will be sent all at once after the block passed
|
1547
|
-
`stream` finishes executing. Streaming does not work at all with Shotgun.
|
1670
|
+
Note that the streaming behavior, especially the number of concurrent
|
1671
|
+
requests, highly depends on the web server used to serve the application.
|
1672
|
+
Some servers might not even support streaming at all. If the server does not
|
1673
|
+
support streaming, the body will be sent all at once after the block passed
|
1674
|
+
to `stream` finishes executing. Streaming does not work at all with Shotgun.
|
1548
1675
|
|
1549
1676
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
1550
1677
|
the stream object, allowing you to close it at any later point in the
|
1551
1678
|
execution flow. This only works on evented servers, like Thin and Rainbows.
|
1552
1679
|
Other servers will still close the stream:
|
1553
1680
|
|
1554
|
-
```
|
1681
|
+
```ruby
|
1555
1682
|
# long polling
|
1556
1683
|
|
1557
1684
|
set :server, :thin
|
@@ -1580,11 +1707,15 @@ post '/:message' do
|
|
1580
1707
|
end
|
1581
1708
|
```
|
1582
1709
|
|
1710
|
+
It's also possible for the client to close the connection when trying to
|
1711
|
+
write to the socket. Because of this, it's recommended to check
|
1712
|
+
`out.closed?` before trying to write.
|
1713
|
+
|
1583
1714
|
### Logging
|
1584
1715
|
|
1585
1716
|
In the request scope, the `logger` helper exposes a `Logger` instance:
|
1586
1717
|
|
1587
|
-
```
|
1718
|
+
```ruby
|
1588
1719
|
get '/' do
|
1589
1720
|
logger.info "loading data"
|
1590
1721
|
# ...
|
@@ -1595,10 +1726,10 @@ This logger will automatically take your Rack handler's logging settings into
|
|
1595
1726
|
account. If logging is disabled, this method will return a dummy object, so
|
1596
1727
|
you do not have to worry about it in your routes and filters.
|
1597
1728
|
|
1598
|
-
Note that logging is only enabled for `Sinatra::Application` by default, so
|
1599
|
-
you inherit from `Sinatra::Base`, you probably want to enable it yourself:
|
1729
|
+
Note that logging is only enabled for `Sinatra::Application` by default, so
|
1730
|
+
if you inherit from `Sinatra::Base`, you probably want to enable it yourself:
|
1600
1731
|
|
1601
|
-
```
|
1732
|
+
```ruby
|
1602
1733
|
class MyApp < Sinatra::Base
|
1603
1734
|
configure :production, :development do
|
1604
1735
|
enable :logging
|
@@ -1616,7 +1747,7 @@ whatever it will find in `env['rack.logger']`.
|
|
1616
1747
|
When using `send_file` or static files you may have mime types Sinatra
|
1617
1748
|
doesn't understand. Use `mime_type` to register them by file extension:
|
1618
1749
|
|
1619
|
-
```
|
1750
|
+
```ruby
|
1620
1751
|
configure do
|
1621
1752
|
mime_type :foo, 'text/foo'
|
1622
1753
|
end
|
@@ -1624,7 +1755,7 @@ end
|
|
1624
1755
|
|
1625
1756
|
You can also use it with the `content_type` helper:
|
1626
1757
|
|
1627
|
-
```
|
1758
|
+
```ruby
|
1628
1759
|
get '/' do
|
1629
1760
|
content_type :foo
|
1630
1761
|
"foo foo foo"
|
@@ -1636,7 +1767,7 @@ end
|
|
1636
1767
|
For generating URLs you should use the `url` helper method, for instance, in
|
1637
1768
|
Haml:
|
1638
1769
|
|
1639
|
-
```
|
1770
|
+
```ruby
|
1640
1771
|
%a{:href => url('/foo')} foo
|
1641
1772
|
```
|
1642
1773
|
|
@@ -1648,7 +1779,7 @@ This method is also aliased to `to` (see below for an example).
|
|
1648
1779
|
|
1649
1780
|
You can trigger a browser redirect with the `redirect` helper method:
|
1650
1781
|
|
1651
|
-
```
|
1782
|
+
```ruby
|
1652
1783
|
get '/foo' do
|
1653
1784
|
redirect to('/bar')
|
1654
1785
|
end
|
@@ -1656,15 +1787,15 @@ end
|
|
1656
1787
|
|
1657
1788
|
Any additional parameters are handled like arguments passed to `halt`:
|
1658
1789
|
|
1659
|
-
```
|
1790
|
+
```ruby
|
1660
1791
|
redirect to('/bar'), 303
|
1661
|
-
redirect 'http://google.com', 'wrong place, buddy'
|
1792
|
+
redirect 'http://www.google.com/', 'wrong place, buddy'
|
1662
1793
|
```
|
1663
1794
|
|
1664
1795
|
You can also easily redirect back to the page the user came from with
|
1665
1796
|
`redirect back`:
|
1666
1797
|
|
1667
|
-
```
|
1798
|
+
```ruby
|
1668
1799
|
get '/foo' do
|
1669
1800
|
"<a href='/bar'>do something</a>"
|
1670
1801
|
end
|
@@ -1677,13 +1808,13 @@ end
|
|
1677
1808
|
|
1678
1809
|
To pass arguments with a redirect, either add them to the query:
|
1679
1810
|
|
1680
|
-
```
|
1811
|
+
```ruby
|
1681
1812
|
redirect to('/bar?sum=42')
|
1682
1813
|
```
|
1683
1814
|
|
1684
1815
|
Or use a session:
|
1685
1816
|
|
1686
|
-
```
|
1817
|
+
```ruby
|
1687
1818
|
enable :sessions
|
1688
1819
|
|
1689
1820
|
get '/foo' do
|
@@ -1702,7 +1833,7 @@ Setting your headers correctly is the foundation for proper HTTP caching.
|
|
1702
1833
|
|
1703
1834
|
You can easily set the Cache-Control header like this:
|
1704
1835
|
|
1705
|
-
```
|
1836
|
+
```ruby
|
1706
1837
|
get '/' do
|
1707
1838
|
cache_control :public
|
1708
1839
|
"cache it!"
|
@@ -1711,7 +1842,7 @@ end
|
|
1711
1842
|
|
1712
1843
|
Pro tip: Set up caching in a before filter:
|
1713
1844
|
|
1714
|
-
```
|
1845
|
+
```ruby
|
1715
1846
|
before do
|
1716
1847
|
cache_control :public, :must_revalidate, :max_age => 60
|
1717
1848
|
end
|
@@ -1720,7 +1851,7 @@ end
|
|
1720
1851
|
If you are using the `expires` helper to set the corresponding header,
|
1721
1852
|
`Cache-Control` will be set automatically for you:
|
1722
1853
|
|
1723
|
-
```
|
1854
|
+
```ruby
|
1724
1855
|
before do
|
1725
1856
|
expires 500, :public, :must_revalidate
|
1726
1857
|
end
|
@@ -1731,7 +1862,7 @@ It is recommended to call those helpers *before* doing any heavy lifting, as
|
|
1731
1862
|
they will immediately flush a response if the client already has the current
|
1732
1863
|
version in its cache:
|
1733
1864
|
|
1734
|
-
```
|
1865
|
+
```ruby
|
1735
1866
|
get "/article/:id" do
|
1736
1867
|
@article = Article.find params['id']
|
1737
1868
|
last_modified @article.updated_at
|
@@ -1741,17 +1872,18 @@ end
|
|
1741
1872
|
```
|
1742
1873
|
|
1743
1874
|
It is also possible to use a
|
1744
|
-
[weak ETag](
|
1875
|
+
[weak ETag](https://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation):
|
1745
1876
|
|
1746
|
-
```
|
1877
|
+
```ruby
|
1747
1878
|
etag @article.sha1, :weak
|
1748
1879
|
```
|
1749
1880
|
|
1750
1881
|
These helpers will not do any caching for you, but rather feed the necessary
|
1751
|
-
information to your cache. If you are looking for a quick
|
1752
|
-
solution, try
|
1882
|
+
information to your cache. If you are looking for a quick
|
1883
|
+
reverse-proxy caching solution, try
|
1884
|
+
[rack-cache](https://github.com/rtomayko/rack-cache):
|
1753
1885
|
|
1754
|
-
```
|
1886
|
+
```ruby
|
1755
1887
|
require "rack/cache"
|
1756
1888
|
require "sinatra"
|
1757
1889
|
|
@@ -1767,14 +1899,15 @@ end
|
|
1767
1899
|
Use the `:static_cache_control` setting (see below) to add
|
1768
1900
|
`Cache-Control` header info to static files.
|
1769
1901
|
|
1770
|
-
According to RFC 2616, your application should behave differently if the
|
1771
|
-
or If-None-Match header is set to `*`, depending on whether the
|
1772
|
-
requested is already in existence. Sinatra assumes resources for
|
1773
|
-
and idempotent (like put) requests are already in existence,
|
1774
|
-
resources (for instance post requests) are treated as new
|
1775
|
-
can change this behavior by passing in a `:new_resource`
|
1902
|
+
According to RFC 2616, your application should behave differently if the
|
1903
|
+
If-Match or If-None-Match header is set to `*`, depending on whether the
|
1904
|
+
resource requested is already in existence. Sinatra assumes resources for
|
1905
|
+
safe (like get) and idempotent (like put) requests are already in existence,
|
1906
|
+
whereas other resources (for instance post requests) are treated as new
|
1907
|
+
resources. You can change this behavior by passing in a `:new_resource`
|
1908
|
+
option:
|
1776
1909
|
|
1777
|
-
```
|
1910
|
+
```ruby
|
1778
1911
|
get '/create' do
|
1779
1912
|
etag '', :new_resource => true
|
1780
1913
|
Article.create
|
@@ -1784,7 +1917,7 @@ end
|
|
1784
1917
|
|
1785
1918
|
If you still want to use a weak ETag, pass in a `:kind` option:
|
1786
1919
|
|
1787
|
-
```
|
1920
|
+
```ruby
|
1788
1921
|
etag '', :new_resource => true, :kind => :weak
|
1789
1922
|
```
|
1790
1923
|
|
@@ -1793,7 +1926,7 @@ etag '', :new_resource => true, :kind => :weak
|
|
1793
1926
|
To return the contents of a file as the response, you can use the `send_file`
|
1794
1927
|
helper method:
|
1795
1928
|
|
1796
|
-
```
|
1929
|
+
```ruby
|
1797
1930
|
get '/' do
|
1798
1931
|
send_file 'foo.png'
|
1799
1932
|
end
|
@@ -1801,7 +1934,7 @@ end
|
|
1801
1934
|
|
1802
1935
|
It also takes options:
|
1803
1936
|
|
1804
|
-
```
|
1937
|
+
```ruby
|
1805
1938
|
send_file 'foo.png', :type => :jpg
|
1806
1939
|
```
|
1807
1940
|
|
@@ -1809,8 +1942,8 @@ The options are:
|
|
1809
1942
|
|
1810
1943
|
<dl>
|
1811
1944
|
<dt>filename</dt>
|
1812
|
-
<dd>File name to be used in the response,
|
1813
|
-
|
1945
|
+
<dd>File name to be used in the response,
|
1946
|
+
defaults to the real file name.</dd>
|
1814
1947
|
<dt>last_modified</dt>
|
1815
1948
|
<dd>Value for Last-Modified header, defaults to the file's mtime.</dd>
|
1816
1949
|
|
@@ -1829,20 +1962,19 @@ The options are:
|
|
1829
1962
|
|
1830
1963
|
<dt>status</dt>
|
1831
1964
|
<dd>
|
1832
|
-
Status code to be sent. Useful when sending a static file as an error
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
automatically handle range requests.
|
1965
|
+
Status code to be sent. Useful when sending a static file as an error
|
1966
|
+
page. If supported by the Rack handler, other means than streaming
|
1967
|
+
from the Ruby process will be used. If you use this helper method,
|
1968
|
+
Sinatra will automatically handle range requests.
|
1837
1969
|
</dd>
|
1838
1970
|
</dl>
|
1839
1971
|
|
1840
1972
|
### Accessing the Request Object
|
1841
1973
|
|
1842
|
-
The incoming request object can be accessed from request level (filter,
|
1843
|
-
error handlers) through the `request` method:
|
1974
|
+
The incoming request object can be accessed from request level (filter,
|
1975
|
+
routes, error handlers) through the `request` method:
|
1844
1976
|
|
1845
|
-
```
|
1977
|
+
```ruby
|
1846
1978
|
# app running on http://example.com/example
|
1847
1979
|
get '/foo' do
|
1848
1980
|
t = %w[text/css text/html application/javascript]
|
@@ -1877,7 +2009,7 @@ end
|
|
1877
2009
|
|
1878
2010
|
Some options, like `script_name` or `path_info`, can also be written:
|
1879
2011
|
|
1880
|
-
```
|
2012
|
+
```ruby
|
1881
2013
|
before { request.path_info = "/" }
|
1882
2014
|
|
1883
2015
|
get "/" do
|
@@ -1887,7 +2019,7 @@ end
|
|
1887
2019
|
|
1888
2020
|
The `request.body` is an IO or StringIO object:
|
1889
2021
|
|
1890
|
-
```
|
2022
|
+
```ruby
|
1891
2023
|
post "/api" do
|
1892
2024
|
request.body.rewind # in case someone already read it
|
1893
2025
|
data = JSON.parse request.body.read
|
@@ -1897,10 +2029,10 @@ end
|
|
1897
2029
|
|
1898
2030
|
### Attachments
|
1899
2031
|
|
1900
|
-
You can use the `attachment` helper to tell the browser the response should
|
1901
|
-
stored on disk rather than displayed in the browser:
|
2032
|
+
You can use the `attachment` helper to tell the browser the response should
|
2033
|
+
be stored on disk rather than displayed in the browser:
|
1902
2034
|
|
1903
|
-
```
|
2035
|
+
```ruby
|
1904
2036
|
get '/' do
|
1905
2037
|
attachment
|
1906
2038
|
"store it!"
|
@@ -1909,7 +2041,7 @@ end
|
|
1909
2041
|
|
1910
2042
|
You can also pass it a file name:
|
1911
2043
|
|
1912
|
-
```
|
2044
|
+
```ruby
|
1913
2045
|
get '/' do
|
1914
2046
|
attachment "info.txt"
|
1915
2047
|
"store it!"
|
@@ -1918,21 +2050,22 @@ end
|
|
1918
2050
|
|
1919
2051
|
### Dealing with Date and Time
|
1920
2052
|
|
1921
|
-
Sinatra offers a `time_for` helper method that generates a Time object from
|
1922
|
-
given value. It is also able to convert `DateTime`, `Date` and similar
|
2053
|
+
Sinatra offers a `time_for` helper method that generates a Time object from
|
2054
|
+
the given value. It is also able to convert `DateTime`, `Date` and similar
|
2055
|
+
classes:
|
1923
2056
|
|
1924
|
-
```
|
2057
|
+
```ruby
|
1925
2058
|
get '/' do
|
1926
|
-
pass if Time.now > time_for('Dec 23,
|
2059
|
+
pass if Time.now > time_for('Dec 23, 2016')
|
1927
2060
|
"still time"
|
1928
2061
|
end
|
1929
2062
|
```
|
1930
2063
|
|
1931
|
-
This method is used internally by `expires`, `last_modified` and akin. You
|
1932
|
-
therefore easily extend the behavior of those methods by overriding
|
1933
|
-
in your application:
|
2064
|
+
This method is used internally by `expires`, `last_modified` and akin. You
|
2065
|
+
can therefore easily extend the behavior of those methods by overriding
|
2066
|
+
`time_for` in your application:
|
1934
2067
|
|
1935
|
-
```
|
2068
|
+
```ruby
|
1936
2069
|
helpers do
|
1937
2070
|
def time_for(value)
|
1938
2071
|
case value
|
@@ -1954,17 +2087,17 @@ end
|
|
1954
2087
|
|
1955
2088
|
The `find_template` helper is used to find template files for rendering:
|
1956
2089
|
|
1957
|
-
```
|
2090
|
+
```ruby
|
1958
2091
|
find_template settings.views, 'foo', Tilt[:haml] do |file|
|
1959
2092
|
puts "could be #{file}"
|
1960
2093
|
end
|
1961
2094
|
```
|
1962
2095
|
|
1963
|
-
This is not really useful. But it is useful that you can actually override
|
1964
|
-
method to hook in your own lookup mechanism. For instance, if you want
|
1965
|
-
able to use more than one view directory:
|
2096
|
+
This is not really useful. But it is useful that you can actually override
|
2097
|
+
this method to hook in your own lookup mechanism. For instance, if you want
|
2098
|
+
to be able to use more than one view directory:
|
1966
2099
|
|
1967
|
-
```
|
2100
|
+
```ruby
|
1968
2101
|
set :views, ['views', 'templates']
|
1969
2102
|
|
1970
2103
|
helpers do
|
@@ -1976,7 +2109,7 @@ end
|
|
1976
2109
|
|
1977
2110
|
Another example would be using different directories for different engines:
|
1978
2111
|
|
1979
|
-
```
|
2112
|
+
```ruby
|
1980
2113
|
set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
|
1981
2114
|
|
1982
2115
|
helpers do
|
@@ -1991,17 +2124,17 @@ end
|
|
1991
2124
|
You can also easily wrap this up in an extension and share with others!
|
1992
2125
|
|
1993
2126
|
Note that `find_template` does not check if the file really exists but
|
1994
|
-
rather calls the given block for all possible paths. This is not a
|
1995
|
-
issue, since `render` will use `break` as soon as a file is
|
1996
|
-
template locations (and content) will be cached if you are not
|
1997
|
-
development mode. You should keep that in mind if you write a
|
1998
|
-
method.
|
2127
|
+
rather calls the given block for all possible paths. This is not a
|
2128
|
+
performance issue, since `render` will use `break` as soon as a file is
|
2129
|
+
found. Also, template locations (and content) will be cached if you are not
|
2130
|
+
running in development mode. You should keep that in mind if you write a
|
2131
|
+
really crazy method.
|
1999
2132
|
|
2000
2133
|
## Configuration
|
2001
2134
|
|
2002
2135
|
Run once, at startup, in any environment:
|
2003
2136
|
|
2004
|
-
```
|
2137
|
+
```ruby
|
2005
2138
|
configure do
|
2006
2139
|
# setting one option
|
2007
2140
|
set :option, 'value'
|
@@ -2020,10 +2153,10 @@ configure do
|
|
2020
2153
|
end
|
2021
2154
|
```
|
2022
2155
|
|
2023
|
-
Run only when the environment (`
|
2156
|
+
Run only when the environment (`APP_ENV` environment variable) is set to
|
2024
2157
|
`:production`:
|
2025
2158
|
|
2026
|
-
```
|
2159
|
+
```ruby
|
2027
2160
|
configure :production do
|
2028
2161
|
...
|
2029
2162
|
end
|
@@ -2039,7 +2172,7 @@ end
|
|
2039
2172
|
|
2040
2173
|
You can access those options via `settings`:
|
2041
2174
|
|
2042
|
-
```
|
2175
|
+
```ruby
|
2043
2176
|
configure do
|
2044
2177
|
set :foo, 'bar'
|
2045
2178
|
end
|
@@ -2054,33 +2187,33 @@ end
|
|
2054
2187
|
### Configuring attack protection
|
2055
2188
|
|
2056
2189
|
Sinatra is using
|
2057
|
-
[Rack::Protection](https://github.com/
|
2058
|
-
your application against common, opportunistic attacks. You can
|
2059
|
-
this behavior (which will open up your application to tons
|
2060
|
-
vulnerabilities):
|
2190
|
+
[Rack::Protection](https://github.com/sinatra/rack-protection#readme) to
|
2191
|
+
defend your application against common, opportunistic attacks. You can
|
2192
|
+
easily disable this behavior (which will open up your application to tons
|
2193
|
+
of common vulnerabilities):
|
2061
2194
|
|
2062
|
-
```
|
2195
|
+
```ruby
|
2063
2196
|
disable :protection
|
2064
2197
|
```
|
2065
2198
|
|
2066
2199
|
To skip a single defense layer, set `protection` to an options hash:
|
2067
2200
|
|
2068
|
-
```
|
2201
|
+
```ruby
|
2069
2202
|
set :protection, :except => :path_traversal
|
2070
2203
|
```
|
2071
2204
|
You can also hand in an array in order to disable a list of protections:
|
2072
2205
|
|
2073
|
-
```
|
2206
|
+
```ruby
|
2074
2207
|
set :protection, :except => [:path_traversal, :session_hijacking]
|
2075
2208
|
```
|
2076
2209
|
|
2077
2210
|
By default, Sinatra will only set up session based protection if `:sessions`
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2211
|
+
have been enabled. See 'Using Sessions'. Sometimes you may want to set up
|
2212
|
+
sessions "outside" of the Sinatra app, such as in the config.ru or with a
|
2213
|
+
separate `Rack::Builder` instance. In that case you can still set up session
|
2214
|
+
based protection by passing the `:session` option:
|
2081
2215
|
|
2082
|
-
```
|
2083
|
-
use Rack::Session::Pool
|
2216
|
+
```ruby
|
2084
2217
|
set :protection, :session => true
|
2085
2218
|
```
|
2086
2219
|
|
@@ -2088,197 +2221,224 @@ set :protection, :session => true
|
|
2088
2221
|
|
2089
2222
|
<dl>
|
2090
2223
|
<dt>absolute_redirects</dt>
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2224
|
+
<dd>
|
2225
|
+
If disabled, Sinatra will allow relative redirects, however, Sinatra
|
2226
|
+
will no longer conform with RFC 2616 (HTTP 1.1), which only allows
|
2227
|
+
absolute redirects.
|
2228
|
+
</dd>
|
2229
|
+
<dd>
|
2230
|
+
Enable if your app is running behind a reverse proxy that has not been
|
2231
|
+
set up properly. Note that the <tt>url</tt> helper will still produce
|
2232
|
+
absolute URLs, unless you pass in <tt>false</tt> as the second
|
2233
|
+
parameter.
|
2234
|
+
</dd>
|
2235
|
+
<dd>Disabled by default.</dd>
|
2101
2236
|
|
2102
2237
|
<dt>add_charset</dt>
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2238
|
+
<dd>
|
2239
|
+
Mime types the <tt>content_type</tt> helper will automatically add the
|
2240
|
+
charset info to. You should add to it rather than overriding this
|
2241
|
+
option: <tt>settings.add_charset << "application/foobar"</tt>
|
2242
|
+
</dd>
|
2108
2243
|
|
2109
2244
|
<dt>app_file</dt>
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2245
|
+
<dd>
|
2246
|
+
Path to the main application file, used to detect project root, views
|
2247
|
+
and public folder and inline templates.
|
2248
|
+
</dd>
|
2114
2249
|
|
2115
2250
|
<dt>bind</dt>
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2251
|
+
<dd>
|
2252
|
+
IP address to bind to (default: <tt>0.0.0.0</tt> <em>or</em>
|
2253
|
+
<tt>localhost</tt> if your `environment` is set to development). Only
|
2254
|
+
used for built-in server.
|
2255
|
+
</dd>
|
2119
2256
|
|
2120
2257
|
<dt>default_encoding</dt>
|
2121
|
-
|
2258
|
+
<dd>Encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
|
2122
2259
|
|
2123
2260
|
<dt>dump_errors</dt>
|
2124
|
-
|
2261
|
+
<dd>Display errors in the log.</dd>
|
2125
2262
|
|
2126
2263
|
<dt>environment</dt>
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2264
|
+
<dd>
|
2265
|
+
Current environment. Defaults to <tt>ENV['APP_ENV']</tt>, or
|
2266
|
+
<tt>"development"</tt> if not available.
|
2267
|
+
</dd>
|
2131
2268
|
|
2132
2269
|
<dt>logging</dt>
|
2133
|
-
|
2270
|
+
<dd>Use the logger.</dd>
|
2134
2271
|
|
2135
2272
|
<dt>lock</dt>
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2273
|
+
<dd>
|
2274
|
+
Places a lock around every request, only running processing on request
|
2275
|
+
per Ruby process concurrently.
|
2276
|
+
</dd>
|
2277
|
+
<dd>Enabled if your app is not thread-safe. Disabled by default.</dd>
|
2141
2278
|
|
2142
2279
|
<dt>method_override</dt>
|
2280
|
+
<dd>
|
2281
|
+
Use <tt>_method</tt> magic to allow put/delete forms in browsers that
|
2282
|
+
don't support it.
|
2283
|
+
</dd>
|
2284
|
+
|
2285
|
+
<dt>mustermann_opts</dt>
|
2143
2286
|
<dd>
|
2144
|
-
|
2145
|
-
|
2287
|
+
A default hash of options to pass to Mustermann.new when compiling routing
|
2288
|
+
paths.
|
2146
2289
|
</dd>
|
2147
2290
|
|
2148
2291
|
<dt>port</dt>
|
2149
|
-
|
2292
|
+
<dd>Port to listen on. Only used for built-in server.</dd>
|
2150
2293
|
|
2151
2294
|
<dt>prefixed_redirects</dt>
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2295
|
+
<dd>
|
2296
|
+
Whether or not to insert <tt>request.script_name</tt> into redirects
|
2297
|
+
if no absolute path is given. That way <tt>redirect '/foo'</tt> would
|
2298
|
+
behave like <tt>redirect to('/foo')</tt>. Disabled by default.
|
2299
|
+
</dd>
|
2157
2300
|
|
2158
2301
|
<dt>protection</dt>
|
2159
|
-
|
2160
|
-
|
2302
|
+
<dd>
|
2303
|
+
Whether or not to enable web attack protections. See protection section
|
2304
|
+
above.
|
2305
|
+
</dd>
|
2161
2306
|
|
2162
2307
|
<dt>public_dir</dt>
|
2163
|
-
|
2308
|
+
<dd>Alias for <tt>public_folder</tt>. See below.</dd>
|
2164
2309
|
|
2165
2310
|
<dt>public_folder</dt>
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2311
|
+
<dd>
|
2312
|
+
Path to the folder public files are served from. Only used if static
|
2313
|
+
file serving is enabled (see <tt>static</tt> setting below). Inferred
|
2314
|
+
from <tt>app_file</tt> setting if not set.
|
2315
|
+
</dd>
|
2316
|
+
|
2317
|
+
<dt>quiet</dt>
|
2318
|
+
<dd>
|
2319
|
+
Disables logs generated by Sinatra's start and stop commands.
|
2320
|
+
<tt>false</tt> by default.
|
2321
|
+
</dd>
|
2171
2322
|
|
2172
2323
|
<dt>reload_templates</dt>
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2324
|
+
<dd>
|
2325
|
+
Whether or not to reload templates between requests. Enabled in
|
2326
|
+
development mode.
|
2327
|
+
</dd>
|
2177
2328
|
|
2178
2329
|
<dt>root</dt>
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2330
|
+
<dd>
|
2331
|
+
Path to project root folder. Inferred from <tt>app_file</tt> setting
|
2332
|
+
if not set.
|
2333
|
+
</dd>
|
2183
2334
|
|
2184
2335
|
<dt>raise_errors</dt>
|
2185
|
-
|
2186
|
-
|
2187
|
-
|
2188
|
-
|
2336
|
+
<dd>
|
2337
|
+
Raise exceptions (will stop application). Enabled by default when
|
2338
|
+
<tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
|
2339
|
+
</dd>
|
2189
2340
|
|
2190
2341
|
<dt>run</dt>
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
|
2342
|
+
<dd>
|
2343
|
+
If enabled, Sinatra will handle starting the web server. Do not
|
2344
|
+
enable if using rackup or other means.
|
2345
|
+
</dd>
|
2195
2346
|
|
2196
2347
|
<dt>running</dt>
|
2197
|
-
|
2348
|
+
<dd>Is the built-in server running now? Do not change this setting!</dd>
|
2198
2349
|
|
2199
2350
|
<dt>server</dt>
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2351
|
+
<dd>
|
2352
|
+
Server or list of servers to use for built-in server. Order indicates
|
2353
|
+
priority, default depends on Ruby implementation.
|
2354
|
+
</dd>
|
2204
2355
|
|
2205
2356
|
<dt>sessions</dt>
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2357
|
+
<dd>
|
2358
|
+
Enable cookie-based sessions support using
|
2359
|
+
<tt>Rack::Session::Cookie</tt>. See 'Using Sessions' section for more
|
2360
|
+
information.
|
2361
|
+
</dd>
|
2362
|
+
|
2363
|
+
<dt>session_store</dt>
|
2364
|
+
<dd>
|
2365
|
+
The Rack session middleware used. Defaults to
|
2366
|
+
<tt>Rack::Session::Cookie</tt>. See 'Using Sessions' section for more
|
2367
|
+
information.
|
2368
|
+
</dd>
|
2210
2369
|
|
2211
2370
|
<dt>show_exceptions</dt>
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2371
|
+
<dd>
|
2372
|
+
Show a stack trace in the browser when an exception happens. Enabled by
|
2373
|
+
default when <tt>environment</tt> is set to <tt>"development"</tt>,
|
2374
|
+
disabled otherwise.
|
2375
|
+
</dd>
|
2376
|
+
<dd>
|
2377
|
+
Can also be set to <tt>:after_handler</tt> to trigger app-specified
|
2378
|
+
error handling before showing a stack trace in the browser.
|
2379
|
+
</dd>
|
2221
2380
|
|
2222
2381
|
<dt>static</dt>
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2382
|
+
<dd>Whether Sinatra should handle serving static files.</dd>
|
2383
|
+
<dd>Disable when using a server able to do this on its own.</dd>
|
2384
|
+
<dd>Disabling will boost performance.</dd>
|
2385
|
+
<dd>
|
2386
|
+
Enabled by default in classic style, disabled for modular apps.
|
2387
|
+
</dd>
|
2229
2388
|
|
2230
2389
|
<dt>static_cache_control</dt>
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2390
|
+
<dd>
|
2391
|
+
When Sinatra is serving static files, set this to add
|
2392
|
+
<tt>Cache-Control</tt> headers to the responses. Uses the
|
2393
|
+
<tt>cache_control</tt> helper. Disabled by default.
|
2394
|
+
</dd>
|
2395
|
+
<dd>
|
2396
|
+
Use an explicit array when setting multiple values:
|
2397
|
+
<tt>set :static_cache_control, [:public, :max_age => 300]</tt>
|
2398
|
+
</dd>
|
2240
2399
|
|
2241
2400
|
<dt>threaded</dt>
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2401
|
+
<dd>
|
2402
|
+
If set to <tt>true</tt>, will tell Thin to use
|
2403
|
+
<tt>EventMachine.defer</tt> for processing the request.
|
2404
|
+
</dd>
|
2246
2405
|
|
2247
2406
|
<dt>traps</dt>
|
2248
|
-
|
2407
|
+
<dd>Whether Sinatra should handle system signals.</dd>
|
2249
2408
|
|
2250
2409
|
<dt>views</dt>
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2410
|
+
<dd>
|
2411
|
+
Path to the views folder. Inferred from <tt>app_file</tt> setting if
|
2412
|
+
not set.
|
2413
|
+
</dd>
|
2255
2414
|
|
2256
2415
|
<dt>x_cascade</dt>
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2416
|
+
<dd>
|
2417
|
+
Whether or not to set the X-Cascade header if no route matches.
|
2418
|
+
Defaults to <tt>true</tt>.
|
2419
|
+
</dd>
|
2261
2420
|
</dl>
|
2262
2421
|
|
2263
2422
|
## Environments
|
2264
2423
|
|
2265
|
-
There are three predefined `environments`: `"development"`,
|
2266
|
-
`"test"`. Environments can be set through the
|
2267
|
-
The default value is `"development"`.
|
2268
|
-
|
2269
|
-
|
2270
|
-
`"test"` environments,
|
2424
|
+
There are three predefined `environments`: `"development"`,
|
2425
|
+
`"production"` and `"test"`. Environments can be set through the
|
2426
|
+
`APP_ENV` environment variable. The default value is `"development"`.
|
2427
|
+
In the `"development"` environment all templates are reloaded between
|
2428
|
+
requests, and special `not_found` and `error` handlers display stack
|
2429
|
+
traces in your browser. In the `"production"` and `"test"` environments,
|
2430
|
+
templates are cached by default.
|
2271
2431
|
|
2272
|
-
To run different environments, set the `
|
2432
|
+
To run different environments, set the `APP_ENV` environment variable:
|
2273
2433
|
|
2274
|
-
```
|
2275
|
-
|
2434
|
+
```shell
|
2435
|
+
APP_ENV=production ruby my_app.rb
|
2276
2436
|
```
|
2277
2437
|
|
2278
2438
|
You can use predefined methods: `development?`, `test?` and `production?` to
|
2279
2439
|
check the current environment setting:
|
2280
2440
|
|
2281
|
-
```
|
2441
|
+
```ruby
|
2282
2442
|
get '/' do
|
2283
2443
|
if settings.development?
|
2284
2444
|
"development!"
|
@@ -2290,16 +2450,16 @@ end
|
|
2290
2450
|
|
2291
2451
|
## Error Handling
|
2292
2452
|
|
2293
|
-
Error handlers run within the same context as routes and before filters,
|
2294
|
-
means you get all the goodies it has to offer, like `haml`,
|
2295
|
-
`
|
2453
|
+
Error handlers run within the same context as routes and before filters,
|
2454
|
+
which means you get all the goodies it has to offer, like `haml`, `erb`,
|
2455
|
+
`halt`, etc.
|
2296
2456
|
|
2297
2457
|
### Not Found
|
2298
2458
|
|
2299
2459
|
When a `Sinatra::NotFound` exception is raised, or the response's status
|
2300
2460
|
code is 404, the `not_found` handler is invoked:
|
2301
2461
|
|
2302
|
-
```
|
2462
|
+
```ruby
|
2303
2463
|
not_found do
|
2304
2464
|
'This is nowhere to be found.'
|
2305
2465
|
end
|
@@ -2317,7 +2477,7 @@ set :show_exceptions, :after_handler
|
|
2317
2477
|
|
2318
2478
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2319
2479
|
|
2320
|
-
```
|
2480
|
+
```ruby
|
2321
2481
|
error do
|
2322
2482
|
'Sorry there was a nasty error - ' + env['sinatra.error'].message
|
2323
2483
|
end
|
@@ -2325,7 +2485,7 @@ end
|
|
2325
2485
|
|
2326
2486
|
Custom errors:
|
2327
2487
|
|
2328
|
-
```
|
2488
|
+
```ruby
|
2329
2489
|
error MyCustomError do
|
2330
2490
|
'So what happened was...' + env['sinatra.error'].message
|
2331
2491
|
end
|
@@ -2333,7 +2493,7 @@ end
|
|
2333
2493
|
|
2334
2494
|
Then, if this happens:
|
2335
2495
|
|
2336
|
-
```
|
2496
|
+
```ruby
|
2337
2497
|
get '/' do
|
2338
2498
|
raise MyCustomError, 'something bad'
|
2339
2499
|
end
|
@@ -2347,7 +2507,7 @@ So what happened was... something bad
|
|
2347
2507
|
|
2348
2508
|
Alternatively, you can install an error handler for a status code:
|
2349
2509
|
|
2350
|
-
```
|
2510
|
+
```ruby
|
2351
2511
|
error 403 do
|
2352
2512
|
'Access forbidden'
|
2353
2513
|
end
|
@@ -2359,7 +2519,7 @@ end
|
|
2359
2519
|
|
2360
2520
|
Or a range:
|
2361
2521
|
|
2362
|
-
```
|
2522
|
+
```ruby
|
2363
2523
|
error 400..510 do
|
2364
2524
|
'Boom'
|
2365
2525
|
end
|
@@ -2372,15 +2532,16 @@ and additional debugging information in your browser.
|
|
2372
2532
|
## Rack Middleware
|
2373
2533
|
|
2374
2534
|
Sinatra rides on [Rack](http://rack.github.io/), a minimal standard
|
2375
|
-
interface for Ruby web frameworks. One of Rack's most interesting
|
2376
|
-
for application developers is support for "middleware" --
|
2377
|
-
between the server and your application monitoring
|
2378
|
-
HTTP request/response to provide various types
|
2535
|
+
interface for Ruby web frameworks. One of Rack's most interesting
|
2536
|
+
capabilities for application developers is support for "middleware" --
|
2537
|
+
components that sit between the server and your application monitoring
|
2538
|
+
and/or manipulating the HTTP request/response to provide various types
|
2539
|
+
of common functionality.
|
2379
2540
|
|
2380
2541
|
Sinatra makes building Rack middleware pipelines a cinch via a top-level
|
2381
2542
|
`use` method:
|
2382
2543
|
|
2383
|
-
```
|
2544
|
+
```ruby
|
2384
2545
|
require 'sinatra'
|
2385
2546
|
require 'my_custom_middleware'
|
2386
2547
|
|
@@ -2393,11 +2554,11 @@ end
|
|
2393
2554
|
```
|
2394
2555
|
|
2395
2556
|
The semantics of `use` are identical to those defined for the
|
2396
|
-
[Rack::Builder](http://rubydoc.info/github/rack/rack/master/Rack/Builder) DSL
|
2557
|
+
[Rack::Builder](http://www.rubydoc.info/github/rack/rack/master/Rack/Builder) DSL
|
2397
2558
|
(most frequently used from rackup files). For example, the `use` method
|
2398
2559
|
accepts multiple/variable args as well as blocks:
|
2399
2560
|
|
2400
|
-
```
|
2561
|
+
```ruby
|
2401
2562
|
use Rack::Auth::Basic do |username, password|
|
2402
2563
|
username == 'admin' && password == 'secret'
|
2403
2564
|
end
|
@@ -2415,11 +2576,12 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2415
2576
|
|
2416
2577
|
## Testing
|
2417
2578
|
|
2418
|
-
Sinatra tests can be written using any Rack-based testing library or
|
2419
|
-
|
2579
|
+
Sinatra tests can be written using any Rack-based testing library or
|
2580
|
+
framework.
|
2581
|
+
[Rack::Test](http://www.rubydoc.info/github/brynary/rack-test/master/frames)
|
2420
2582
|
is recommended:
|
2421
2583
|
|
2422
|
-
```
|
2584
|
+
```ruby
|
2423
2585
|
require 'my_sinatra_app'
|
2424
2586
|
require 'minitest/autorun'
|
2425
2587
|
require 'rack/test'
|
@@ -2441,7 +2603,7 @@ class MyAppTest < Minitest::Test
|
|
2441
2603
|
assert_equal 'Hello Frank!', last_response.body
|
2442
2604
|
end
|
2443
2605
|
|
2444
|
-
def
|
2606
|
+
def test_with_user_agent
|
2445
2607
|
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
|
2446
2608
|
assert_equal "You're using Songbird!", last_response.body
|
2447
2609
|
end
|
@@ -2461,7 +2623,7 @@ Sinatra extensions. The top-level assumes a micro-app style configuration
|
|
2461
2623
|
directories, logging, exception detail page, etc.). That's where
|
2462
2624
|
`Sinatra::Base` comes into play:
|
2463
2625
|
|
2464
|
-
```
|
2626
|
+
```ruby
|
2465
2627
|
require 'sinatra/base'
|
2466
2628
|
|
2467
2629
|
class MyApp < Sinatra::Base
|
@@ -2474,9 +2636,9 @@ class MyApp < Sinatra::Base
|
|
2474
2636
|
end
|
2475
2637
|
```
|
2476
2638
|
|
2477
|
-
The methods available to `Sinatra::Base` subclasses are exactly the same
|
2478
|
-
those available via the top-level DSL. Most top-level apps can be
|
2479
|
-
`Sinatra::Base` components with two modifications:
|
2639
|
+
The methods available to `Sinatra::Base` subclasses are exactly the same
|
2640
|
+
as those available via the top-level DSL. Most top-level apps can be
|
2641
|
+
converted to `Sinatra::Base` components with two modifications:
|
2480
2642
|
|
2481
2643
|
* Your file should require `sinatra/base` instead of `sinatra`;
|
2482
2644
|
otherwise, all of Sinatra's DSL methods are imported into the main
|
@@ -2485,14 +2647,13 @@ those available via the top-level DSL. Most top-level apps can be converted to
|
|
2485
2647
|
of `Sinatra::Base`.
|
2486
2648
|
|
2487
2649
|
`Sinatra::Base` is a blank slate. Most options are disabled by default,
|
2488
|
-
including the built-in server. See
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
``` ruby
|
2650
|
+
including the built-in server. See [Configuring
|
2651
|
+
Settings](http://www.sinatrarb.com/configuration.html) for details on
|
2652
|
+
available options and their behavior. If you want behavior more similar
|
2653
|
+
to when you define your app at the top level (also known as Classic
|
2654
|
+
style), you can subclass `Sinatra::Application`:
|
2655
|
+
|
2656
|
+
```ruby
|
2496
2657
|
require 'sinatra/base'
|
2497
2658
|
|
2498
2659
|
class MyApp < Sinatra::Application
|
@@ -2504,16 +2665,17 @@ end
|
|
2504
2665
|
|
2505
2666
|
### Modular vs. Classic Style
|
2506
2667
|
|
2507
|
-
Contrary to common belief, there is nothing wrong with the classic
|
2508
|
-
suits your application, you do not have to switch to a
|
2668
|
+
Contrary to common belief, there is nothing wrong with the classic
|
2669
|
+
style. If it suits your application, you do not have to switch to a
|
2670
|
+
modular application.
|
2509
2671
|
|
2510
|
-
The main disadvantage of using the classic style rather than the modular
|
2511
|
-
is that you will only have one Sinatra application per Ruby
|
2512
|
-
plan to use more than one, switch to the modular style.
|
2513
|
-
cannot mix the modular and the classic styles.
|
2672
|
+
The main disadvantage of using the classic style rather than the modular
|
2673
|
+
style is that you will only have one Sinatra application per Ruby
|
2674
|
+
process. If you plan to use more than one, switch to the modular style.
|
2675
|
+
There is no reason you cannot mix the modular and the classic styles.
|
2514
2676
|
|
2515
|
-
If switching from one style to the other, you should be aware of
|
2516
|
-
different default settings:
|
2677
|
+
If switching from one style to the other, you should be aware of
|
2678
|
+
slightly different default settings:
|
2517
2679
|
|
2518
2680
|
<table>
|
2519
2681
|
<tr>
|
@@ -2561,17 +2723,17 @@ different default settings:
|
|
2561
2723
|
<tr>
|
2562
2724
|
<td>static</td>
|
2563
2725
|
<td>true</td>
|
2564
|
-
<td>
|
2726
|
+
<td>File.exist?(public_folder)</td>
|
2565
2727
|
<td>true</td>
|
2566
2728
|
</tr>
|
2567
2729
|
</table>
|
2568
2730
|
|
2569
2731
|
### Serving a Modular Application
|
2570
2732
|
|
2571
|
-
There are two common options for starting a modular app, actively
|
2572
|
-
`run!`:
|
2733
|
+
There are two common options for starting a modular app, actively
|
2734
|
+
starting with `run!`:
|
2573
2735
|
|
2574
|
-
```
|
2736
|
+
```ruby
|
2575
2737
|
# my_app.rb
|
2576
2738
|
require 'sinatra/base'
|
2577
2739
|
|
@@ -2585,13 +2747,13 @@ end
|
|
2585
2747
|
|
2586
2748
|
Start with:
|
2587
2749
|
|
2588
|
-
```
|
2750
|
+
```shell
|
2589
2751
|
ruby my_app.rb
|
2590
2752
|
```
|
2591
2753
|
|
2592
2754
|
Or with a `config.ru` file, which allows using any Rack handler:
|
2593
2755
|
|
2594
|
-
```
|
2756
|
+
```ruby
|
2595
2757
|
# config.ru (run with rackup)
|
2596
2758
|
require './my_app'
|
2597
2759
|
run MyApp
|
@@ -2599,7 +2761,7 @@ run MyApp
|
|
2599
2761
|
|
2600
2762
|
Run:
|
2601
2763
|
|
2602
|
-
```
|
2764
|
+
```shell
|
2603
2765
|
rackup -p 4567
|
2604
2766
|
```
|
2605
2767
|
|
@@ -2607,7 +2769,7 @@ rackup -p 4567
|
|
2607
2769
|
|
2608
2770
|
Write your app file:
|
2609
2771
|
|
2610
|
-
```
|
2772
|
+
```ruby
|
2611
2773
|
# app.rb
|
2612
2774
|
require 'sinatra'
|
2613
2775
|
|
@@ -2618,7 +2780,7 @@ end
|
|
2618
2780
|
|
2619
2781
|
And a corresponding `config.ru`:
|
2620
2782
|
|
2621
|
-
```
|
2783
|
+
```ruby
|
2622
2784
|
require './app'
|
2623
2785
|
run Sinatra::Application
|
2624
2786
|
```
|
@@ -2632,18 +2794,18 @@ A `config.ru` file is recommended if:
|
|
2632
2794
|
* You want to use more than one subclass of `Sinatra::Base`.
|
2633
2795
|
* You want to use Sinatra only for middleware, and not as an endpoint.
|
2634
2796
|
|
2635
|
-
**There is no need to switch to a `config.ru` simply because you
|
2636
|
-
the modular style, and you don't have to use the modular
|
2637
|
-
a `config.ru`.**
|
2797
|
+
**There is no need to switch to a `config.ru` simply because you
|
2798
|
+
switched to the modular style, and you don't have to use the modular
|
2799
|
+
style for running with a `config.ru`.**
|
2638
2800
|
|
2639
2801
|
### Using Sinatra as Middleware
|
2640
2802
|
|
2641
|
-
Not only is Sinatra able to use other Rack middleware, any Sinatra
|
2642
|
-
can in turn be added in front of any Rack endpoint as
|
2643
|
-
endpoint could be another Sinatra application,
|
2644
|
-
application (Rails/
|
2803
|
+
Not only is Sinatra able to use other Rack middleware, any Sinatra
|
2804
|
+
application can in turn be added in front of any Rack endpoint as
|
2805
|
+
middleware itself. This endpoint could be another Sinatra application,
|
2806
|
+
or any other Rack-based application (Rails/Hanami/Roda/...):
|
2645
2807
|
|
2646
|
-
```
|
2808
|
+
```ruby
|
2647
2809
|
require 'sinatra/base'
|
2648
2810
|
|
2649
2811
|
class LoginScreen < Sinatra::Base
|
@@ -2679,7 +2841,7 @@ end
|
|
2679
2841
|
Sometimes you want to create new applications at runtime without having to
|
2680
2842
|
assign them to a constant. You can do this with `Sinatra.new`:
|
2681
2843
|
|
2682
|
-
```
|
2844
|
+
```ruby
|
2683
2845
|
require 'sinatra/base'
|
2684
2846
|
my_app = Sinatra.new { get('/') { "hi" } }
|
2685
2847
|
my_app.run!
|
@@ -2710,7 +2872,7 @@ your own library.
|
|
2710
2872
|
|
2711
2873
|
This also makes using Sinatra as middleware extremely easy:
|
2712
2874
|
|
2713
|
-
```
|
2875
|
+
```ruby
|
2714
2876
|
require 'sinatra/base'
|
2715
2877
|
|
2716
2878
|
use Sinatra do
|
@@ -2730,13 +2892,13 @@ available.
|
|
2730
2892
|
Every Sinatra application corresponds to a subclass of `Sinatra::Base`.
|
2731
2893
|
If you are using the top-level DSL (`require 'sinatra'`), then this
|
2732
2894
|
class is `Sinatra::Application`, otherwise it is the subclass you
|
2733
|
-
created explicitly. At class level you have methods like `get` or
|
2734
|
-
you cannot access the `request` or `session` objects, as
|
2735
|
-
single application class for all requests.
|
2895
|
+
created explicitly. At class level you have methods like `get` or
|
2896
|
+
`before`, but you cannot access the `request` or `session` objects, as
|
2897
|
+
there is only a single application class for all requests.
|
2736
2898
|
|
2737
2899
|
Options created via `set` are methods at class level:
|
2738
2900
|
|
2739
|
-
```
|
2901
|
+
```ruby
|
2740
2902
|
class MyApp < Sinatra::Base
|
2741
2903
|
# Hey, I'm in the application scope!
|
2742
2904
|
set :foo, 42
|
@@ -2769,7 +2931,7 @@ can access the `request` and `session` objects or call rendering methods like
|
|
2769
2931
|
`erb` or `haml`. You can access the application scope from within the request
|
2770
2932
|
scope via the `settings` helper:
|
2771
2933
|
|
2772
|
-
```
|
2934
|
+
```ruby
|
2773
2935
|
class MyApp < Sinatra::Base
|
2774
2936
|
# Hey, I'm in the application scope!
|
2775
2937
|
get '/define_route/:name' do
|
@@ -2788,7 +2950,7 @@ end
|
|
2788
2950
|
|
2789
2951
|
You have the request scope binding inside:
|
2790
2952
|
|
2791
|
-
* get, head, post, put, delete, options, patch, link
|
2953
|
+
* get, head, post, put, delete, options, patch, link and unlink blocks
|
2792
2954
|
* before and after filters
|
2793
2955
|
* helper methods
|
2794
2956
|
* templates/views
|
@@ -2815,8 +2977,8 @@ being [extending the main object](https://github.com/sinatra/sinatra/blob/ca0636
|
|
2815
2977
|
|
2816
2978
|
Sinatra applications can be run directly:
|
2817
2979
|
|
2818
|
-
```
|
2819
|
-
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
|
2980
|
+
```shell
|
2981
|
+
ruby myapp.rb [-h] [-x] [-q] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
|
2820
2982
|
```
|
2821
2983
|
|
2822
2984
|
Options are:
|
@@ -2827,38 +2989,54 @@ Options are:
|
|
2827
2989
|
-o # set the host (default is 0.0.0.0)
|
2828
2990
|
-e # set the environment (default is development)
|
2829
2991
|
-s # specify rack server/handler (default is thin)
|
2992
|
+
-q # turn on quiet mode for server (default is off)
|
2830
2993
|
-x # turn on the mutex lock (default is off)
|
2831
2994
|
```
|
2832
2995
|
|
2833
|
-
|
2996
|
+
### Multi-threading
|
2834
2997
|
|
2835
|
-
|
2836
|
-
<dl>
|
2837
|
-
<dt>Ruby 1.8.7</dt>
|
2838
|
-
<dd>
|
2839
|
-
1.8.7 is fully supported, however, if nothing is keeping you from it, we
|
2840
|
-
recommend upgrading or switching to JRuby or Rubinius. Support for 1.8.7
|
2841
|
-
will not be dropped before Sinatra 2.0. Ruby 1.8.6 is no longer supported.
|
2842
|
-
</dd>
|
2998
|
+
_Paraphrasing from [this StackOverflow answer][so-answer] by Konstantin_
|
2843
2999
|
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
3000
|
+
Sinatra doesn't impose any concurrency model, but leaves that to the
|
3001
|
+
underlying Rack handler (server) like Thin, Puma or WEBrick. Sinatra
|
3002
|
+
itself is thread-safe, so there won't be any problem if the Rack handler
|
3003
|
+
uses a threaded model of concurrency. This would mean that when starting
|
3004
|
+
the server, you'd have to specify the correct invocation method for the
|
3005
|
+
specific Rack handler. The following example is a demonstration of how
|
3006
|
+
to start a multi-threaded Thin server:
|
2850
3007
|
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
3008
|
+
```ruby
|
3009
|
+
# app.rb
|
3010
|
+
|
3011
|
+
require 'sinatra/base'
|
3012
|
+
|
3013
|
+
class App < Sinatra::Base
|
3014
|
+
get '/' do
|
3015
|
+
"Hello, World"
|
3016
|
+
end
|
3017
|
+
end
|
3018
|
+
|
3019
|
+
App.run!
|
3020
|
+
|
3021
|
+
```
|
3022
|
+
|
3023
|
+
To start the server, the command would be:
|
3024
|
+
|
3025
|
+
```shell
|
3026
|
+
thin --threaded start
|
3027
|
+
```
|
2857
3028
|
|
2858
|
-
|
3029
|
+
|
3030
|
+
[so-answer]: http://stackoverflow.com/questions/6278817/is-sinatra-multi-threaded/6282999#6282999)
|
3031
|
+
|
3032
|
+
## Requirement
|
3033
|
+
|
3034
|
+
The following Ruby versions are officially supported:
|
3035
|
+
<dl>
|
3036
|
+
<dt>Ruby 2.2</dt>
|
2859
3037
|
<dd>
|
2860
|
-
2.
|
2861
|
-
official support for it.
|
3038
|
+
2.2 is fully supported and recommended. There are currently no plans to
|
3039
|
+
drop official support for it.
|
2862
3040
|
</dd>
|
2863
3041
|
|
2864
3042
|
<dt>Rubinius</dt>
|
@@ -2875,6 +3053,8 @@ The following Ruby versions are officially supported:
|
|
2875
3053
|
</dd>
|
2876
3054
|
</dl>
|
2877
3055
|
|
3056
|
+
Versions of Ruby prior to 2.2.2 are no longer supported as of Sinatra 2.0.
|
3057
|
+
|
2878
3058
|
We also keep an eye on upcoming Ruby versions.
|
2879
3059
|
|
2880
3060
|
The following Ruby implementations are not officially supported but still are
|
@@ -2888,9 +3068,9 @@ known to run Sinatra:
|
|
2888
3068
|
Not being officially supported means if things only break there and not on a
|
2889
3069
|
supported platform, we assume it's not our issue but theirs.
|
2890
3070
|
|
2891
|
-
We also run our CI against ruby-head (future releases of MRI), but we
|
2892
|
-
guarantee anything, since it is constantly moving. Expect upcoming
|
2893
|
-
to be fully supported.
|
3071
|
+
We also run our CI against ruby-head (future releases of MRI), but we
|
3072
|
+
can't guarantee anything, since it is constantly moving. Expect upcoming
|
3073
|
+
2.x releases to be fully supported.
|
2894
3074
|
|
2895
3075
|
Sinatra should work on any operating system supported by the chosen Ruby
|
2896
3076
|
implementation.
|
@@ -2898,16 +3078,17 @@ implementation.
|
|
2898
3078
|
If you run MacRuby, you should `gem install control_tower`.
|
2899
3079
|
|
2900
3080
|
Sinatra currently doesn't run on Cardinal, SmallRuby, BlueRuby or any
|
2901
|
-
Ruby version prior to
|
3081
|
+
Ruby version prior to 2.2.
|
2902
3082
|
|
2903
3083
|
## The Bleeding Edge
|
2904
3084
|
|
2905
|
-
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
2906
|
-
application against the master branch, it should be rather
|
3085
|
+
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
3086
|
+
to run your application against the master branch, it should be rather
|
3087
|
+
stable.
|
2907
3088
|
|
2908
3089
|
We also push out prerelease gems from time to time, so you can do a
|
2909
3090
|
|
2910
|
-
```
|
3091
|
+
```shell
|
2911
3092
|
gem install sinatra --pre
|
2912
3093
|
```
|
2913
3094
|
|
@@ -2916,11 +3097,11 @@ to get some of the latest features.
|
|
2916
3097
|
### With Bundler
|
2917
3098
|
|
2918
3099
|
If you want to run your application with the latest Sinatra, using
|
2919
|
-
[Bundler](http://
|
3100
|
+
[Bundler](http://bundler.io) is the recommended way.
|
2920
3101
|
|
2921
3102
|
First, install bundler, if you haven't:
|
2922
3103
|
|
2923
|
-
```
|
3104
|
+
```shell
|
2924
3105
|
gem install bundler
|
2925
3106
|
```
|
2926
3107
|
|
@@ -2928,58 +3109,22 @@ Then, in your project directory, create a `Gemfile`:
|
|
2928
3109
|
|
2929
3110
|
```ruby
|
2930
3111
|
source 'https://rubygems.org'
|
2931
|
-
gem 'sinatra', :github =>
|
3112
|
+
gem 'sinatra', :github => 'sinatra/sinatra'
|
2932
3113
|
|
2933
3114
|
# other dependencies
|
2934
3115
|
gem 'haml' # for instance, if you use haml
|
2935
|
-
gem 'activerecord', '~> 3.0' # maybe you also need ActiveRecord 3.x
|
2936
3116
|
```
|
2937
3117
|
|
2938
|
-
Note that you will have to list all your application's dependencies in
|
2939
|
-
Sinatra's direct dependencies (Rack and Tilt) will,
|
2940
|
-
fetched and added by Bundler.
|
3118
|
+
Note that you will have to list all your application's dependencies in
|
3119
|
+
the `Gemfile`. Sinatra's direct dependencies (Rack and Tilt) will,
|
3120
|
+
however, be automatically fetched and added by Bundler.
|
2941
3121
|
|
2942
3122
|
Now you can run your app like this:
|
2943
3123
|
|
2944
|
-
```
|
3124
|
+
```shell
|
2945
3125
|
bundle exec ruby myapp.rb
|
2946
3126
|
```
|
2947
3127
|
|
2948
|
-
### Roll Your Own
|
2949
|
-
|
2950
|
-
Create a local clone and run your app with the `sinatra/lib` directory
|
2951
|
-
on the `$LOAD_PATH`:
|
2952
|
-
|
2953
|
-
``` shell
|
2954
|
-
cd myapp
|
2955
|
-
git clone git://github.com/sinatra/sinatra.git
|
2956
|
-
ruby -I sinatra/lib myapp.rb
|
2957
|
-
```
|
2958
|
-
|
2959
|
-
To update the Sinatra sources in the future:
|
2960
|
-
|
2961
|
-
``` shell
|
2962
|
-
cd myapp/sinatra
|
2963
|
-
git pull
|
2964
|
-
```
|
2965
|
-
|
2966
|
-
### Install Globally
|
2967
|
-
|
2968
|
-
You can build the gem on your own:
|
2969
|
-
|
2970
|
-
``` shell
|
2971
|
-
git clone git://github.com/sinatra/sinatra.git
|
2972
|
-
cd sinatra
|
2973
|
-
rake sinatra.gemspec
|
2974
|
-
rake install
|
2975
|
-
```
|
2976
|
-
|
2977
|
-
If you install gems as root, the last step should be:
|
2978
|
-
|
2979
|
-
``` shell
|
2980
|
-
sudo rake install
|
2981
|
-
```
|
2982
|
-
|
2983
3128
|
## Versioning
|
2984
3129
|
|
2985
3130
|
Sinatra follows [Semantic Versioning](http://semver.org/), both SemVer and
|
@@ -2991,14 +3136,16 @@ SemVerTag.
|
|
2991
3136
|
news, and links to other resources.
|
2992
3137
|
* [Contributing](http://www.sinatrarb.com/contributing) - Find a bug? Need
|
2993
3138
|
help? Have a patch?
|
2994
|
-
* [Issue tracker](
|
2995
|
-
* [Twitter](
|
3139
|
+
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
3140
|
+
* [Twitter](https://twitter.com/sinatra)
|
2996
3141
|
* [Mailing List](http://groups.google.com/group/sinatrarb/topics)
|
2997
3142
|
* IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on http://freenode.net
|
3143
|
+
* [Sinatra & Friends](https://sinatrarb.slack.com) on Slack and see
|
3144
|
+
[here](https://sinatra-slack.herokuapp.com/) for an invite.
|
2998
3145
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book/) Cookbook Tutorial
|
2999
3146
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) Community
|
3000
3147
|
contributed recipes
|
3001
|
-
* API documentation for the [latest release](http://rubydoc.info/gems/sinatra)
|
3002
|
-
or the [current HEAD](http://rubydoc.info/github/sinatra/sinatra) on
|
3003
|
-
http://rubydoc.info
|
3004
|
-
* [CI server](
|
3148
|
+
* API documentation for the [latest release](http://www.rubydoc.info/gems/sinatra)
|
3149
|
+
or the [current HEAD](http://www.rubydoc.info/github/sinatra/sinatra) on
|
3150
|
+
http://www.rubydoc.info/
|
3151
|
+
* [CI server](https://travis-ci.org/sinatra/sinatra)
|