sinatra 1.4.6 → 1.4.7
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} +17 -1
- data/CONTRIBUTING.md +100 -0
- data/LICENSE +2 -2
- data/README.de.md +78 -41
- data/README.es.md +200 -165
- data/README.fr.md +364 -338
- data/README.hu.md +7 -7
- data/README.ja.md +199 -167
- data/README.ko.md +222 -183
- data/README.md +218 -179
- data/README.pt-br.md +146 -112
- data/README.pt-pt.md +63 -63
- data/README.ru.md +158 -35
- data/README.zh.md +1941 -1235
- data/Rakefile +2 -2
- data/lib/sinatra/base.rb +16 -24
- data/lib/sinatra/ext.rb +17 -0
- data/lib/sinatra/show_exceptions.rb +13 -7
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +1 -1
- data/test/public/hello+world.txt +1 -0
- data/test/routing_test.rb +44 -0
- data/test/static_test.rb +30 -0
- metadata +9 -6
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Sinatra
|
2
2
|
|
3
|
-
Sinatra is a [DSL](
|
3
|
+
Sinatra is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for
|
4
4
|
quickly creating web applications in Ruby with minimal effort:
|
5
5
|
|
6
|
-
```
|
6
|
+
```ruby
|
7
7
|
# myapp.rb
|
8
8
|
require 'sinatra'
|
9
9
|
|
@@ -14,17 +14,17 @@ end
|
|
14
14
|
|
15
15
|
Install the gem:
|
16
16
|
|
17
|
-
```
|
17
|
+
```shell
|
18
18
|
gem install sinatra
|
19
19
|
```
|
20
20
|
|
21
21
|
And run with:
|
22
22
|
|
23
|
-
```
|
23
|
+
```shell
|
24
24
|
ruby myapp.rb
|
25
25
|
```
|
26
26
|
|
27
|
-
View at: http://localhost:4567
|
27
|
+
View at: [http://localhost:4567](http://localhost:4567)
|
28
28
|
|
29
29
|
It is recommended to also run `gem install thin`, which Sinatra will
|
30
30
|
pick up if available.
|
@@ -109,6 +109,7 @@ pick up if available.
|
|
109
109
|
* [Request/Instance Scope](#requestinstance-scope)
|
110
110
|
* [Delegation Scope](#delegation-scope)
|
111
111
|
* [Command Line](#command-line)
|
112
|
+
* [Multi-threading](#multi-threading)
|
112
113
|
* [Requirement](#requirement)
|
113
114
|
* [The Bleeding Edge](#the-bleeding-edge)
|
114
115
|
* [With Bundler](#with-bundler)
|
@@ -122,7 +123,7 @@ pick up if available.
|
|
122
123
|
In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
|
123
124
|
Each route is associated with a block:
|
124
125
|
|
125
|
-
```
|
126
|
+
```ruby
|
126
127
|
get '/' do
|
127
128
|
.. show something ..
|
128
129
|
end
|
@@ -162,7 +163,7 @@ matches the request is invoked.
|
|
162
163
|
Route patterns may include named parameters, accessible via the
|
163
164
|
`params` hash:
|
164
165
|
|
165
|
-
```
|
166
|
+
```ruby
|
166
167
|
get '/hello/:name' do
|
167
168
|
# matches "GET /hello/foo" and "GET /hello/bar"
|
168
169
|
# params['name'] is 'foo' or 'bar'
|
@@ -172,7 +173,7 @@ end
|
|
172
173
|
|
173
174
|
You can also access named parameters via block parameters:
|
174
175
|
|
175
|
-
```
|
176
|
+
```ruby
|
176
177
|
get '/hello/:name' do |n|
|
177
178
|
# matches "GET /hello/foo" and "GET /hello/bar"
|
178
179
|
# params['name'] is 'foo' or 'bar'
|
@@ -184,7 +185,7 @@ end
|
|
184
185
|
Route patterns may also include splat (or wildcard) parameters, accessible
|
185
186
|
via the `params['splat']` array:
|
186
187
|
|
187
|
-
```
|
188
|
+
```ruby
|
188
189
|
get '/say/*/to/*' do
|
189
190
|
# matches /say/hello/to/world
|
190
191
|
params['splat'] # => ["hello", "world"]
|
@@ -198,7 +199,7 @@ end
|
|
198
199
|
|
199
200
|
Or with block parameters:
|
200
201
|
|
201
|
-
```
|
202
|
+
```ruby
|
202
203
|
get '/download/*.*' do |path, ext|
|
203
204
|
[path, ext] # => ["path/to/file", "xml"]
|
204
205
|
end
|
@@ -206,7 +207,7 @@ end
|
|
206
207
|
|
207
208
|
Route matching with Regular Expressions:
|
208
209
|
|
209
|
-
```
|
210
|
+
```ruby
|
210
211
|
get /\A\/hello\/([\w]+)\z/ do
|
211
212
|
"Hello, #{params['captures'].first}!"
|
212
213
|
end
|
@@ -214,7 +215,7 @@ end
|
|
214
215
|
|
215
216
|
Or with a block parameter:
|
216
217
|
|
217
|
-
```
|
218
|
+
```ruby
|
218
219
|
get %r{/hello/([\w]+)} do |c|
|
219
220
|
# Matches "GET /meta/hello/world", "GET /hello/world/1234" etc.
|
220
221
|
"Hello, #{c}!"
|
@@ -223,15 +224,15 @@ end
|
|
223
224
|
|
224
225
|
Route patterns may have optional parameters:
|
225
226
|
|
226
|
-
```
|
227
|
-
get '/posts
|
228
|
-
# matches "GET /posts" and any extension "GET /posts
|
227
|
+
```ruby
|
228
|
+
get '/posts/:format?' do
|
229
|
+
# matches "GET /posts/" and any extension "GET /posts/json", "GET /posts/xml" etc
|
229
230
|
end
|
230
231
|
```
|
231
232
|
|
232
233
|
Routes may also utilize query parameters:
|
233
234
|
|
234
|
-
```
|
235
|
+
```ruby
|
235
236
|
get '/posts' do
|
236
237
|
# matches "GET /posts?title=foo&author=bar"
|
237
238
|
title = params['title']
|
@@ -247,7 +248,7 @@ the request path might be modified before matching against your routes.
|
|
247
248
|
|
248
249
|
Routes may include a variety of matching conditions, such as the user agent:
|
249
250
|
|
250
|
-
```
|
251
|
+
```ruby
|
251
252
|
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
|
252
253
|
"You're using Songbird version #{params['agent'][0]}"
|
253
254
|
end
|
@@ -259,7 +260,7 @@ end
|
|
259
260
|
|
260
261
|
Other available conditions are `host_name` and `provides`:
|
261
262
|
|
262
|
-
```
|
263
|
+
```ruby
|
263
264
|
get '/', :host_name => /^admin\./ do
|
264
265
|
"Admin Area, Access denied!"
|
265
266
|
end
|
@@ -276,7 +277,7 @@ end
|
|
276
277
|
|
277
278
|
You can easily define your own conditions:
|
278
279
|
|
279
|
-
```
|
280
|
+
```ruby
|
280
281
|
set(:probability) { |value| condition { rand <= value } }
|
281
282
|
|
282
283
|
get '/win_a_car', :probability => 0.1 do
|
@@ -290,7 +291,7 @@ end
|
|
290
291
|
|
291
292
|
For a condition that takes multiple values use a splat:
|
292
293
|
|
293
|
-
```
|
294
|
+
```ruby
|
294
295
|
set(:auth) do |*roles| # <- notice the splat here
|
295
296
|
condition do
|
296
297
|
unless logged_in? && roles.any? {|role| current_user.in_role? role }
|
@@ -328,7 +329,7 @@ body object or HTTP status code:
|
|
328
329
|
|
329
330
|
That way we can, for instance, easily implement a streaming example:
|
330
331
|
|
331
|
-
```
|
332
|
+
```ruby
|
332
333
|
class Stream
|
333
334
|
def each
|
334
335
|
100.times { |i| yield "#{i}\n" }
|
@@ -347,7 +348,7 @@ As shown above, Sinatra ships with built-in support for using String patterns
|
|
347
348
|
and regular expressions as route matches. However, it does not stop there. You
|
348
349
|
can easily define your own matchers:
|
349
350
|
|
350
|
-
```
|
351
|
+
```ruby
|
351
352
|
class AllButPattern
|
352
353
|
Match = Struct.new(:captures)
|
353
354
|
|
@@ -373,7 +374,7 @@ end
|
|
373
374
|
Note that the above example might be over-engineered, as it can also be
|
374
375
|
expressed as:
|
375
376
|
|
376
|
-
```
|
377
|
+
```ruby
|
377
378
|
get // do
|
378
379
|
pass if request.path_info == "/index"
|
379
380
|
# ...
|
@@ -382,7 +383,7 @@ end
|
|
382
383
|
|
383
384
|
Or, using negative look ahead:
|
384
385
|
|
385
|
-
```
|
386
|
+
```ruby
|
386
387
|
get %r{^(?!/index$)} do
|
387
388
|
# ...
|
388
389
|
end
|
@@ -393,7 +394,7 @@ end
|
|
393
394
|
Static files are served from the `./public` directory. You can specify
|
394
395
|
a different location by setting the `:public_folder` option:
|
395
396
|
|
396
|
-
```
|
397
|
+
```ruby
|
397
398
|
set :public_folder, File.dirname(__FILE__) + '/static'
|
398
399
|
```
|
399
400
|
|
@@ -409,7 +410,7 @@ Use the `:static_cache_control` setting (see below) to add
|
|
409
410
|
Each template language is exposed via its own rendering method. These
|
410
411
|
methods simply return a string:
|
411
412
|
|
412
|
-
```
|
413
|
+
```ruby
|
413
414
|
get '/' do
|
414
415
|
erb :index
|
415
416
|
end
|
@@ -420,7 +421,7 @@ This renders `views/index.erb`.
|
|
420
421
|
Instead of a template name, you can also just pass in the template content
|
421
422
|
directly:
|
422
423
|
|
423
|
-
```
|
424
|
+
```ruby
|
424
425
|
get '/' do
|
425
426
|
code = "<%= Time.now %>"
|
426
427
|
erb code
|
@@ -429,7 +430,7 @@ end
|
|
429
430
|
|
430
431
|
Templates take a second argument, the options hash:
|
431
432
|
|
432
|
-
```
|
433
|
+
```ruby
|
433
434
|
get '/' do
|
434
435
|
erb :index, :layout => :post
|
435
436
|
end
|
@@ -441,7 +442,7 @@ This will render `views/index.erb` embedded in the
|
|
441
442
|
Any options not understood by Sinatra will be passed on to the template
|
442
443
|
engine:
|
443
444
|
|
444
|
-
```
|
445
|
+
```ruby
|
445
446
|
get '/' do
|
446
447
|
haml :index, :format => :html5
|
447
448
|
end
|
@@ -449,7 +450,7 @@ end
|
|
449
450
|
|
450
451
|
You can also set options per template language in general:
|
451
452
|
|
452
|
-
```
|
453
|
+
```ruby
|
453
454
|
set :haml, :format => :html5
|
454
455
|
|
455
456
|
get '/' do
|
@@ -514,7 +515,7 @@ Available Options:
|
|
514
515
|
Templates are assumed to be located directly under the `./views` directory. To
|
515
516
|
use a different views directory:
|
516
517
|
|
517
|
-
```
|
518
|
+
```ruby
|
518
519
|
set :views, settings.root + '/templates'
|
519
520
|
```
|
520
521
|
|
@@ -527,7 +528,7 @@ directly.
|
|
527
528
|
|
528
529
|
### Literal Templates
|
529
530
|
|
530
|
-
```
|
531
|
+
```ruby
|
531
532
|
get '/' do
|
532
533
|
haml '%div.title Hello World'
|
533
534
|
end
|
@@ -540,7 +541,7 @@ Renders the template string.
|
|
540
541
|
Some languages have multiple implementations. To specify what implementation
|
541
542
|
to use (and to be thread-safe), you should simply require it first:
|
542
543
|
|
543
|
-
```
|
544
|
+
```ruby
|
544
545
|
require 'rdiscount' # or require 'bluecloth'
|
545
546
|
get('/') { markdown :index }
|
546
547
|
```
|
@@ -608,7 +609,7 @@ It also takes a block for inline templates (see example).
|
|
608
609
|
<table>
|
609
610
|
<tr>
|
610
611
|
<td>Dependency</td>
|
611
|
-
<td><a href="http://nokogiri.org/" title="nokogiri">nokogiri</a></td>
|
612
|
+
<td><a href="http://www.nokogiri.org/" title="nokogiri">nokogiri</a></td>
|
612
613
|
</tr>
|
613
614
|
<tr>
|
614
615
|
<td>File Extension</td>
|
@@ -661,7 +662,7 @@ It also takes a block for inline templates (see example).
|
|
661
662
|
<table>
|
662
663
|
<tr>
|
663
664
|
<td>Dependency</td>
|
664
|
-
<td><a href="http://
|
665
|
+
<td><a href="http://lesscss.org/" title="less">less</a></td>
|
665
666
|
</tr>
|
666
667
|
<tr>
|
667
668
|
<td>File Extension</td>
|
@@ -678,7 +679,7 @@ It also takes a block for inline templates (see example).
|
|
678
679
|
<table>
|
679
680
|
<tr>
|
680
681
|
<td>Dependency</td>
|
681
|
-
<td><a href="http://
|
682
|
+
<td><a href="http://liquidmarkup.org/" title="liquid">liquid</a></td>
|
682
683
|
</tr>
|
683
684
|
<tr>
|
684
685
|
<td>File Extension</td>
|
@@ -700,7 +701,7 @@ template, you almost always want to pass locals to it.
|
|
700
701
|
<td>Dependency</td>
|
701
702
|
<td>
|
702
703
|
Anyone of:
|
703
|
-
<a href="https://github.com/
|
704
|
+
<a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
|
704
705
|
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
|
705
706
|
<a href="http://deveiate.org/projects/BlueCloth" title="BlueCloth">BlueCloth</a>,
|
706
707
|
<a href="http://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
|
@@ -721,13 +722,13 @@ It is not possible to call methods from markdown, nor to pass locals to it.
|
|
721
722
|
You therefore will usually use it in combination with another rendering
|
722
723
|
engine:
|
723
724
|
|
724
|
-
```
|
725
|
+
```ruby
|
725
726
|
erb :overview, :locals => { :text => markdown(:introduction) }
|
726
727
|
```
|
727
728
|
|
728
729
|
Note that you may also call the `markdown` method from within other templates:
|
729
730
|
|
730
|
-
```
|
731
|
+
```ruby
|
731
732
|
%h1 Hello From Haml!
|
732
733
|
%p= markdown(:greetings)
|
733
734
|
```
|
@@ -756,13 +757,13 @@ template than for the layout by passing the `:layout_engine` option.
|
|
756
757
|
It is not possible to call methods from textile, nor to pass locals to it. You
|
757
758
|
therefore will usually use it in combination with another rendering engine:
|
758
759
|
|
759
|
-
```
|
760
|
+
```ruby
|
760
761
|
erb :overview, :locals => { :text => textile(:introduction) }
|
761
762
|
```
|
762
763
|
|
763
764
|
Note that you may also call the `textile` method from within other templates:
|
764
765
|
|
765
|
-
```
|
766
|
+
```ruby
|
766
767
|
%h1 Hello From Haml!
|
767
768
|
%p= textile(:greetings)
|
768
769
|
```
|
@@ -791,13 +792,13 @@ template than for the layout by passing the `:layout_engine` option.
|
|
791
792
|
It is not possible to call methods from rdoc, nor to pass locals to it. You
|
792
793
|
therefore will usually use it in combination with another rendering engine:
|
793
794
|
|
794
|
-
```
|
795
|
+
```ruby
|
795
796
|
erb :overview, :locals => { :text => rdoc(:introduction) }
|
796
797
|
```
|
797
798
|
|
798
799
|
Note that you may also call the `rdoc` method from within other templates:
|
799
800
|
|
800
|
-
```
|
801
|
+
```ruby
|
801
802
|
%h1 Hello From Haml!
|
802
803
|
%p= rdoc(:greetings)
|
803
804
|
```
|
@@ -851,7 +852,7 @@ always want to pass locals to it.
|
|
851
852
|
<table>
|
852
853
|
<tr>
|
853
854
|
<td>Dependency</td>
|
854
|
-
<td><a href="http://markaby.github.
|
855
|
+
<td><a href="http://markaby.github.io/" title="Markaby">Markaby</a></td>
|
855
856
|
</tr>
|
856
857
|
<tr>
|
857
858
|
<td>File Extension</td>
|
@@ -919,13 +920,13 @@ It also takes a block for inline templates (see example).
|
|
919
920
|
It is not possible to call methods from creole, nor to pass locals to it. You
|
920
921
|
therefore will usually use it in combination with another rendering engine:
|
921
922
|
|
922
|
-
```
|
923
|
+
```ruby
|
923
924
|
erb :overview, :locals => { :text => creole(:introduction) }
|
924
925
|
```
|
925
926
|
|
926
927
|
Note that you may also call the `creole` method from within other templates:
|
927
928
|
|
928
|
-
```
|
929
|
+
```ruby
|
929
930
|
%h1 Hello From Haml!
|
930
931
|
%p= creole(:greetings)
|
931
932
|
```
|
@@ -955,13 +956,13 @@ It is not possible to call methods from MediaWiki markup, nor to pass locals to
|
|
955
956
|
it. You therefore will usually use it in combination with another rendering
|
956
957
|
engine:
|
957
958
|
|
958
|
-
```
|
959
|
+
```ruby
|
959
960
|
erb :overview, :locals => { :text => mediawiki(:introduction) }
|
960
961
|
```
|
961
962
|
|
962
963
|
Note that you may also call the `mediawiki` method from within other templates:
|
963
964
|
|
964
|
-
```
|
965
|
+
```ruby
|
965
966
|
%h1 Hello From Haml!
|
966
967
|
%p= mediawiki(:greetings)
|
967
968
|
```
|
@@ -1000,7 +1001,7 @@ template than for the layout by passing the `:layout_engine` option.
|
|
1000
1001
|
<tr>
|
1001
1002
|
<td>Dependency</td>
|
1002
1003
|
<td>
|
1003
|
-
<a href="https://github.com/
|
1004
|
+
<a href="https://github.com/forgecrafted/ruby-stylus" title="Ruby Stylus">
|
1004
1005
|
Stylus
|
1005
1006
|
</a> and a
|
1006
1007
|
<a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS">
|
@@ -1021,7 +1022,7 @@ template than for the layout by passing the `:layout_engine` option.
|
|
1021
1022
|
Before being able to use Stylus templates, you need to load `stylus` and
|
1022
1023
|
`stylus/tilt` first:
|
1023
1024
|
|
1024
|
-
```
|
1025
|
+
```ruby
|
1025
1026
|
require 'sinatra'
|
1026
1027
|
require 'stylus'
|
1027
1028
|
require 'stylus/tilt'
|
@@ -1059,7 +1060,7 @@ end
|
|
1059
1060
|
The template source is evaluated as a Ruby string, and the
|
1060
1061
|
resulting json variable is converted using `#to_json`:
|
1061
1062
|
|
1062
|
-
```
|
1063
|
+
```ruby
|
1063
1064
|
json = { :foo => 'bar' }
|
1064
1065
|
json[:baz] = key
|
1065
1066
|
```
|
@@ -1067,7 +1068,7 @@ json[:baz] = key
|
|
1067
1068
|
The `:callback` and `:variable` options can be used to decorate the rendered
|
1068
1069
|
object:
|
1069
1070
|
|
1070
|
-
```
|
1071
|
+
```javascript
|
1071
1072
|
var resource = {"foo":"bar","baz":"qux"};
|
1072
1073
|
present(resource);
|
1073
1074
|
```
|
@@ -1097,7 +1098,7 @@ pass locals to it. Layouts written in WLang and `yield` are supported, though.
|
|
1097
1098
|
Templates are evaluated within the same context as route handlers. Instance
|
1098
1099
|
variables set in route handlers are directly accessible by templates:
|
1099
1100
|
|
1100
|
-
```
|
1101
|
+
```ruby
|
1101
1102
|
get '/:id' do
|
1102
1103
|
@foo = Foo.find(params['id'])
|
1103
1104
|
haml '%h1= @foo.name'
|
@@ -1106,7 +1107,7 @@ end
|
|
1106
1107
|
|
1107
1108
|
Or, specify an explicit Hash of local variables:
|
1108
1109
|
|
1109
|
-
```
|
1110
|
+
```ruby
|
1110
1111
|
get '/:id' do
|
1111
1112
|
foo = Foo.find(params['id'])
|
1112
1113
|
haml '%h1= bar.name', :locals => { :bar => foo }
|
@@ -1122,7 +1123,7 @@ A layout is usually just a template that calls `yield`.
|
|
1122
1123
|
Such a template can be used either through the `:template` option as
|
1123
1124
|
described above, or it can be rendered with a block as follows:
|
1124
1125
|
|
1125
|
-
```
|
1126
|
+
```ruby
|
1126
1127
|
erb :post, :layout => false do
|
1127
1128
|
erb :index
|
1128
1129
|
end
|
@@ -1132,7 +1133,7 @@ This code is mostly equivalent to `erb :index, :layout => :post`.
|
|
1132
1133
|
|
1133
1134
|
Passing blocks to rendering methods is most useful for creating nested layouts:
|
1134
1135
|
|
1135
|
-
```
|
1136
|
+
```ruby
|
1136
1137
|
erb :main_layout, :layout => false do
|
1137
1138
|
erb :admin_layout do
|
1138
1139
|
erb :user
|
@@ -1142,7 +1143,7 @@ end
|
|
1142
1143
|
|
1143
1144
|
This can also be done in fewer lines of code with:
|
1144
1145
|
|
1145
|
-
```
|
1146
|
+
```ruby
|
1146
1147
|
erb :admin_layout, :layout => :main_layout do
|
1147
1148
|
erb :user
|
1148
1149
|
end
|
@@ -1155,7 +1156,7 @@ Currently, the following rendering methods accept a block: `erb`, `haml`,
|
|
1155
1156
|
|
1156
1157
|
Templates may be defined at the end of the source file:
|
1157
1158
|
|
1158
|
-
```
|
1159
|
+
```ruby
|
1159
1160
|
require 'sinatra'
|
1160
1161
|
|
1161
1162
|
get '/' do
|
@@ -1180,7 +1181,7 @@ have inline templates in other source files.
|
|
1180
1181
|
|
1181
1182
|
Templates may also be defined using the top-level `template` method:
|
1182
1183
|
|
1183
|
-
```
|
1184
|
+
```ruby
|
1184
1185
|
template :layout do
|
1185
1186
|
"%html\n =yield\n"
|
1186
1187
|
end
|
@@ -1199,7 +1200,7 @@ is rendered. You can individually disable layouts by passing
|
|
1199
1200
|
`:layout => false` or disable them by default via
|
1200
1201
|
`set :haml, :layout => false`:
|
1201
1202
|
|
1202
|
-
```
|
1203
|
+
```ruby
|
1203
1204
|
get '/' do
|
1204
1205
|
haml :index, :layout => !request.xhr?
|
1205
1206
|
end
|
@@ -1211,7 +1212,7 @@ To associate a file extension with a template engine, use
|
|
1211
1212
|
`Tilt.register`. For instance, if you like to use the file extension
|
1212
1213
|
`tt` for Textile templates, you can do the following:
|
1213
1214
|
|
1214
|
-
```
|
1215
|
+
```ruby
|
1215
1216
|
Tilt.register :tt, Tilt[:textile]
|
1216
1217
|
```
|
1217
1218
|
|
@@ -1219,7 +1220,7 @@ Tilt.register :tt, Tilt[:textile]
|
|
1219
1220
|
|
1220
1221
|
First, register your engine with Tilt, then create a rendering method:
|
1221
1222
|
|
1222
|
-
```
|
1223
|
+
```ruby
|
1223
1224
|
Tilt.register :myat, MyAwesomeTemplateEngine
|
1224
1225
|
|
1225
1226
|
helpers do
|
@@ -1239,7 +1240,7 @@ learn more about Tilt.
|
|
1239
1240
|
To implement your own template lookup mechanism you can write your
|
1240
1241
|
own `#find_template` method:
|
1241
1242
|
|
1242
|
-
```
|
1243
|
+
```ruby
|
1243
1244
|
configure do
|
1244
1245
|
set :views [ './views/a', './views/b' ]
|
1245
1246
|
end
|
@@ -1257,7 +1258,7 @@ Before filters are evaluated before each request within the same
|
|
1257
1258
|
context as the routes will be and can modify the request and response. Instance
|
1258
1259
|
variables set in filters are accessible by routes and templates:
|
1259
1260
|
|
1260
|
-
```
|
1261
|
+
```ruby
|
1261
1262
|
before do
|
1262
1263
|
@note = 'Hi!'
|
1263
1264
|
request.path_info = '/foo/bar/baz'
|
@@ -1273,7 +1274,7 @@ After filters are evaluated after each request within the same context as the
|
|
1273
1274
|
routes will be and can also modify the request and response. Instance variables
|
1274
1275
|
set in before filters and routes are accessible by after filters:
|
1275
1276
|
|
1276
|
-
```
|
1277
|
+
```ruby
|
1277
1278
|
after do
|
1278
1279
|
puts response.status
|
1279
1280
|
end
|
@@ -1286,7 +1287,7 @@ generated later on.
|
|
1286
1287
|
Filters optionally take a pattern, causing them to be evaluated only if the
|
1287
1288
|
request path matches that pattern:
|
1288
1289
|
|
1289
|
-
```
|
1290
|
+
```ruby
|
1290
1291
|
before '/protected/*' do
|
1291
1292
|
authenticate!
|
1292
1293
|
end
|
@@ -1298,7 +1299,7 @@ end
|
|
1298
1299
|
|
1299
1300
|
Like routes, filters also take conditions:
|
1300
1301
|
|
1301
|
-
```
|
1302
|
+
```ruby
|
1302
1303
|
before :agent => /Songbird/ do
|
1303
1304
|
# ...
|
1304
1305
|
end
|
@@ -1313,7 +1314,7 @@ end
|
|
1313
1314
|
Use the top-level `helpers` method to define helper methods for use in
|
1314
1315
|
route handlers and templates:
|
1315
1316
|
|
1316
|
-
```
|
1317
|
+
```ruby
|
1317
1318
|
helpers do
|
1318
1319
|
def bar(name)
|
1319
1320
|
"#{name}bar"
|
@@ -1327,7 +1328,7 @@ end
|
|
1327
1328
|
|
1328
1329
|
Alternatively, helper methods can be separately defined in a module:
|
1329
1330
|
|
1330
|
-
```
|
1331
|
+
```ruby
|
1331
1332
|
module FooUtils
|
1332
1333
|
def foo(name) "#{name}foo" end
|
1333
1334
|
end
|
@@ -1346,7 +1347,7 @@ The effect is the same as including the modules in the application class.
|
|
1346
1347
|
A session is used to keep state during requests. If activated, you have one
|
1347
1348
|
session hash per user session:
|
1348
1349
|
|
1349
|
-
```
|
1350
|
+
```ruby
|
1350
1351
|
enable :sessions
|
1351
1352
|
|
1352
1353
|
get '/' do
|
@@ -1364,7 +1365,7 @@ traffic, for instance). You can use any Rack session middleware: in order to
|
|
1364
1365
|
do so, do **not** call `enable :sessions`, but instead pull in your
|
1365
1366
|
middleware of choice as you would any other middleware:
|
1366
1367
|
|
1367
|
-
```
|
1368
|
+
```ruby
|
1368
1369
|
use Rack::Session::Pool, :expire_after => 2592000
|
1369
1370
|
|
1370
1371
|
get '/' do
|
@@ -1381,21 +1382,21 @@ secret. A random secret is generated for you by Sinatra. However, since this
|
|
1381
1382
|
secret will change with every start of your application, you might want to
|
1382
1383
|
set the secret yourself, so all your application instances share it:
|
1383
1384
|
|
1384
|
-
```
|
1385
|
+
```ruby
|
1385
1386
|
set :session_secret, 'super secret'
|
1386
1387
|
```
|
1387
1388
|
|
1388
1389
|
If you want to configure it further, you may also store a hash with options in
|
1389
1390
|
the `sessions` setting:
|
1390
1391
|
|
1391
|
-
```
|
1392
|
+
```ruby
|
1392
1393
|
set :sessions, :domain => 'foo.com'
|
1393
1394
|
```
|
1394
1395
|
|
1395
1396
|
To share your session across other apps on subdomains of foo.com, prefix the
|
1396
1397
|
domain with a *.* like this instead:
|
1397
1398
|
|
1398
|
-
```
|
1399
|
+
```ruby
|
1399
1400
|
set :sessions, :domain => '.foo.com'
|
1400
1401
|
```
|
1401
1402
|
|
@@ -1403,37 +1404,37 @@ set :sessions, :domain => '.foo.com'
|
|
1403
1404
|
|
1404
1405
|
To immediately stop a request within a filter or route use:
|
1405
1406
|
|
1406
|
-
```
|
1407
|
+
```ruby
|
1407
1408
|
halt
|
1408
1409
|
```
|
1409
1410
|
|
1410
1411
|
You can also specify the status when halting:
|
1411
1412
|
|
1412
|
-
```
|
1413
|
+
```ruby
|
1413
1414
|
halt 410
|
1414
1415
|
```
|
1415
1416
|
|
1416
1417
|
Or the body:
|
1417
1418
|
|
1418
|
-
```
|
1419
|
+
```ruby
|
1419
1420
|
halt 'this will be the body'
|
1420
1421
|
```
|
1421
1422
|
|
1422
1423
|
Or both:
|
1423
1424
|
|
1424
|
-
```
|
1425
|
+
```ruby
|
1425
1426
|
halt 401, 'go away!'
|
1426
1427
|
```
|
1427
1428
|
|
1428
1429
|
With headers:
|
1429
1430
|
|
1430
|
-
```
|
1431
|
+
```ruby
|
1431
1432
|
halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
|
1432
1433
|
```
|
1433
1434
|
|
1434
1435
|
It is of course possible to combine a template with `halt`:
|
1435
1436
|
|
1436
|
-
```
|
1437
|
+
```ruby
|
1437
1438
|
halt erb(:error)
|
1438
1439
|
```
|
1439
1440
|
|
@@ -1441,7 +1442,7 @@ halt erb(:error)
|
|
1441
1442
|
|
1442
1443
|
A route can punt processing to the next matching route using `pass`:
|
1443
1444
|
|
1444
|
-
```
|
1445
|
+
```ruby
|
1445
1446
|
get '/guess/:who' do
|
1446
1447
|
pass unless params['who'] == 'Frank'
|
1447
1448
|
'You got me!'
|
@@ -1460,7 +1461,7 @@ matching route. If no matching route is found, a 404 is returned.
|
|
1460
1461
|
Sometimes `pass` is not what you want, instead you would like to get the result
|
1461
1462
|
of calling another route. Simply use `call` to achieve this:
|
1462
1463
|
|
1463
|
-
```
|
1464
|
+
```ruby
|
1464
1465
|
get '/foo' do
|
1465
1466
|
status, headers, body = call env.merge("PATH_INFO" => '/bar')
|
1466
1467
|
[status, headers, body.map(&:upcase)]
|
@@ -1487,7 +1488,7 @@ set the body at an arbitrary point in the execution flow. You can do so with the
|
|
1487
1488
|
`body` helper method. If you do so, you can use that method from there on to
|
1488
1489
|
access the body:
|
1489
1490
|
|
1490
|
-
```
|
1491
|
+
```ruby
|
1491
1492
|
get '/foo' do
|
1492
1493
|
body "bar"
|
1493
1494
|
end
|
@@ -1502,7 +1503,7 @@ Rack handler (this can be used to implement streaming, see "Return Values").
|
|
1502
1503
|
|
1503
1504
|
Similar to the body, you can also set the status code and headers:
|
1504
1505
|
|
1505
|
-
```
|
1506
|
+
```ruby
|
1506
1507
|
get '/foo' do
|
1507
1508
|
status 418
|
1508
1509
|
headers \
|
@@ -1522,7 +1523,7 @@ the response body. In extreme examples, you want to keep sending data until
|
|
1522
1523
|
the client closes the connection. You can use the `stream` helper to avoid
|
1523
1524
|
creating your own wrapper:
|
1524
1525
|
|
1525
|
-
```
|
1526
|
+
```ruby
|
1526
1527
|
get '/' do
|
1527
1528
|
stream do |out|
|
1528
1529
|
out << "It's gonna be legen -\n"
|
@@ -1535,23 +1536,23 @@ end
|
|
1535
1536
|
```
|
1536
1537
|
|
1537
1538
|
This allows you to implement streaming APIs,
|
1538
|
-
[Server Sent Events](
|
1539
|
-
the basis for [WebSockets](
|
1539
|
+
[Server Sent Events](https://w3c.github.io/eventsource/), and can be used as
|
1540
|
+
the basis for [WebSockets](https://en.wikipedia.org/wiki/WebSocket). It can also be
|
1540
1541
|
used to increase throughput if some but not all content depends on a slow
|
1541
1542
|
resource.
|
1542
1543
|
|
1543
1544
|
Note that the streaming behavior, especially the number of concurrent requests,
|
1544
|
-
highly depends on the web server used to serve the application. Some servers
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1545
|
+
highly depends on the web server used to serve the application. Some servers
|
1546
|
+
might not even support streaming at all. If the server does not support
|
1547
|
+
streaming, the body will be sent all at once after the block passed to `stream`
|
1548
|
+
finishes executing. Streaming does not work at all with Shotgun.
|
1548
1549
|
|
1549
1550
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
1550
1551
|
the stream object, allowing you to close it at any later point in the
|
1551
1552
|
execution flow. This only works on evented servers, like Thin and Rainbows.
|
1552
1553
|
Other servers will still close the stream:
|
1553
1554
|
|
1554
|
-
```
|
1555
|
+
```ruby
|
1555
1556
|
# long polling
|
1556
1557
|
|
1557
1558
|
set :server, :thin
|
@@ -1584,7 +1585,7 @@ end
|
|
1584
1585
|
|
1585
1586
|
In the request scope, the `logger` helper exposes a `Logger` instance:
|
1586
1587
|
|
1587
|
-
```
|
1588
|
+
```ruby
|
1588
1589
|
get '/' do
|
1589
1590
|
logger.info "loading data"
|
1590
1591
|
# ...
|
@@ -1598,7 +1599,7 @@ you do not have to worry about it in your routes and filters.
|
|
1598
1599
|
Note that logging is only enabled for `Sinatra::Application` by default, so if
|
1599
1600
|
you inherit from `Sinatra::Base`, you probably want to enable it yourself:
|
1600
1601
|
|
1601
|
-
```
|
1602
|
+
```ruby
|
1602
1603
|
class MyApp < Sinatra::Base
|
1603
1604
|
configure :production, :development do
|
1604
1605
|
enable :logging
|
@@ -1616,7 +1617,7 @@ whatever it will find in `env['rack.logger']`.
|
|
1616
1617
|
When using `send_file` or static files you may have mime types Sinatra
|
1617
1618
|
doesn't understand. Use `mime_type` to register them by file extension:
|
1618
1619
|
|
1619
|
-
```
|
1620
|
+
```ruby
|
1620
1621
|
configure do
|
1621
1622
|
mime_type :foo, 'text/foo'
|
1622
1623
|
end
|
@@ -1624,7 +1625,7 @@ end
|
|
1624
1625
|
|
1625
1626
|
You can also use it with the `content_type` helper:
|
1626
1627
|
|
1627
|
-
```
|
1628
|
+
```ruby
|
1628
1629
|
get '/' do
|
1629
1630
|
content_type :foo
|
1630
1631
|
"foo foo foo"
|
@@ -1636,7 +1637,7 @@ end
|
|
1636
1637
|
For generating URLs you should use the `url` helper method, for instance, in
|
1637
1638
|
Haml:
|
1638
1639
|
|
1639
|
-
```
|
1640
|
+
```ruby
|
1640
1641
|
%a{:href => url('/foo')} foo
|
1641
1642
|
```
|
1642
1643
|
|
@@ -1648,7 +1649,7 @@ This method is also aliased to `to` (see below for an example).
|
|
1648
1649
|
|
1649
1650
|
You can trigger a browser redirect with the `redirect` helper method:
|
1650
1651
|
|
1651
|
-
```
|
1652
|
+
```ruby
|
1652
1653
|
get '/foo' do
|
1653
1654
|
redirect to('/bar')
|
1654
1655
|
end
|
@@ -1656,15 +1657,15 @@ end
|
|
1656
1657
|
|
1657
1658
|
Any additional parameters are handled like arguments passed to `halt`:
|
1658
1659
|
|
1659
|
-
```
|
1660
|
+
```ruby
|
1660
1661
|
redirect to('/bar'), 303
|
1661
|
-
redirect 'http://google.com', 'wrong place, buddy'
|
1662
|
+
redirect 'http://www.google.com/', 'wrong place, buddy'
|
1662
1663
|
```
|
1663
1664
|
|
1664
1665
|
You can also easily redirect back to the page the user came from with
|
1665
1666
|
`redirect back`:
|
1666
1667
|
|
1667
|
-
```
|
1668
|
+
```ruby
|
1668
1669
|
get '/foo' do
|
1669
1670
|
"<a href='/bar'>do something</a>"
|
1670
1671
|
end
|
@@ -1677,13 +1678,13 @@ end
|
|
1677
1678
|
|
1678
1679
|
To pass arguments with a redirect, either add them to the query:
|
1679
1680
|
|
1680
|
-
```
|
1681
|
+
```ruby
|
1681
1682
|
redirect to('/bar?sum=42')
|
1682
1683
|
```
|
1683
1684
|
|
1684
1685
|
Or use a session:
|
1685
1686
|
|
1686
|
-
```
|
1687
|
+
```ruby
|
1687
1688
|
enable :sessions
|
1688
1689
|
|
1689
1690
|
get '/foo' do
|
@@ -1702,7 +1703,7 @@ Setting your headers correctly is the foundation for proper HTTP caching.
|
|
1702
1703
|
|
1703
1704
|
You can easily set the Cache-Control header like this:
|
1704
1705
|
|
1705
|
-
```
|
1706
|
+
```ruby
|
1706
1707
|
get '/' do
|
1707
1708
|
cache_control :public
|
1708
1709
|
"cache it!"
|
@@ -1711,7 +1712,7 @@ end
|
|
1711
1712
|
|
1712
1713
|
Pro tip: Set up caching in a before filter:
|
1713
1714
|
|
1714
|
-
```
|
1715
|
+
```ruby
|
1715
1716
|
before do
|
1716
1717
|
cache_control :public, :must_revalidate, :max_age => 60
|
1717
1718
|
end
|
@@ -1720,7 +1721,7 @@ end
|
|
1720
1721
|
If you are using the `expires` helper to set the corresponding header,
|
1721
1722
|
`Cache-Control` will be set automatically for you:
|
1722
1723
|
|
1723
|
-
```
|
1724
|
+
```ruby
|
1724
1725
|
before do
|
1725
1726
|
expires 500, :public, :must_revalidate
|
1726
1727
|
end
|
@@ -1731,7 +1732,7 @@ It is recommended to call those helpers *before* doing any heavy lifting, as
|
|
1731
1732
|
they will immediately flush a response if the client already has the current
|
1732
1733
|
version in its cache:
|
1733
1734
|
|
1734
|
-
```
|
1735
|
+
```ruby
|
1735
1736
|
get "/article/:id" do
|
1736
1737
|
@article = Article.find params['id']
|
1737
1738
|
last_modified @article.updated_at
|
@@ -1741,9 +1742,9 @@ end
|
|
1741
1742
|
```
|
1742
1743
|
|
1743
1744
|
It is also possible to use a
|
1744
|
-
[weak ETag](
|
1745
|
+
[weak ETag](https://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation):
|
1745
1746
|
|
1746
|
-
```
|
1747
|
+
```ruby
|
1747
1748
|
etag @article.sha1, :weak
|
1748
1749
|
```
|
1749
1750
|
|
@@ -1751,7 +1752,7 @@ These helpers will not do any caching for you, but rather feed the necessary
|
|
1751
1752
|
information to your cache. If you are looking for a quick reverse-proxy caching
|
1752
1753
|
solution, try [rack-cache](https://github.com/rtomayko/rack-cache):
|
1753
1754
|
|
1754
|
-
```
|
1755
|
+
```ruby
|
1755
1756
|
require "rack/cache"
|
1756
1757
|
require "sinatra"
|
1757
1758
|
|
@@ -1774,7 +1775,7 @@ and idempotent (like put) requests are already in existence, whereas other
|
|
1774
1775
|
resources (for instance post requests) are treated as new resources. You
|
1775
1776
|
can change this behavior by passing in a `:new_resource` option:
|
1776
1777
|
|
1777
|
-
```
|
1778
|
+
```ruby
|
1778
1779
|
get '/create' do
|
1779
1780
|
etag '', :new_resource => true
|
1780
1781
|
Article.create
|
@@ -1784,7 +1785,7 @@ end
|
|
1784
1785
|
|
1785
1786
|
If you still want to use a weak ETag, pass in a `:kind` option:
|
1786
1787
|
|
1787
|
-
```
|
1788
|
+
```ruby
|
1788
1789
|
etag '', :new_resource => true, :kind => :weak
|
1789
1790
|
```
|
1790
1791
|
|
@@ -1793,7 +1794,7 @@ etag '', :new_resource => true, :kind => :weak
|
|
1793
1794
|
To return the contents of a file as the response, you can use the `send_file`
|
1794
1795
|
helper method:
|
1795
1796
|
|
1796
|
-
```
|
1797
|
+
```ruby
|
1797
1798
|
get '/' do
|
1798
1799
|
send_file 'foo.png'
|
1799
1800
|
end
|
@@ -1801,7 +1802,7 @@ end
|
|
1801
1802
|
|
1802
1803
|
It also takes options:
|
1803
1804
|
|
1804
|
-
```
|
1805
|
+
```ruby
|
1805
1806
|
send_file 'foo.png', :type => :jpg
|
1806
1807
|
```
|
1807
1808
|
|
@@ -1842,7 +1843,7 @@ The options are:
|
|
1842
1843
|
The incoming request object can be accessed from request level (filter, routes,
|
1843
1844
|
error handlers) through the `request` method:
|
1844
1845
|
|
1845
|
-
```
|
1846
|
+
```ruby
|
1846
1847
|
# app running on http://example.com/example
|
1847
1848
|
get '/foo' do
|
1848
1849
|
t = %w[text/css text/html application/javascript]
|
@@ -1877,7 +1878,7 @@ end
|
|
1877
1878
|
|
1878
1879
|
Some options, like `script_name` or `path_info`, can also be written:
|
1879
1880
|
|
1880
|
-
```
|
1881
|
+
```ruby
|
1881
1882
|
before { request.path_info = "/" }
|
1882
1883
|
|
1883
1884
|
get "/" do
|
@@ -1887,7 +1888,7 @@ end
|
|
1887
1888
|
|
1888
1889
|
The `request.body` is an IO or StringIO object:
|
1889
1890
|
|
1890
|
-
```
|
1891
|
+
```ruby
|
1891
1892
|
post "/api" do
|
1892
1893
|
request.body.rewind # in case someone already read it
|
1893
1894
|
data = JSON.parse request.body.read
|
@@ -1900,7 +1901,7 @@ end
|
|
1900
1901
|
You can use the `attachment` helper to tell the browser the response should be
|
1901
1902
|
stored on disk rather than displayed in the browser:
|
1902
1903
|
|
1903
|
-
```
|
1904
|
+
```ruby
|
1904
1905
|
get '/' do
|
1905
1906
|
attachment
|
1906
1907
|
"store it!"
|
@@ -1909,7 +1910,7 @@ end
|
|
1909
1910
|
|
1910
1911
|
You can also pass it a file name:
|
1911
1912
|
|
1912
|
-
```
|
1913
|
+
```ruby
|
1913
1914
|
get '/' do
|
1914
1915
|
attachment "info.txt"
|
1915
1916
|
"store it!"
|
@@ -1921,7 +1922,7 @@ end
|
|
1921
1922
|
Sinatra offers a `time_for` helper method that generates a Time object from the
|
1922
1923
|
given value. It is also able to convert `DateTime`, `Date` and similar classes:
|
1923
1924
|
|
1924
|
-
```
|
1925
|
+
```ruby
|
1925
1926
|
get '/' do
|
1926
1927
|
pass if Time.now > time_for('Dec 23, 2012')
|
1927
1928
|
"still time"
|
@@ -1932,7 +1933,7 @@ This method is used internally by `expires`, `last_modified` and akin. You can
|
|
1932
1933
|
therefore easily extend the behavior of those methods by overriding `time_for`
|
1933
1934
|
in your application:
|
1934
1935
|
|
1935
|
-
```
|
1936
|
+
```ruby
|
1936
1937
|
helpers do
|
1937
1938
|
def time_for(value)
|
1938
1939
|
case value
|
@@ -1954,7 +1955,7 @@ end
|
|
1954
1955
|
|
1955
1956
|
The `find_template` helper is used to find template files for rendering:
|
1956
1957
|
|
1957
|
-
```
|
1958
|
+
```ruby
|
1958
1959
|
find_template settings.views, 'foo', Tilt[:haml] do |file|
|
1959
1960
|
puts "could be #{file}"
|
1960
1961
|
end
|
@@ -1964,7 +1965,7 @@ This is not really useful. But it is useful that you can actually override this
|
|
1964
1965
|
method to hook in your own lookup mechanism. For instance, if you want to be
|
1965
1966
|
able to use more than one view directory:
|
1966
1967
|
|
1967
|
-
```
|
1968
|
+
```ruby
|
1968
1969
|
set :views, ['views', 'templates']
|
1969
1970
|
|
1970
1971
|
helpers do
|
@@ -1976,7 +1977,7 @@ end
|
|
1976
1977
|
|
1977
1978
|
Another example would be using different directories for different engines:
|
1978
1979
|
|
1979
|
-
```
|
1980
|
+
```ruby
|
1980
1981
|
set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
|
1981
1982
|
|
1982
1983
|
helpers do
|
@@ -2001,7 +2002,7 @@ method.
|
|
2001
2002
|
|
2002
2003
|
Run once, at startup, in any environment:
|
2003
2004
|
|
2004
|
-
```
|
2005
|
+
```ruby
|
2005
2006
|
configure do
|
2006
2007
|
# setting one option
|
2007
2008
|
set :option, 'value'
|
@@ -2023,7 +2024,7 @@ end
|
|
2023
2024
|
Run only when the environment (`RACK_ENV` environment variable) is set to
|
2024
2025
|
`:production`:
|
2025
2026
|
|
2026
|
-
```
|
2027
|
+
```ruby
|
2027
2028
|
configure :production do
|
2028
2029
|
...
|
2029
2030
|
end
|
@@ -2039,7 +2040,7 @@ end
|
|
2039
2040
|
|
2040
2041
|
You can access those options via `settings`:
|
2041
2042
|
|
2042
|
-
```
|
2043
|
+
```ruby
|
2043
2044
|
configure do
|
2044
2045
|
set :foo, 'bar'
|
2045
2046
|
end
|
@@ -2054,23 +2055,23 @@ end
|
|
2054
2055
|
### Configuring attack protection
|
2055
2056
|
|
2056
2057
|
Sinatra is using
|
2057
|
-
[Rack::Protection](https://github.com/
|
2058
|
+
[Rack::Protection](https://github.com/sinatra/rack-protection#readme) to defend
|
2058
2059
|
your application against common, opportunistic attacks. You can easily disable
|
2059
2060
|
this behavior (which will open up your application to tons of common
|
2060
2061
|
vulnerabilities):
|
2061
2062
|
|
2062
|
-
```
|
2063
|
+
```ruby
|
2063
2064
|
disable :protection
|
2064
2065
|
```
|
2065
2066
|
|
2066
2067
|
To skip a single defense layer, set `protection` to an options hash:
|
2067
2068
|
|
2068
|
-
```
|
2069
|
+
```ruby
|
2069
2070
|
set :protection, :except => :path_traversal
|
2070
2071
|
```
|
2071
2072
|
You can also hand in an array in order to disable a list of protections:
|
2072
2073
|
|
2073
|
-
```
|
2074
|
+
```ruby
|
2074
2075
|
set :protection, :except => [:path_traversal, :session_hijacking]
|
2075
2076
|
```
|
2076
2077
|
|
@@ -2079,7 +2080,7 @@ has been enabled. Sometimes you want to set up sessions on your own, though. In
|
|
2079
2080
|
that case you can get it to set up session based protections by passing the
|
2080
2081
|
`:session` option:
|
2081
2082
|
|
2082
|
-
```
|
2083
|
+
```ruby
|
2083
2084
|
use Rack::Session::Pool
|
2084
2085
|
set :protection, :session => true
|
2085
2086
|
```
|
@@ -2137,7 +2138,7 @@ set :protection, :session => true
|
|
2137
2138
|
Places a lock around every request, only running processing on request
|
2138
2139
|
per Ruby process concurrently.
|
2139
2140
|
</dd>
|
2140
|
-
<dd>Enabled if your app is not thread-safe. Disabled
|
2141
|
+
<dd>Enabled if your app is not thread-safe. Disabled by default.</dd>
|
2141
2142
|
|
2142
2143
|
<dt>method_override</dt>
|
2143
2144
|
<dd>
|
@@ -2152,7 +2153,7 @@ set :protection, :session => true
|
|
2152
2153
|
<dd>
|
2153
2154
|
Whether or not to insert <tt>request.script_name</tt> into redirects if no
|
2154
2155
|
absolute path is given. That way <tt>redirect '/foo'</tt> would behave like
|
2155
|
-
<tt>redirect to('/foo')</tt>. Disabled
|
2156
|
+
<tt>redirect to('/foo')</tt>. Disabled by default.
|
2156
2157
|
</dd>
|
2157
2158
|
|
2158
2159
|
<dt>protection</dt>
|
@@ -2224,7 +2225,7 @@ set :protection, :session => true
|
|
2224
2225
|
<dd>Disable when using a server able to do this on its own.</dd>
|
2225
2226
|
<dd>Disabling will boost performance.</dd>
|
2226
2227
|
<dd>
|
2227
|
-
Enabled
|
2228
|
+
Enabled by default in classic style, disabled for modular apps.
|
2228
2229
|
</dd>
|
2229
2230
|
|
2230
2231
|
<dt>static_cache_control</dt>
|
@@ -2271,14 +2272,14 @@ handlers display stack traces in your browser. In the `"production"` and
|
|
2271
2272
|
|
2272
2273
|
To run different environments, set the `RACK_ENV` environment variable:
|
2273
2274
|
|
2274
|
-
```
|
2275
|
+
```shell
|
2275
2276
|
RACK_ENV=production ruby my_app.rb
|
2276
2277
|
```
|
2277
2278
|
|
2278
2279
|
You can use predefined methods: `development?`, `test?` and `production?` to
|
2279
2280
|
check the current environment setting:
|
2280
2281
|
|
2281
|
-
```
|
2282
|
+
```ruby
|
2282
2283
|
get '/' do
|
2283
2284
|
if settings.development?
|
2284
2285
|
"development!"
|
@@ -2299,7 +2300,7 @@ means you get all the goodies it has to offer, like `haml`,
|
|
2299
2300
|
When a `Sinatra::NotFound` exception is raised, or the response's status
|
2300
2301
|
code is 404, the `not_found` handler is invoked:
|
2301
2302
|
|
2302
|
-
```
|
2303
|
+
```ruby
|
2303
2304
|
not_found do
|
2304
2305
|
'This is nowhere to be found.'
|
2305
2306
|
end
|
@@ -2317,7 +2318,7 @@ set :show_exceptions, :after_handler
|
|
2317
2318
|
|
2318
2319
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2319
2320
|
|
2320
|
-
```
|
2321
|
+
```ruby
|
2321
2322
|
error do
|
2322
2323
|
'Sorry there was a nasty error - ' + env['sinatra.error'].message
|
2323
2324
|
end
|
@@ -2325,7 +2326,7 @@ end
|
|
2325
2326
|
|
2326
2327
|
Custom errors:
|
2327
2328
|
|
2328
|
-
```
|
2329
|
+
```ruby
|
2329
2330
|
error MyCustomError do
|
2330
2331
|
'So what happened was...' + env['sinatra.error'].message
|
2331
2332
|
end
|
@@ -2333,7 +2334,7 @@ end
|
|
2333
2334
|
|
2334
2335
|
Then, if this happens:
|
2335
2336
|
|
2336
|
-
```
|
2337
|
+
```ruby
|
2337
2338
|
get '/' do
|
2338
2339
|
raise MyCustomError, 'something bad'
|
2339
2340
|
end
|
@@ -2347,7 +2348,7 @@ So what happened was... something bad
|
|
2347
2348
|
|
2348
2349
|
Alternatively, you can install an error handler for a status code:
|
2349
2350
|
|
2350
|
-
```
|
2351
|
+
```ruby
|
2351
2352
|
error 403 do
|
2352
2353
|
'Access forbidden'
|
2353
2354
|
end
|
@@ -2359,7 +2360,7 @@ end
|
|
2359
2360
|
|
2360
2361
|
Or a range:
|
2361
2362
|
|
2362
|
-
```
|
2363
|
+
```ruby
|
2363
2364
|
error 400..510 do
|
2364
2365
|
'Boom'
|
2365
2366
|
end
|
@@ -2380,7 +2381,7 @@ HTTP request/response to provide various types of common functionality.
|
|
2380
2381
|
Sinatra makes building Rack middleware pipelines a cinch via a top-level
|
2381
2382
|
`use` method:
|
2382
2383
|
|
2383
|
-
```
|
2384
|
+
```ruby
|
2384
2385
|
require 'sinatra'
|
2385
2386
|
require 'my_custom_middleware'
|
2386
2387
|
|
@@ -2393,11 +2394,11 @@ end
|
|
2393
2394
|
```
|
2394
2395
|
|
2395
2396
|
The semantics of `use` are identical to those defined for the
|
2396
|
-
[Rack::Builder](http://rubydoc.info/github/rack/rack/master/Rack/Builder) DSL
|
2397
|
+
[Rack::Builder](http://www.rubydoc.info/github/rack/rack/master/Rack/Builder) DSL
|
2397
2398
|
(most frequently used from rackup files). For example, the `use` method
|
2398
2399
|
accepts multiple/variable args as well as blocks:
|
2399
2400
|
|
2400
|
-
```
|
2401
|
+
```ruby
|
2401
2402
|
use Rack::Auth::Basic do |username, password|
|
2402
2403
|
username == 'admin' && password == 'secret'
|
2403
2404
|
end
|
@@ -2416,10 +2417,10 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2416
2417
|
## Testing
|
2417
2418
|
|
2418
2419
|
Sinatra tests can be written using any Rack-based testing library or framework.
|
2419
|
-
[Rack::Test](http://
|
2420
|
+
[Rack::Test](http://www.rubydoc.info/github/brynary/rack-test/master/frames)
|
2420
2421
|
is recommended:
|
2421
2422
|
|
2422
|
-
```
|
2423
|
+
```ruby
|
2423
2424
|
require 'my_sinatra_app'
|
2424
2425
|
require 'minitest/autorun'
|
2425
2426
|
require 'rack/test'
|
@@ -2461,7 +2462,7 @@ Sinatra extensions. The top-level assumes a micro-app style configuration
|
|
2461
2462
|
directories, logging, exception detail page, etc.). That's where
|
2462
2463
|
`Sinatra::Base` comes into play:
|
2463
2464
|
|
2464
|
-
```
|
2465
|
+
```ruby
|
2465
2466
|
require 'sinatra/base'
|
2466
2467
|
|
2467
2468
|
class MyApp < Sinatra::Base
|
@@ -2486,13 +2487,13 @@ those available via the top-level DSL. Most top-level apps can be converted to
|
|
2486
2487
|
|
2487
2488
|
`Sinatra::Base` is a blank slate. Most options are disabled by default,
|
2488
2489
|
including the built-in server. See
|
2489
|
-
[Configuring Settings](http://
|
2490
|
+
[Configuring Settings](http://www.sinatrarb.com/configuration.html)
|
2490
2491
|
for details on available options and their behavior. If you want
|
2491
2492
|
behavior more similar to when you define your app at the top level (also
|
2492
2493
|
known as Classic style), you
|
2493
2494
|
can subclass `Sinatra::Application`.
|
2494
2495
|
|
2495
|
-
```
|
2496
|
+
```ruby
|
2496
2497
|
require 'sinatra/base'
|
2497
2498
|
|
2498
2499
|
class MyApp < Sinatra::Application
|
@@ -2561,7 +2562,7 @@ different default settings:
|
|
2561
2562
|
<tr>
|
2562
2563
|
<td>static</td>
|
2563
2564
|
<td>true</td>
|
2564
|
-
<td>
|
2565
|
+
<td>File.exist?(public_folder)</td>
|
2565
2566
|
<td>true</td>
|
2566
2567
|
</tr>
|
2567
2568
|
</table>
|
@@ -2571,7 +2572,7 @@ different default settings:
|
|
2571
2572
|
There are two common options for starting a modular app, actively starting with
|
2572
2573
|
`run!`:
|
2573
2574
|
|
2574
|
-
```
|
2575
|
+
```ruby
|
2575
2576
|
# my_app.rb
|
2576
2577
|
require 'sinatra/base'
|
2577
2578
|
|
@@ -2585,13 +2586,13 @@ end
|
|
2585
2586
|
|
2586
2587
|
Start with:
|
2587
2588
|
|
2588
|
-
```
|
2589
|
+
```shell
|
2589
2590
|
ruby my_app.rb
|
2590
2591
|
```
|
2591
2592
|
|
2592
2593
|
Or with a `config.ru` file, which allows using any Rack handler:
|
2593
2594
|
|
2594
|
-
```
|
2595
|
+
```ruby
|
2595
2596
|
# config.ru (run with rackup)
|
2596
2597
|
require './my_app'
|
2597
2598
|
run MyApp
|
@@ -2599,7 +2600,7 @@ run MyApp
|
|
2599
2600
|
|
2600
2601
|
Run:
|
2601
2602
|
|
2602
|
-
```
|
2603
|
+
```shell
|
2603
2604
|
rackup -p 4567
|
2604
2605
|
```
|
2605
2606
|
|
@@ -2607,7 +2608,7 @@ rackup -p 4567
|
|
2607
2608
|
|
2608
2609
|
Write your app file:
|
2609
2610
|
|
2610
|
-
```
|
2611
|
+
```ruby
|
2611
2612
|
# app.rb
|
2612
2613
|
require 'sinatra'
|
2613
2614
|
|
@@ -2618,7 +2619,7 @@ end
|
|
2618
2619
|
|
2619
2620
|
And a corresponding `config.ru`:
|
2620
2621
|
|
2621
|
-
```
|
2622
|
+
```ruby
|
2622
2623
|
require './app'
|
2623
2624
|
run Sinatra::Application
|
2624
2625
|
```
|
@@ -2643,7 +2644,7 @@ can in turn be added in front of any Rack endpoint as middleware itself. This
|
|
2643
2644
|
endpoint could be another Sinatra application, or any other Rack-based
|
2644
2645
|
application (Rails/Ramaze/Camping/...):
|
2645
2646
|
|
2646
|
-
```
|
2647
|
+
```ruby
|
2647
2648
|
require 'sinatra/base'
|
2648
2649
|
|
2649
2650
|
class LoginScreen < Sinatra::Base
|
@@ -2679,7 +2680,7 @@ end
|
|
2679
2680
|
Sometimes you want to create new applications at runtime without having to
|
2680
2681
|
assign them to a constant. You can do this with `Sinatra.new`:
|
2681
2682
|
|
2682
|
-
```
|
2683
|
+
```ruby
|
2683
2684
|
require 'sinatra/base'
|
2684
2685
|
my_app = Sinatra.new { get('/') { "hi" } }
|
2685
2686
|
my_app.run!
|
@@ -2710,7 +2711,7 @@ your own library.
|
|
2710
2711
|
|
2711
2712
|
This also makes using Sinatra as middleware extremely easy:
|
2712
2713
|
|
2713
|
-
```
|
2714
|
+
```ruby
|
2714
2715
|
require 'sinatra/base'
|
2715
2716
|
|
2716
2717
|
use Sinatra do
|
@@ -2736,7 +2737,7 @@ single application class for all requests.
|
|
2736
2737
|
|
2737
2738
|
Options created via `set` are methods at class level:
|
2738
2739
|
|
2739
|
-
```
|
2740
|
+
```ruby
|
2740
2741
|
class MyApp < Sinatra::Base
|
2741
2742
|
# Hey, I'm in the application scope!
|
2742
2743
|
set :foo, 42
|
@@ -2769,7 +2770,7 @@ can access the `request` and `session` objects or call rendering methods like
|
|
2769
2770
|
`erb` or `haml`. You can access the application scope from within the request
|
2770
2771
|
scope via the `settings` helper:
|
2771
2772
|
|
2772
|
-
```
|
2773
|
+
```ruby
|
2773
2774
|
class MyApp < Sinatra::Base
|
2774
2775
|
# Hey, I'm in the application scope!
|
2775
2776
|
get '/define_route/:name' do
|
@@ -2788,7 +2789,7 @@ end
|
|
2788
2789
|
|
2789
2790
|
You have the request scope binding inside:
|
2790
2791
|
|
2791
|
-
* get, head, post, put, delete, options, patch, link
|
2792
|
+
* get, head, post, put, delete, options, patch, link and unlink blocks
|
2792
2793
|
* before and after filters
|
2793
2794
|
* helper methods
|
2794
2795
|
* templates/views
|
@@ -2815,7 +2816,7 @@ being [extending the main object](https://github.com/sinatra/sinatra/blob/ca0636
|
|
2815
2816
|
|
2816
2817
|
Sinatra applications can be run directly:
|
2817
2818
|
|
2818
|
-
```
|
2819
|
+
```shell
|
2819
2820
|
ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
|
2820
2821
|
```
|
2821
2822
|
|
@@ -2830,6 +2831,42 @@ Options are:
|
|
2830
2831
|
-x # turn on the mutex lock (default is off)
|
2831
2832
|
```
|
2832
2833
|
|
2834
|
+
### Multi-threading
|
2835
|
+
|
2836
|
+
_Paraphrasing from [this StackOverflow answer][so-answer] by Konstantin_
|
2837
|
+
|
2838
|
+
Sinatra doesn't impose any concurrency model, but leaves that to the
|
2839
|
+
underlying Rack handler (server) like Thin, Puma or WEBrick. Sinatra
|
2840
|
+
itself is thread-safe, so there won't be any problem if the Rack handler
|
2841
|
+
uses a threaded model of concurrency. This would mean that when starting
|
2842
|
+
the server, you'd have to specify the correct invocation method for the
|
2843
|
+
specific Rack handler. The following example is a demonstration of how
|
2844
|
+
to start a multi-threaded Thin server:
|
2845
|
+
|
2846
|
+
```ruby
|
2847
|
+
# app.rb
|
2848
|
+
|
2849
|
+
require 'sinatra/base'
|
2850
|
+
|
2851
|
+
class App < Sinatra::Base
|
2852
|
+
get '/' do
|
2853
|
+
"Hello, World"
|
2854
|
+
end
|
2855
|
+
end
|
2856
|
+
|
2857
|
+
App.run!
|
2858
|
+
|
2859
|
+
```
|
2860
|
+
|
2861
|
+
To start the server, the command would be:
|
2862
|
+
|
2863
|
+
```shell
|
2864
|
+
thin --threaded start
|
2865
|
+
```
|
2866
|
+
|
2867
|
+
|
2868
|
+
[so-answer]: http://stackoverflow.com/questions/6278817/is-sinatra-multi-threaded/6282999#6282999)
|
2869
|
+
|
2833
2870
|
## Requirement
|
2834
2871
|
|
2835
2872
|
The following Ruby versions are officially supported:
|
@@ -2907,7 +2944,7 @@ application against the master branch, it should be rather stable.
|
|
2907
2944
|
|
2908
2945
|
We also push out prerelease gems from time to time, so you can do a
|
2909
2946
|
|
2910
|
-
```
|
2947
|
+
```shell
|
2911
2948
|
gem install sinatra --pre
|
2912
2949
|
```
|
2913
2950
|
|
@@ -2916,11 +2953,11 @@ to get some of the latest features.
|
|
2916
2953
|
### With Bundler
|
2917
2954
|
|
2918
2955
|
If you want to run your application with the latest Sinatra, using
|
2919
|
-
[Bundler](http://
|
2956
|
+
[Bundler](http://bundler.io) is the recommended way.
|
2920
2957
|
|
2921
2958
|
First, install bundler, if you haven't:
|
2922
2959
|
|
2923
|
-
```
|
2960
|
+
```shell
|
2924
2961
|
gem install bundler
|
2925
2962
|
```
|
2926
2963
|
|
@@ -2941,7 +2978,7 @@ fetched and added by Bundler.
|
|
2941
2978
|
|
2942
2979
|
Now you can run your app like this:
|
2943
2980
|
|
2944
|
-
```
|
2981
|
+
```shell
|
2945
2982
|
bundle exec ruby myapp.rb
|
2946
2983
|
```
|
2947
2984
|
|
@@ -2950,7 +2987,7 @@ bundle exec ruby myapp.rb
|
|
2950
2987
|
Create a local clone and run your app with the `sinatra/lib` directory
|
2951
2988
|
on the `$LOAD_PATH`:
|
2952
2989
|
|
2953
|
-
```
|
2990
|
+
```shell
|
2954
2991
|
cd myapp
|
2955
2992
|
git clone git://github.com/sinatra/sinatra.git
|
2956
2993
|
ruby -I sinatra/lib myapp.rb
|
@@ -2958,7 +2995,7 @@ ruby -I sinatra/lib myapp.rb
|
|
2958
2995
|
|
2959
2996
|
To update the Sinatra sources in the future:
|
2960
2997
|
|
2961
|
-
```
|
2998
|
+
```shell
|
2962
2999
|
cd myapp/sinatra
|
2963
3000
|
git pull
|
2964
3001
|
```
|
@@ -2967,7 +3004,7 @@ git pull
|
|
2967
3004
|
|
2968
3005
|
You can build the gem on your own:
|
2969
3006
|
|
2970
|
-
```
|
3007
|
+
```shell
|
2971
3008
|
git clone git://github.com/sinatra/sinatra.git
|
2972
3009
|
cd sinatra
|
2973
3010
|
rake sinatra.gemspec
|
@@ -2976,7 +3013,7 @@ rake install
|
|
2976
3013
|
|
2977
3014
|
If you install gems as root, the last step should be:
|
2978
3015
|
|
2979
|
-
```
|
3016
|
+
```shell
|
2980
3017
|
sudo rake install
|
2981
3018
|
```
|
2982
3019
|
|
@@ -2991,14 +3028,16 @@ SemVerTag.
|
|
2991
3028
|
news, and links to other resources.
|
2992
3029
|
* [Contributing](http://www.sinatrarb.com/contributing) - Find a bug? Need
|
2993
3030
|
help? Have a patch?
|
2994
|
-
* [Issue tracker](
|
2995
|
-
* [Twitter](
|
3031
|
+
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
3032
|
+
* [Twitter](https://twitter.com/sinatra)
|
2996
3033
|
* [Mailing List](http://groups.google.com/group/sinatrarb/topics)
|
2997
3034
|
* IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on http://freenode.net
|
3035
|
+
* [Sinatra & Friends](https://sinatrarb.slack.com) on Slack and see
|
3036
|
+
[here](https://sinatra-slack.herokuapp.com/) for an invite.
|
2998
3037
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book/) Cookbook Tutorial
|
2999
3038
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) Community
|
3000
3039
|
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](
|
3040
|
+
* API documentation for the [latest release](http://www.rubydoc.info/gems/sinatra)
|
3041
|
+
or the [current HEAD](http://www.rubydoc.info/github/sinatra/sinatra) on
|
3042
|
+
http://www.rubydoc.info/
|
3043
|
+
* [CI server](https://travis-ci.org/sinatra/sinatra)
|