sinatra 2.1.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AUTHORS.md +14 -8
- data/CHANGELOG.md +251 -2
- data/CONTRIBUTING.md +11 -11
- data/Gemfile +55 -69
- data/MAINTENANCE.md +3 -16
- data/README.md +262 -529
- data/Rakefile +82 -79
- data/SECURITY.md +1 -1
- data/VERSION +1 -1
- data/examples/chat.rb +25 -12
- data/examples/lifecycle_events.rb +20 -0
- data/examples/simple.rb +2 -0
- data/examples/stream.ru +2 -2
- data/lib/sinatra/base.rb +531 -384
- data/lib/sinatra/indifferent_hash.rb +48 -40
- data/lib/sinatra/main.rb +18 -16
- data/lib/sinatra/middleware/logger.rb +21 -0
- data/lib/sinatra/show_exceptions.rb +17 -15
- data/lib/sinatra/version.rb +3 -1
- data/lib/sinatra.rb +2 -0
- data/sinatra.gemspec +40 -41
- metadata +60 -43
- data/README.de.md +0 -3239
- data/README.es.md +0 -3202
- data/README.fr.md +0 -3111
- data/README.hu.md +0 -728
- data/README.ja.md +0 -2814
- data/README.ko.md +0 -2967
- data/README.malayalam.md +0 -3141
- data/README.pt-br.md +0 -3787
- data/README.pt-pt.md +0 -791
- data/README.ru.md +0 -3207
- data/README.zh.md +0 -2934
- data/examples/rainbows.conf +0 -3
- data/examples/rainbows.rb +0 -20
data/README.md
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# Sinatra
|
2
2
|
|
3
|
-
[](
|
4
|
-
[](https://dependabot.com/compatibility-score.html?dependency-name=sinatra&package-manager=bundler&version-scheme=semver)
|
3
|
+
[](https://badge.fury.io/rb/sinatra)
|
4
|
+
[](https://github.com/sinatra/sinatra/actions/workflows/test.yml)
|
6
5
|
|
7
6
|
Sinatra is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for
|
8
7
|
quickly creating web applications in Ruby with minimal effort:
|
@@ -16,10 +15,10 @@ get '/' do
|
|
16
15
|
end
|
17
16
|
```
|
18
17
|
|
19
|
-
Install the
|
18
|
+
Install the gems needed:
|
20
19
|
|
21
20
|
```shell
|
22
|
-
gem install sinatra
|
21
|
+
gem install sinatra rackup puma
|
23
22
|
```
|
24
23
|
|
25
24
|
And run with:
|
@@ -31,101 +30,95 @@ ruby myapp.rb
|
|
31
30
|
View at: [http://localhost:4567](http://localhost:4567)
|
32
31
|
|
33
32
|
The code you changed will not take effect until you restart the server.
|
34
|
-
Please restart the server every time you change or use
|
35
|
-
[
|
33
|
+
Please restart the server every time you change or use a code reloader
|
34
|
+
like [rerun](https://github.com/alexch/rerun) or
|
35
|
+
[rack-unreloader](https://github.com/jeremyevans/rack-unreloader).
|
36
36
|
|
37
37
|
It is recommended to also run `gem install puma`, which Sinatra will
|
38
38
|
pick up if available.
|
39
39
|
|
40
40
|
## Table of Contents
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
* [Command Line](#command-line)
|
123
|
-
* [Multi-threading](#multi-threading)
|
124
|
-
* [Requirement](#requirement)
|
125
|
-
* [The Bleeding Edge](#the-bleeding-edge)
|
126
|
-
* [With Bundler](#with-bundler)
|
127
|
-
* [Versioning](#versioning)
|
128
|
-
* [Further Reading](#further-reading)
|
42
|
+
- [Sinatra](#sinatra)
|
43
|
+
- [Table of Contents](#table-of-contents)
|
44
|
+
- [Routes](#routes)
|
45
|
+
- [Conditions](#conditions)
|
46
|
+
- [Return Values](#return-values)
|
47
|
+
- [Custom Route Matchers](#custom-route-matchers)
|
48
|
+
- [Static Files](#static-files)
|
49
|
+
- [Views / Templates](#views--templates)
|
50
|
+
- [Literal Templates](#literal-templates)
|
51
|
+
- [Available Template Languages](#available-template-languages)
|
52
|
+
- [Haml Templates](#haml-templates)
|
53
|
+
- [Erb Templates](#erb-templates)
|
54
|
+
- [Builder Templates](#builder-templates)
|
55
|
+
- [Nokogiri Templates](#nokogiri-templates)
|
56
|
+
- [Sass Templates](#sass-templates)
|
57
|
+
- [Scss Templates](#scss-templates)
|
58
|
+
- [Liquid Templates](#liquid-templates)
|
59
|
+
- [Markdown Templates](#markdown-templates)
|
60
|
+
- [RDoc Templates](#rdoc-templates)
|
61
|
+
- [AsciiDoc Templates](#asciidoc-templates)
|
62
|
+
- [Markaby Templates](#markaby-templates)
|
63
|
+
- [RABL Templates](#rabl-templates)
|
64
|
+
- [Slim Templates](#slim-templates)
|
65
|
+
- [Yajl Templates](#yajl-templates)
|
66
|
+
- [Accessing Variables in Templates](#accessing-variables-in-templates)
|
67
|
+
- [Templates with `yield` and nested layouts](#templates-with-yield-and-nested-layouts)
|
68
|
+
- [Inline Templates](#inline-templates)
|
69
|
+
- [Named Templates](#named-templates)
|
70
|
+
- [Associating File Extensions](#associating-file-extensions)
|
71
|
+
- [Adding Your Own Template Engine](#adding-your-own-template-engine)
|
72
|
+
- [Using Custom Logic for Template Lookup](#using-custom-logic-for-template-lookup)
|
73
|
+
- [Filters](#filters)
|
74
|
+
- [Helpers](#helpers)
|
75
|
+
- [Using Sessions](#using-sessions)
|
76
|
+
- [Session Secret Security](#session-secret-security)
|
77
|
+
- [Session Config](#session-config)
|
78
|
+
- [Choosing Your Own Session Middleware](#choosing-your-own-session-middleware)
|
79
|
+
- [Halting](#halting)
|
80
|
+
- [Passing](#passing)
|
81
|
+
- [Triggering Another Route](#triggering-another-route)
|
82
|
+
- [Setting Body, Status Code, and Headers](#setting-body-status-code-and-headers)
|
83
|
+
- [Streaming Responses](#streaming-responses)
|
84
|
+
- [Logging](#logging)
|
85
|
+
- [Mime Types](#mime-types)
|
86
|
+
- [Generating URLs](#generating-urls)
|
87
|
+
- [Browser Redirect](#browser-redirect)
|
88
|
+
- [Cache Control](#cache-control)
|
89
|
+
- [Sending Files](#sending-files)
|
90
|
+
- [Accessing the Request Object](#accessing-the-request-object)
|
91
|
+
- [Attachments](#attachments)
|
92
|
+
- [Dealing with Date and Time](#dealing-with-date-and-time)
|
93
|
+
- [Looking Up Template Files](#looking-up-template-files)
|
94
|
+
- [Configuration](#configuration)
|
95
|
+
- [Configuring attack protection](#configuring-attack-protection)
|
96
|
+
- [Available Settings](#available-settings)
|
97
|
+
- [Lifecycle Events](#lifecycle-events)
|
98
|
+
- [Environments](#environments)
|
99
|
+
- [Error Handling](#error-handling)
|
100
|
+
- [Not Found](#not-found)
|
101
|
+
- [Error](#error)
|
102
|
+
- [Rack Middleware](#rack-middleware)
|
103
|
+
- [Testing](#testing)
|
104
|
+
- [Sinatra::Base - Middleware, Libraries, and Modular Apps](#sinatrabase---middleware-libraries-and-modular-apps)
|
105
|
+
- [Modular vs. Classic Style](#modular-vs-classic-style)
|
106
|
+
- [Serving a Modular Application](#serving-a-modular-application)
|
107
|
+
- [Using a Classic Style Application with a config.ru](#using-a-classic-style-application-with-a-configru)
|
108
|
+
- [When to use a config.ru?](#when-to-use-a-configru)
|
109
|
+
- [Using Sinatra as Middleware](#using-sinatra-as-middleware)
|
110
|
+
- [Dynamic Application Creation](#dynamic-application-creation)
|
111
|
+
- [Scopes and Binding](#scopes-and-binding)
|
112
|
+
- [Application/Class Scope](#applicationclass-scope)
|
113
|
+
- [Request/Instance Scope](#requestinstance-scope)
|
114
|
+
- [Delegation Scope](#delegation-scope)
|
115
|
+
- [Command Line](#command-line)
|
116
|
+
- [Multi-threading](#multi-threading)
|
117
|
+
- [Requirement](#requirement)
|
118
|
+
- [The Bleeding Edge](#the-bleeding-edge)
|
119
|
+
- [With Bundler](#with-bundler)
|
120
|
+
- [Versioning](#versioning)
|
121
|
+
- [Further Reading](#further-reading)
|
129
122
|
|
130
123
|
## Routes
|
131
124
|
|
@@ -344,11 +337,11 @@ end
|
|
344
337
|
## Return Values
|
345
338
|
|
346
339
|
The return value of a route block determines at least the response body
|
347
|
-
passed on to the HTTP client
|
340
|
+
passed on to the HTTP client or at least the next middleware in the
|
348
341
|
Rack stack. Most commonly, this is a string, as in the above examples.
|
349
342
|
But other values are also accepted.
|
350
343
|
|
351
|
-
You can return
|
344
|
+
You can return an object that would either be a valid Rack response, Rack
|
352
345
|
body object or HTTP status code:
|
353
346
|
|
354
347
|
* An Array with three elements: `[status (Integer), headers (Hash), response
|
@@ -372,7 +365,7 @@ get('/') { Stream.new }
|
|
372
365
|
```
|
373
366
|
|
374
367
|
You can also use the `stream` helper method ([described below](#streaming-responses)) to reduce
|
375
|
-
|
368
|
+
boilerplate and embed the streaming logic in the route.
|
376
369
|
|
377
370
|
## Custom Route Matchers
|
378
371
|
|
@@ -382,15 +375,16 @@ stop there. You can easily define your own matchers:
|
|
382
375
|
|
383
376
|
```ruby
|
384
377
|
class AllButPattern
|
385
|
-
Match = Struct.new(:captures)
|
386
|
-
|
387
378
|
def initialize(except)
|
388
|
-
@except
|
389
|
-
|
379
|
+
@except = except
|
380
|
+
end
|
381
|
+
|
382
|
+
def to_pattern(options)
|
383
|
+
return self
|
390
384
|
end
|
391
385
|
|
392
|
-
def
|
393
|
-
|
386
|
+
def params(route)
|
387
|
+
return {} unless @except === route
|
394
388
|
end
|
395
389
|
end
|
396
390
|
|
@@ -407,20 +401,12 @@ Note that the above example might be over-engineered, as it can also be
|
|
407
401
|
expressed as:
|
408
402
|
|
409
403
|
```ruby
|
410
|
-
get
|
404
|
+
get /.*/ do
|
411
405
|
pass if request.path_info == "/index"
|
412
406
|
# ...
|
413
407
|
end
|
414
408
|
```
|
415
409
|
|
416
|
-
Or, using negative look ahead:
|
417
|
-
|
418
|
-
```ruby
|
419
|
-
get %r{(?!/index)} do
|
420
|
-
# ...
|
421
|
-
end
|
422
|
-
```
|
423
|
-
|
424
410
|
## Static Files
|
425
411
|
|
426
412
|
Static files are served from the `./public` directory. You can specify
|
@@ -584,7 +570,7 @@ Some languages have multiple implementations. To specify what implementation
|
|
584
570
|
to use (and to be thread-safe), you should simply require it first:
|
585
571
|
|
586
572
|
```ruby
|
587
|
-
require 'rdiscount'
|
573
|
+
require 'rdiscount'
|
588
574
|
get('/') { markdown :index }
|
589
575
|
```
|
590
576
|
|
@@ -612,14 +598,12 @@ get('/') { markdown :index }
|
|
612
598
|
<td>Dependency</td>
|
613
599
|
<td>
|
614
600
|
<a href="https://github.com/jeremyevans/erubi" title="erubi">erubi</a>
|
615
|
-
or <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a>
|
616
601
|
or erb (included in Ruby)
|
617
602
|
</td>
|
618
603
|
</tr>
|
619
604
|
<tr>
|
620
605
|
<td>File Extensions</td>
|
621
|
-
<td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubi</tt> (Erubi only)
|
622
|
-
or <tt>.erubis</tt> (Erubis only)</td>
|
606
|
+
<td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubi</tt> (Erubi only)</td>
|
623
607
|
</tr>
|
624
608
|
<tr>
|
625
609
|
<td>Example</td>
|
@@ -672,7 +656,7 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
672
656
|
<table>
|
673
657
|
<tr>
|
674
658
|
<td>Dependency</td>
|
675
|
-
<td><a href="https://
|
659
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
676
660
|
</tr>
|
677
661
|
<tr>
|
678
662
|
<td>File Extension</td>
|
@@ -684,12 +668,12 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
684
668
|
</tr>
|
685
669
|
</table>
|
686
670
|
|
687
|
-
####
|
671
|
+
#### Scss Templates
|
688
672
|
|
689
673
|
<table>
|
690
674
|
<tr>
|
691
675
|
<td>Dependency</td>
|
692
|
-
<td><a href="https://
|
676
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
693
677
|
</tr>
|
694
678
|
<tr>
|
695
679
|
<td>File Extension</td>
|
@@ -701,23 +685,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
701
685
|
</tr>
|
702
686
|
</table>
|
703
687
|
|
704
|
-
#### Less Templates
|
705
|
-
|
706
|
-
<table>
|
707
|
-
<tr>
|
708
|
-
<td>Dependency</td>
|
709
|
-
<td><a href="http://lesscss.org/" title="less">less</a></td>
|
710
|
-
</tr>
|
711
|
-
<tr>
|
712
|
-
<td>File Extension</td>
|
713
|
-
<td><tt>.less</tt></td>
|
714
|
-
</tr>
|
715
|
-
<tr>
|
716
|
-
<td>Example</td>
|
717
|
-
<td><tt>less :stylesheet</tt></td>
|
718
|
-
</tr>
|
719
|
-
</table>
|
720
|
-
|
721
688
|
#### Liquid Templates
|
722
689
|
|
723
690
|
<table>
|
@@ -747,9 +714,7 @@ template, you almost always want to pass locals to it.
|
|
747
714
|
Anyone of:
|
748
715
|
<a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
|
749
716
|
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
|
750
|
-
<a href="https://github.com/ged/bluecloth" title="BlueCloth">BlueCloth</a>,
|
751
717
|
<a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
|
752
|
-
<a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
|
753
718
|
<a href="https://github.com/gjtorikian/commonmarker" title="commonmarker">commonmarker</a>
|
754
719
|
<a href="https://github.com/alphabetum/pandoc-ruby" title="pandoc">pandoc</a>
|
755
720
|
</td>
|
@@ -784,42 +749,6 @@ Since you cannot call Ruby from Markdown, you cannot use layouts written in
|
|
784
749
|
Markdown. However, it is possible to use another rendering engine for the
|
785
750
|
template than for the layout by passing the `:layout_engine` option.
|
786
751
|
|
787
|
-
#### Textile Templates
|
788
|
-
|
789
|
-
<table>
|
790
|
-
<tr>
|
791
|
-
<td>Dependency</td>
|
792
|
-
<td><a href="http://redcloth.org/" title="RedCloth">RedCloth</a></td>
|
793
|
-
</tr>
|
794
|
-
<tr>
|
795
|
-
<td>File Extension</td>
|
796
|
-
<td><tt>.textile</tt></td>
|
797
|
-
</tr>
|
798
|
-
<tr>
|
799
|
-
<td>Example</td>
|
800
|
-
<td><tt>textile :index, :layout_engine => :erb</tt></td>
|
801
|
-
</tr>
|
802
|
-
</table>
|
803
|
-
|
804
|
-
It is not possible to call methods from Textile, nor to pass locals to
|
805
|
-
it. You therefore will usually use it in combination with another
|
806
|
-
rendering engine:
|
807
|
-
|
808
|
-
```ruby
|
809
|
-
erb :overview, :locals => { :text => textile(:introduction) }
|
810
|
-
```
|
811
|
-
|
812
|
-
Note that you may also call the `textile` method from within other templates:
|
813
|
-
|
814
|
-
```ruby
|
815
|
-
%h1 Hello From Haml!
|
816
|
-
%p= textile(:greetings)
|
817
|
-
```
|
818
|
-
|
819
|
-
Since you cannot call Ruby from Textile, you cannot use layouts written in
|
820
|
-
Textile. However, it is possible to use another rendering engine for the
|
821
|
-
template than for the layout by passing the `:layout_engine` option.
|
822
|
-
|
823
752
|
#### RDoc Templates
|
824
753
|
|
825
754
|
<table>
|
@@ -875,26 +804,6 @@ template than for the layout by passing the `:layout_engine` option.
|
|
875
804
|
Since you cannot call Ruby methods directly from an AsciiDoc template, you
|
876
805
|
almost always want to pass locals to it.
|
877
806
|
|
878
|
-
#### Radius Templates
|
879
|
-
|
880
|
-
<table>
|
881
|
-
<tr>
|
882
|
-
<td>Dependency</td>
|
883
|
-
<td><a href="https://github.com/jlong/radius" title="Radius">Radius</a></td>
|
884
|
-
</tr>
|
885
|
-
<tr>
|
886
|
-
<td>File Extension</td>
|
887
|
-
<td><tt>.radius</tt></td>
|
888
|
-
</tr>
|
889
|
-
<tr>
|
890
|
-
<td>Example</td>
|
891
|
-
<td><tt>radius :index, :locals => { :key => 'value' }</tt></td>
|
892
|
-
</tr>
|
893
|
-
</table>
|
894
|
-
|
895
|
-
Since you cannot call Ruby methods directly from a Radius template, you
|
896
|
-
almost always want to pass locals to it.
|
897
|
-
|
898
807
|
#### Markaby Templates
|
899
808
|
|
900
809
|
<table>
|
@@ -936,7 +845,7 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
936
845
|
<table>
|
937
846
|
<tr>
|
938
847
|
<td>Dependency</td>
|
939
|
-
<td><a href="
|
848
|
+
<td><a href="https://slim-template.github.io/" title="Slim Lang">Slim Lang</a></td>
|
940
849
|
</tr>
|
941
850
|
<tr>
|
942
851
|
<td>File Extension</td>
|
@@ -948,139 +857,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
948
857
|
</tr>
|
949
858
|
</table>
|
950
859
|
|
951
|
-
#### Creole Templates
|
952
|
-
|
953
|
-
<table>
|
954
|
-
<tr>
|
955
|
-
<td>Dependency</td>
|
956
|
-
<td><a href="https://github.com/minad/creole" title="Creole">Creole</a></td>
|
957
|
-
</tr>
|
958
|
-
<tr>
|
959
|
-
<td>File Extension</td>
|
960
|
-
<td><tt>.creole</tt></td>
|
961
|
-
</tr>
|
962
|
-
<tr>
|
963
|
-
<td>Example</td>
|
964
|
-
<td><tt>creole :wiki, :layout_engine => :erb</tt></td>
|
965
|
-
</tr>
|
966
|
-
</table>
|
967
|
-
|
968
|
-
It is not possible to call methods from Creole, nor to pass locals to it. You
|
969
|
-
therefore will usually use it in combination with another rendering engine:
|
970
|
-
|
971
|
-
```ruby
|
972
|
-
erb :overview, :locals => { :text => creole(:introduction) }
|
973
|
-
```
|
974
|
-
|
975
|
-
Note that you may also call the `creole` method from within other templates:
|
976
|
-
|
977
|
-
```ruby
|
978
|
-
%h1 Hello From Haml!
|
979
|
-
%p= creole(:greetings)
|
980
|
-
```
|
981
|
-
|
982
|
-
Since you cannot call Ruby from Creole, you cannot use layouts written in
|
983
|
-
Creole. However, it is possible to use another rendering engine for the
|
984
|
-
template than for the layout by passing the `:layout_engine` option.
|
985
|
-
|
986
|
-
#### MediaWiki Templates
|
987
|
-
|
988
|
-
<table>
|
989
|
-
<tr>
|
990
|
-
<td>Dependency</td>
|
991
|
-
<td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td>
|
992
|
-
</tr>
|
993
|
-
<tr>
|
994
|
-
<td>File Extension</td>
|
995
|
-
<td><tt>.mediawiki</tt> and <tt>.mw</tt></td>
|
996
|
-
</tr>
|
997
|
-
<tr>
|
998
|
-
<td>Example</td>
|
999
|
-
<td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td>
|
1000
|
-
</tr>
|
1001
|
-
</table>
|
1002
|
-
|
1003
|
-
It is not possible to call methods from MediaWiki markup, nor to pass
|
1004
|
-
locals to it. You therefore will usually use it in combination with
|
1005
|
-
another rendering engine:
|
1006
|
-
|
1007
|
-
```ruby
|
1008
|
-
erb :overview, :locals => { :text => mediawiki(:introduction) }
|
1009
|
-
```
|
1010
|
-
|
1011
|
-
Note that you may also call the `mediawiki` method from within other
|
1012
|
-
templates:
|
1013
|
-
|
1014
|
-
```ruby
|
1015
|
-
%h1 Hello From Haml!
|
1016
|
-
%p= mediawiki(:greetings)
|
1017
|
-
```
|
1018
|
-
|
1019
|
-
Since you cannot call Ruby from MediaWiki, you cannot use layouts written in
|
1020
|
-
MediaWiki. However, it is possible to use another rendering engine for the
|
1021
|
-
template than for the layout by passing the `:layout_engine` option.
|
1022
|
-
|
1023
|
-
#### CoffeeScript Templates
|
1024
|
-
|
1025
|
-
<table>
|
1026
|
-
<tr>
|
1027
|
-
<td>Dependency</td>
|
1028
|
-
<td>
|
1029
|
-
<a href="https://github.com/josh/ruby-coffee-script" title="Ruby CoffeeScript">
|
1030
|
-
CoffeeScript
|
1031
|
-
</a> and a
|
1032
|
-
<a href="https://github.com/sstephenson/execjs" title="ExecJS">
|
1033
|
-
way to execute javascript
|
1034
|
-
</a>
|
1035
|
-
</td>
|
1036
|
-
</tr>
|
1037
|
-
<tr>
|
1038
|
-
<td>File Extension</td>
|
1039
|
-
<td><tt>.coffee</tt></td>
|
1040
|
-
</tr>
|
1041
|
-
<tr>
|
1042
|
-
<td>Example</td>
|
1043
|
-
<td><tt>coffee :index</tt></td>
|
1044
|
-
</tr>
|
1045
|
-
</table>
|
1046
|
-
|
1047
|
-
#### Stylus Templates
|
1048
|
-
|
1049
|
-
<table>
|
1050
|
-
<tr>
|
1051
|
-
<td>Dependency</td>
|
1052
|
-
<td>
|
1053
|
-
<a href="https://github.com/forgecrafted/ruby-stylus" title="Ruby Stylus">
|
1054
|
-
Stylus
|
1055
|
-
</a> and a
|
1056
|
-
<a href="https://github.com/sstephenson/execjs" title="ExecJS">
|
1057
|
-
way to execute javascript
|
1058
|
-
</a>
|
1059
|
-
</td>
|
1060
|
-
</tr>
|
1061
|
-
<tr>
|
1062
|
-
<td>File Extension</td>
|
1063
|
-
<td><tt>.styl</tt></td>
|
1064
|
-
</tr>
|
1065
|
-
<tr>
|
1066
|
-
<td>Example</td>
|
1067
|
-
<td><tt>stylus :index</tt></td>
|
1068
|
-
</tr>
|
1069
|
-
</table>
|
1070
|
-
|
1071
|
-
Before being able to use Stylus templates, you need to load `stylus` and
|
1072
|
-
`stylus/tilt` first:
|
1073
|
-
|
1074
|
-
```ruby
|
1075
|
-
require 'sinatra'
|
1076
|
-
require 'stylus'
|
1077
|
-
require 'stylus/tilt'
|
1078
|
-
|
1079
|
-
get '/' do
|
1080
|
-
stylus :example
|
1081
|
-
end
|
1082
|
-
```
|
1083
|
-
|
1084
860
|
#### Yajl Templates
|
1085
861
|
|
1086
862
|
<table>
|
@@ -1122,27 +898,6 @@ var resource = {"foo":"bar","baz":"qux"};
|
|
1122
898
|
present(resource);
|
1123
899
|
```
|
1124
900
|
|
1125
|
-
#### WLang Templates
|
1126
|
-
|
1127
|
-
<table>
|
1128
|
-
<tr>
|
1129
|
-
<td>Dependency</td>
|
1130
|
-
<td><a href="https://github.com/blambeau/wlang" title="WLang">WLang</a></td>
|
1131
|
-
</tr>
|
1132
|
-
<tr>
|
1133
|
-
<td>File Extension</td>
|
1134
|
-
<td><tt>.wlang</tt></td>
|
1135
|
-
</tr>
|
1136
|
-
<tr>
|
1137
|
-
<td>Example</td>
|
1138
|
-
<td><tt>wlang :index, :locals => { :key => 'value' }</tt></td>
|
1139
|
-
</tr>
|
1140
|
-
</table>
|
1141
|
-
|
1142
|
-
Since calling ruby methods is not idiomatic in WLang, you almost always
|
1143
|
-
want to pass locals to it. Layouts written in WLang and `yield` are
|
1144
|
-
supported, though.
|
1145
|
-
|
1146
901
|
### Accessing Variables in Templates
|
1147
902
|
|
1148
903
|
Templates are evaluated within the same context as route handlers. Instance
|
@@ -1201,7 +956,7 @@ end
|
|
1201
956
|
```
|
1202
957
|
|
1203
958
|
Currently, the following rendering methods accept a block: `erb`, `haml`,
|
1204
|
-
`liquid`, `slim
|
959
|
+
`liquid`, `slim `. Also, the general `render` method accepts a block.
|
1205
960
|
|
1206
961
|
### Inline Templates
|
1207
962
|
|
@@ -1218,13 +973,13 @@ __END__
|
|
1218
973
|
|
1219
974
|
@@ layout
|
1220
975
|
%html
|
1221
|
-
|
976
|
+
!= yield
|
1222
977
|
|
1223
978
|
@@ index
|
1224
979
|
%div.title Hello world.
|
1225
980
|
```
|
1226
981
|
|
1227
|
-
NOTE: Inline templates defined in the source file that requires
|
982
|
+
NOTE: Inline templates defined in the source file that requires Sinatra are
|
1228
983
|
automatically loaded. Call `enable :inline_templates` explicitly if you
|
1229
984
|
have inline templates in other source files.
|
1230
985
|
|
@@ -1261,10 +1016,10 @@ end
|
|
1261
1016
|
|
1262
1017
|
To associate a file extension with a template engine, use
|
1263
1018
|
`Tilt.register`. For instance, if you like to use the file extension
|
1264
|
-
`tt` for
|
1019
|
+
`tt` for Haml templates, you can do the following:
|
1265
1020
|
|
1266
1021
|
```ruby
|
1267
|
-
Tilt.register :
|
1022
|
+
Tilt.register Tilt[:haml], :tt
|
1268
1023
|
```
|
1269
1024
|
|
1270
1025
|
### Adding Your Own Template Engine
|
@@ -1272,7 +1027,7 @@ Tilt.register :tt, Tilt[:textile]
|
|
1272
1027
|
First, register your engine with Tilt, then create a rendering method:
|
1273
1028
|
|
1274
1029
|
```ruby
|
1275
|
-
Tilt.register :myat
|
1030
|
+
Tilt.register MyAwesomeTemplateEngine, :myat
|
1276
1031
|
|
1277
1032
|
helpers do
|
1278
1033
|
def myat(*args) render(:myat, *args) end
|
@@ -1434,7 +1189,7 @@ For better security and usability it's
|
|
1434
1189
|
secret and store it in an environment variable on each host running your
|
1435
1190
|
application so that all of your application instances will share the same
|
1436
1191
|
secret. You should periodically rotate this session secret to a new value.
|
1437
|
-
Here are some examples of how you might create a 64
|
1192
|
+
Here are some examples of how you might create a 64-byte secret and set it:
|
1438
1193
|
|
1439
1194
|
**Session Secret Generation**
|
1440
1195
|
|
@@ -1443,22 +1198,6 @@ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
|
|
1443
1198
|
99ae8af...snip...ec0f262ac
|
1444
1199
|
```
|
1445
1200
|
|
1446
|
-
**Session Secret Generation (Bonus Points)**
|
1447
|
-
|
1448
|
-
Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
|
1449
|
-
prefer use of system RNG facilities to generate random values instead of
|
1450
|
-
userspace `OpenSSL` which MRI Ruby currently defaults to:
|
1451
|
-
|
1452
|
-
```text
|
1453
|
-
$ gem install sysrandom
|
1454
|
-
Building native extensions. This could take a while...
|
1455
|
-
Successfully installed sysrandom-1.x
|
1456
|
-
1 gem installed
|
1457
|
-
|
1458
|
-
$ ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
|
1459
|
-
99ae8af...snip...ec0f262ac
|
1460
|
-
```
|
1461
|
-
|
1462
1201
|
**Session Secret Environment Variable**
|
1463
1202
|
|
1464
1203
|
Set a `SESSION_SECRET` environment variable for Sinatra to the value you
|
@@ -1472,15 +1211,11 @@ purposes only:
|
|
1472
1211
|
|
1473
1212
|
**Session Secret App Config**
|
1474
1213
|
|
1475
|
-
|
1476
|
-
if the `SESSION_SECRET` environment variable is not available
|
1477
|
-
|
1478
|
-
For bonus points use the [sysrandom
|
1479
|
-
gem](https://github.com/cryptosphere/sysrandom#readme) here as well:
|
1214
|
+
Set up your app config to fail-safe to a secure random secret
|
1215
|
+
if the `SESSION_SECRET` environment variable is not available:
|
1480
1216
|
|
1481
1217
|
```ruby
|
1482
1218
|
require 'securerandom'
|
1483
|
-
# -or- require 'sysrandom/securerandom'
|
1484
1219
|
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
|
1485
1220
|
```
|
1486
1221
|
|
@@ -1593,7 +1328,7 @@ matching route. If no matching route is found, a 404 is returned.
|
|
1593
1328
|
|
1594
1329
|
### Triggering Another Route
|
1595
1330
|
|
1596
|
-
Sometimes `pass` is not what you want, instead you would like to get the
|
1331
|
+
Sometimes `pass` is not what you want, instead, you would like to get the
|
1597
1332
|
result of calling another route. Simply use `call` to achieve this:
|
1598
1333
|
|
1599
1334
|
```ruby
|
@@ -1616,13 +1351,13 @@ than a duplicate, use `call!` instead of `call`.
|
|
1616
1351
|
|
1617
1352
|
Check out the Rack specification if you want to learn more about `call`.
|
1618
1353
|
|
1619
|
-
### Setting Body, Status Code and Headers
|
1354
|
+
### Setting Body, Status Code, and Headers
|
1620
1355
|
|
1621
1356
|
It is possible and recommended to set the status code and response body with
|
1622
|
-
the return value of the route block. However, in some scenarios you might
|
1357
|
+
the return value of the route block. However, in some scenarios, you might
|
1623
1358
|
want to set the body at an arbitrary point in the execution flow. You can do
|
1624
1359
|
so with the `body` helper method. If you do so, you can use that method from
|
1625
|
-
|
1360
|
+
thereon to access the body:
|
1626
1361
|
|
1627
1362
|
```ruby
|
1628
1363
|
get '/foo' do
|
@@ -1645,7 +1380,7 @@ get '/foo' do
|
|
1645
1380
|
headers \
|
1646
1381
|
"Allow" => "BREW, POST, GET, PROPFIND, WHEN",
|
1647
1382
|
"Refresh" => "Refresh: 20; https://ietf.org/rfc/rfc2324.txt"
|
1648
|
-
body "I'm a
|
1383
|
+
body "I'm a teapot!"
|
1649
1384
|
end
|
1650
1385
|
```
|
1651
1386
|
|
@@ -1678,60 +1413,16 @@ also be used to increase throughput if some but not all content depends on a
|
|
1678
1413
|
slow resource.
|
1679
1414
|
|
1680
1415
|
Note that the streaming behavior, especially the number of concurrent
|
1681
|
-
requests, highly depends on the
|
1416
|
+
requests, highly depends on the webserver used to serve the application.
|
1682
1417
|
Some servers might not even support streaming at all. If the server does not
|
1683
1418
|
support streaming, the body will be sent all at once after the block passed
|
1684
1419
|
to `stream` finishes executing. Streaming does not work at all with Shotgun.
|
1685
1420
|
|
1686
1421
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
1687
1422
|
the stream object, allowing you to close it at any later point in the
|
1688
|
-
execution flow.
|
1689
|
-
Other servers will still close the stream:
|
1690
|
-
|
1691
|
-
```ruby
|
1692
|
-
# config.ru
|
1693
|
-
require 'sinatra/base'
|
1694
|
-
|
1695
|
-
class App < Sinatra::Base
|
1696
|
-
connections = []
|
1697
|
-
|
1698
|
-
get '/subscribe', provides: 'text/event-stream' do
|
1699
|
-
# register a client's interest in server events
|
1700
|
-
stream(:keep_open) do |out|
|
1701
|
-
connections << out
|
1702
|
-
# purge dead connections
|
1703
|
-
connections.reject!(&:closed?)
|
1704
|
-
end
|
1705
|
-
end
|
1706
|
-
|
1707
|
-
post '/' do
|
1708
|
-
connections.each do |out|
|
1709
|
-
# notify client that a new message has arrived
|
1710
|
-
out << "data: #{params[:msg]}\n\n"
|
1711
|
-
|
1712
|
-
# indicate client to connect again
|
1713
|
-
out.close
|
1714
|
-
end
|
1715
|
-
|
1716
|
-
204 # response without entity body
|
1717
|
-
end
|
1718
|
-
end
|
1423
|
+
execution flow.
|
1719
1424
|
|
1720
|
-
|
1721
|
-
```
|
1722
|
-
|
1723
|
-
```ruby
|
1724
|
-
# rainbows.conf
|
1725
|
-
Rainbows! do
|
1726
|
-
use :EventMachine
|
1727
|
-
end
|
1728
|
-
````
|
1729
|
-
|
1730
|
-
Run:
|
1731
|
-
|
1732
|
-
```shell
|
1733
|
-
rainbows -c rainbows.conf
|
1734
|
-
```
|
1425
|
+
You can have a look at the [chat example](https://github.com/sinatra/sinatra/blob/main/examples/chat.rb)
|
1735
1426
|
|
1736
1427
|
It's also possible for the client to close the connection when trying to
|
1737
1428
|
write to the socket. Because of this, it's recommended to check
|
@@ -1763,7 +1454,7 @@ class MyApp < Sinatra::Base
|
|
1763
1454
|
end
|
1764
1455
|
```
|
1765
1456
|
|
1766
|
-
To avoid any logging middleware to be set up, set the `logging`
|
1457
|
+
To avoid any logging middleware to be set up, set the `logging` option to
|
1767
1458
|
`nil`. However, keep in mind that `logger` will in that case return `nil`. A
|
1768
1459
|
common use case is when you want to set your own logger. Sinatra will use
|
1769
1460
|
whatever it will find in `env['rack.logger']`.
|
@@ -1797,7 +1488,7 @@ Haml:
|
|
1797
1488
|
%a{:href => url('/foo')} foo
|
1798
1489
|
```
|
1799
1490
|
|
1800
|
-
It takes reverse proxies and Rack routers into account
|
1491
|
+
It takes reverse proxies and Rack routers into account - if present.
|
1801
1492
|
|
1802
1493
|
This method is also aliased to `to` (see [below](#browser-redirect) for an example).
|
1803
1494
|
|
@@ -2136,7 +1827,7 @@ end
|
|
2136
1827
|
Another example would be using different directories for different engines:
|
2137
1828
|
|
2138
1829
|
```ruby
|
2139
|
-
set :views, :
|
1830
|
+
set :views, :haml => 'templates', :default => 'views'
|
2140
1831
|
|
2141
1832
|
helpers do
|
2142
1833
|
def find_template(views, name, engine, &block)
|
@@ -2147,7 +1838,7 @@ helpers do
|
|
2147
1838
|
end
|
2148
1839
|
```
|
2149
1840
|
|
2150
|
-
You can also easily wrap this up in an extension and share with others!
|
1841
|
+
You can also easily wrap this up in an extension and share it with others!
|
2151
1842
|
|
2152
1843
|
Note that `find_template` does not check if the file really exists but
|
2153
1844
|
rather calls the given block for all possible paths. This is not a
|
@@ -2213,7 +1904,7 @@ end
|
|
2213
1904
|
### Configuring attack protection
|
2214
1905
|
|
2215
1906
|
Sinatra is using
|
2216
|
-
[Rack::Protection](https://github.com/sinatra/sinatra/tree/
|
1907
|
+
[Rack::Protection](https://github.com/sinatra/sinatra/tree/main/rack-protection#readme) to
|
2217
1908
|
defend your application against common, opportunistic attacks. You can
|
2218
1909
|
easily disable this behavior (which will open up your application to tons
|
2219
1910
|
of common vulnerabilities):
|
@@ -2230,13 +1921,13 @@ set :protection, :except => :path_traversal
|
|
2230
1921
|
You can also hand in an array in order to disable a list of protections:
|
2231
1922
|
|
2232
1923
|
```ruby
|
2233
|
-
set :protection, :except => [:path_traversal, :
|
1924
|
+
set :protection, :except => [:path_traversal, :remote_token]
|
2234
1925
|
```
|
2235
1926
|
|
2236
1927
|
By default, Sinatra will only set up session based protection if `:sessions`
|
2237
1928
|
have been enabled. See '[Using Sessions](#using-sessions)'. Sometimes you may want to set up
|
2238
1929
|
sessions "outside" of the Sinatra app, such as in the config.ru or with a
|
2239
|
-
separate `Rack::Builder` instance. In that case you can still set up session
|
1930
|
+
separate `Rack::Builder` instance. In that case, you can still set up session
|
2240
1931
|
based protection by passing the `:session` option:
|
2241
1932
|
|
2242
1933
|
```ruby
|
@@ -2293,7 +1984,7 @@ set :protection, :session => true
|
|
2293
1984
|
<dd>Encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
|
2294
1985
|
|
2295
1986
|
<dt>dump_errors</dt>
|
2296
|
-
<dd>Display errors in the log.</dd>
|
1987
|
+
<dd>Display errors in the log. Enabled by default unless environment is "test".</dd>
|
2297
1988
|
|
2298
1989
|
<dt>environment</dt>
|
2299
1990
|
<dd>
|
@@ -2301,6 +1992,33 @@ set :protection, :session => true
|
|
2301
1992
|
<tt>"development"</tt> if not available.
|
2302
1993
|
</dd>
|
2303
1994
|
|
1995
|
+
<dt>host_authorization</dt>
|
1996
|
+
<dd>
|
1997
|
+
<p>
|
1998
|
+
You can pass a hash of options to <tt>host_authorization</tt>,
|
1999
|
+
to be used by the <tt>Rack::Protection::HostAuthorization</tt> middleware.
|
2000
|
+
</p>
|
2001
|
+
<p>
|
2002
|
+
The middleware can block requests with unrecognized hostnames, to prevent DNS rebinding
|
2003
|
+
and other host header attacks. It checks the <tt>Host</tt>, <tt>X-Forwarded-Host</tt>
|
2004
|
+
and <tt>Forwarded</tt> headers.
|
2005
|
+
</p>
|
2006
|
+
<p>
|
2007
|
+
Useful options are:
|
2008
|
+
<ul>
|
2009
|
+
<li><tt>permitted_hosts</tt> – an array of hostnames (and <tt>IPAddr</tt> objects) your app recognizes
|
2010
|
+
<ul>
|
2011
|
+
<li>in the <tt>development</tt> environment, it is set to <tt>.localhost</tt>, <tt>.test</tt> and any IPv4/IPv6 address</li>
|
2012
|
+
<li>if empty, any hostname is permitted (the default for any other environment)</li>
|
2013
|
+
</ul>
|
2014
|
+
</li>
|
2015
|
+
<li><tt>status</tt> – the HTTP status code used in the response when a request is blocked (defaults to <tt>403</tt>)</li>
|
2016
|
+
<li><tt>message</tt> – the body used in the response when a request is blocked (defaults to <tt>Host not permitted</tt>)</li>
|
2017
|
+
<li><tt>allow_if</tt> – supply a <tt>Proc</tt> to use custom allow/deny logic, the proc is passed the request environment</li>
|
2018
|
+
</ul>
|
2019
|
+
</p>
|
2020
|
+
</dd>
|
2021
|
+
|
2304
2022
|
<dt>logging</dt>
|
2305
2023
|
<dd>Use the logger.</dd>
|
2306
2024
|
|
@@ -2369,9 +2087,13 @@ set :protection, :session => true
|
|
2369
2087
|
|
2370
2088
|
<dt>raise_errors</dt>
|
2371
2089
|
<dd>
|
2372
|
-
Raise
|
2090
|
+
Raise unhandled errors (will stop application). Enabled by default when
|
2373
2091
|
<tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
|
2374
2092
|
</dd>
|
2093
|
+
<dd>
|
2094
|
+
Any explicitly defined error handlers always override this setting. See
|
2095
|
+
the "Error" section below.
|
2096
|
+
</dd>
|
2375
2097
|
|
2376
2098
|
<dt>run</dt>
|
2377
2099
|
<dd>
|
@@ -2390,12 +2112,8 @@ set :protection, :session => true
|
|
2390
2112
|
|
2391
2113
|
<dt>server_settings</dt>
|
2392
2114
|
<dd>
|
2393
|
-
|
2394
|
-
|
2395
|
-
such as <tt>SSLEnable</tt> or <tt>SSLVerifyClient</tt>. However, web
|
2396
|
-
servers such as Puma do not support this, so you can set
|
2397
|
-
<tt>server_settings</tt> by defining it as a method when you call
|
2398
|
-
<tt>configure</tt>.
|
2115
|
+
You can pass a hash of options to <tt>server_settings</tt>,
|
2116
|
+
such as <tt>Host</tt> or <tt>Port</tt>.
|
2399
2117
|
</dd>
|
2400
2118
|
|
2401
2119
|
<dt>sessions</dt>
|
@@ -2464,6 +2182,24 @@ set :protection, :session => true
|
|
2464
2182
|
</dd>
|
2465
2183
|
</dl>
|
2466
2184
|
|
2185
|
+
## Lifecycle Events
|
2186
|
+
|
2187
|
+
There are 2 lifecycle events currently exposed by Sinatra. One when the server starts and one when it stops.
|
2188
|
+
|
2189
|
+
They can be used like this:
|
2190
|
+
|
2191
|
+
```ruby
|
2192
|
+
on_start do
|
2193
|
+
puts "===== Booting up ====="
|
2194
|
+
end
|
2195
|
+
|
2196
|
+
on_stop do
|
2197
|
+
puts "===== Shutting down ====="
|
2198
|
+
end
|
2199
|
+
```
|
2200
|
+
|
2201
|
+
Note that these callbacks only work when using Sinatra to start the web server.
|
2202
|
+
|
2467
2203
|
## Environments
|
2468
2204
|
|
2469
2205
|
There are three predefined `environments`: `"development"`,
|
@@ -2520,6 +2256,14 @@ show exceptions option to `:after_handler`:
|
|
2520
2256
|
set :show_exceptions, :after_handler
|
2521
2257
|
```
|
2522
2258
|
|
2259
|
+
A catch-all error handler can be defined with `error` and a block:
|
2260
|
+
|
2261
|
+
```ruby
|
2262
|
+
error do
|
2263
|
+
'Sorry there was a nasty error'
|
2264
|
+
end
|
2265
|
+
```
|
2266
|
+
|
2523
2267
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2524
2268
|
|
2525
2269
|
```ruby
|
@@ -2528,7 +2272,7 @@ error do
|
|
2528
2272
|
end
|
2529
2273
|
```
|
2530
2274
|
|
2531
|
-
|
2275
|
+
Pass an error class as an argument to create handlers for custom errors:
|
2532
2276
|
|
2533
2277
|
```ruby
|
2534
2278
|
error MyCustomError do
|
@@ -2574,6 +2318,51 @@ Sinatra installs special `not_found` and `error` handlers when
|
|
2574
2318
|
running under the development environment to display nice stack traces
|
2575
2319
|
and additional debugging information in your browser.
|
2576
2320
|
|
2321
|
+
### Behavior with `raise_errors` option
|
2322
|
+
|
2323
|
+
When `raise_errors` option is `true`, errors that are unhandled are raised
|
2324
|
+
outside of the application. Additionally, any errors that would have been
|
2325
|
+
caught by the catch-all error handler are raised.
|
2326
|
+
|
2327
|
+
For example, consider the following configuration:
|
2328
|
+
|
2329
|
+
```ruby
|
2330
|
+
# First handler
|
2331
|
+
error MyCustomError do
|
2332
|
+
'A custom message'
|
2333
|
+
end
|
2334
|
+
|
2335
|
+
# Second handler
|
2336
|
+
error do
|
2337
|
+
'A catch-all message'
|
2338
|
+
end
|
2339
|
+
```
|
2340
|
+
|
2341
|
+
If `raise_errors` is `false`:
|
2342
|
+
|
2343
|
+
* When `MyCustomError` or descendant is raised, the first handler is invoked.
|
2344
|
+
The HTTP response body will contain `"A custom message"`.
|
2345
|
+
* When any other error is raised, the second handler is invoked. The HTTP
|
2346
|
+
response body will contain `"A catch-all message"`.
|
2347
|
+
|
2348
|
+
If `raise_errors` is `true`:
|
2349
|
+
|
2350
|
+
* When `MyCustomError` or descendant is raised, the behavior is identical to
|
2351
|
+
when `raise_errors` is `false`, described above.
|
2352
|
+
* When any other error is raised, the second handler is *not* invoked, and
|
2353
|
+
the error is raised outside of the application.
|
2354
|
+
* If the environment is `production`, the HTTP response body will contain
|
2355
|
+
a generic error message, e.g. `"An unhandled lowlevel error occurred. The
|
2356
|
+
application logs may have details."`
|
2357
|
+
* If the environment is not `production`, the HTTP response body will contain
|
2358
|
+
the verbose error backtrace.
|
2359
|
+
* Regardless of environment, if `show_exceptions` is set to `:after_handler`,
|
2360
|
+
the HTTP response body will contain the verbose error backtrace.
|
2361
|
+
|
2362
|
+
In the `test` environment, `raise_errors` is set to `true` by default. This
|
2363
|
+
means that in order to write a test for a catch-all error handler,
|
2364
|
+
`raise_errors` must temporarily be set to `false` for that particular test.
|
2365
|
+
|
2577
2366
|
## Rack Middleware
|
2578
2367
|
|
2579
2368
|
Sinatra rides on [Rack](https://rack.github.io/), a minimal standard
|
@@ -2599,7 +2388,7 @@ end
|
|
2599
2388
|
```
|
2600
2389
|
|
2601
2390
|
The semantics of `use` are identical to those defined for the
|
2602
|
-
[Rack::Builder](
|
2391
|
+
[Rack::Builder](https://www.rubydoc.info/github/rack/rack/main/Rack/Builder) DSL
|
2603
2392
|
(most frequently used from rackup files). For example, the `use` method
|
2604
2393
|
accepts multiple/variable args as well as blocks:
|
2605
2394
|
|
@@ -2615,7 +2404,7 @@ many of these components automatically based on configuration so you
|
|
2615
2404
|
typically don't have to `use` them explicitly.
|
2616
2405
|
|
2617
2406
|
You can find useful middleware in
|
2618
|
-
[rack](https://github.com/rack/rack/tree/
|
2407
|
+
[rack](https://github.com/rack/rack/tree/main/lib/rack),
|
2619
2408
|
[rack-contrib](https://github.com/rack/rack-contrib#readme),
|
2620
2409
|
or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
2621
2410
|
|
@@ -2623,7 +2412,7 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2623
2412
|
|
2624
2413
|
Sinatra tests can be written using any Rack-based testing library or
|
2625
2414
|
framework.
|
2626
|
-
[Rack::Test](
|
2415
|
+
[Rack::Test](https://www.rubydoc.info/github/rack/rack-test/main/frames)
|
2627
2416
|
is recommended:
|
2628
2417
|
|
2629
2418
|
```ruby
|
@@ -2717,7 +2506,7 @@ modular application.
|
|
2717
2506
|
The main disadvantage of using the classic style rather than the modular
|
2718
2507
|
style is that you will only have one Sinatra application per Ruby
|
2719
2508
|
process. If you plan to use more than one, switch to the modular style.
|
2720
|
-
There is no reason you cannot mix the modular and
|
2509
|
+
There is no reason you cannot mix the modular and classic styles.
|
2721
2510
|
|
2722
2511
|
If switching from one style to the other, you should be aware of
|
2723
2512
|
slightly different default settings:
|
@@ -2846,7 +2635,7 @@ style for running with a `config.ru`.**
|
|
2846
2635
|
### Using Sinatra as Middleware
|
2847
2636
|
|
2848
2637
|
Not only is Sinatra able to use other Rack middleware, any Sinatra
|
2849
|
-
application can in turn be added in front of any Rack endpoint as
|
2638
|
+
application can, in turn, be added in front of any Rack endpoint as
|
2850
2639
|
middleware itself. This endpoint could be another Sinatra application,
|
2851
2640
|
or any other Rack-based application (Rails/Hanami/Roda/...):
|
2852
2641
|
|
@@ -2937,7 +2726,7 @@ available.
|
|
2937
2726
|
Every Sinatra application corresponds to a subclass of `Sinatra::Base`.
|
2938
2727
|
If you are using the top-level DSL (`require 'sinatra'`), then this
|
2939
2728
|
class is `Sinatra::Application`, otherwise it is the subclass you
|
2940
|
-
created explicitly. At class level you have methods like `get` or
|
2729
|
+
created explicitly. At the class level, you have methods like `get` or
|
2941
2730
|
`before`, but you cannot access the `request` or `session` objects, as
|
2942
2731
|
there is only a single application class for all requests.
|
2943
2732
|
|
@@ -2960,7 +2749,7 @@ You have the application scope binding inside:
|
|
2960
2749
|
* Your application class body
|
2961
2750
|
* Methods defined by extensions
|
2962
2751
|
* The block passed to `helpers`
|
2963
|
-
* Procs/blocks used as value for `set`
|
2752
|
+
* Procs/blocks used as a value for `set`
|
2964
2753
|
* The block passed to `Sinatra.new`
|
2965
2754
|
|
2966
2755
|
You can reach the scope object (the class) like this:
|
@@ -3011,7 +2800,7 @@ do not share variables/state with the class scope (read: you have a different
|
|
3011
2800
|
|
3012
2801
|
You have the delegate scope binding inside:
|
3013
2802
|
|
3014
|
-
* The top
|
2803
|
+
* The top-level binding, if you did `require "sinatra"`
|
3015
2804
|
* An object extended with the `Sinatra::Delegator` mixin
|
3016
2805
|
|
3017
2806
|
Have a look at the code for yourself: here's the
|
@@ -3044,98 +2833,43 @@ _Paraphrasing from
|
|
3044
2833
|
[this StackOverflow answer](https://stackoverflow.com/a/6282999/5245129)
|
3045
2834
|
by Konstantin_
|
3046
2835
|
|
3047
|
-
Sinatra doesn't impose any concurrency model
|
3048
|
-
underlying Rack handler (server) like Puma or
|
2836
|
+
Sinatra doesn't impose any concurrency model but leaves that to the
|
2837
|
+
underlying Rack handler (server) like Puma or Falcon. Sinatra
|
3049
2838
|
itself is thread-safe, so there won't be any problem if the Rack handler
|
3050
|
-
uses a threaded model of concurrency.
|
3051
|
-
the server, you'd have to specify the correct invocation method for the
|
3052
|
-
specific Rack handler. The following example is a demonstration of how
|
3053
|
-
to start a multi-threaded Rainbows server:
|
3054
|
-
|
3055
|
-
```ruby
|
3056
|
-
# config.ru
|
3057
|
-
|
3058
|
-
require 'sinatra/base'
|
3059
|
-
|
3060
|
-
class App < Sinatra::Base
|
3061
|
-
get '/' do
|
3062
|
-
"Hello, World"
|
3063
|
-
end
|
3064
|
-
end
|
3065
|
-
|
3066
|
-
run App
|
3067
|
-
```
|
3068
|
-
|
3069
|
-
```ruby
|
3070
|
-
# rainbows.conf
|
3071
|
-
|
3072
|
-
# Rainbows configurator is based on Unicorn.
|
3073
|
-
Rainbows! do
|
3074
|
-
use :ThreadSpawn
|
3075
|
-
end
|
3076
|
-
```
|
3077
|
-
|
3078
|
-
To start the server, the command would be:
|
3079
|
-
|
3080
|
-
```shell
|
3081
|
-
rainbows -c rainbows.conf
|
3082
|
-
```
|
2839
|
+
uses a threaded model of concurrency.
|
3083
2840
|
|
3084
2841
|
## Requirement
|
3085
2842
|
|
3086
2843
|
The following Ruby versions are officially supported:
|
3087
2844
|
<dl>
|
3088
|
-
<dt>Ruby
|
2845
|
+
<dt>Ruby</dt>
|
3089
2846
|
<dd>
|
3090
|
-
|
3091
|
-
drop official support for it.
|
2847
|
+
<a href="https://www.ruby-lang.org/en/downloads/">The stable releases</a> are fully supported and recommended.
|
3092
2848
|
</dd>
|
3093
2849
|
|
3094
|
-
<dt>
|
2850
|
+
<dt>TruffleRuby</dt>
|
3095
2851
|
<dd>
|
3096
|
-
|
3097
|
-
<tt>gem install puma</tt>.
|
2852
|
+
The latest stable release of TruffleRuby is supported.
|
3098
2853
|
</dd>
|
3099
2854
|
|
3100
2855
|
<dt>JRuby</dt>
|
3101
2856
|
<dd>
|
3102
|
-
The latest stable release of JRuby is
|
3103
|
-
recommended to use C extensions with JRuby.
|
3104
|
-
<tt>gem install trinidad</tt>.
|
2857
|
+
The latest stable release of JRuby is supported. It is not
|
2858
|
+
recommended to use C extensions with JRuby.
|
3105
2859
|
</dd>
|
3106
2860
|
</dl>
|
3107
2861
|
|
3108
|
-
Versions of Ruby
|
3109
|
-
|
3110
|
-
We also keep an eye on upcoming Ruby versions.
|
3111
|
-
|
3112
|
-
The following Ruby implementations are not officially supported but still are
|
3113
|
-
known to run Sinatra:
|
3114
|
-
|
3115
|
-
* Older versions of JRuby and Rubinius
|
3116
|
-
* Ruby Enterprise Edition
|
3117
|
-
* MacRuby, Maglev, IronRuby
|
3118
|
-
* Ruby 1.9.0 and 1.9.1 (but we do recommend against using those)
|
3119
|
-
|
3120
|
-
Not being officially supported means if things only break there and not on a
|
3121
|
-
supported platform, we assume it's not our issue but theirs.
|
3122
|
-
|
3123
|
-
We also run our CI against ruby-head (future releases of MRI), but we
|
3124
|
-
can't guarantee anything, since it is constantly moving. Expect upcoming
|
3125
|
-
2.x releases to be fully supported.
|
2862
|
+
Versions of Ruby before 2.7.8 are no longer supported as of Sinatra 4.0.0.
|
3126
2863
|
|
3127
2864
|
Sinatra should work on any operating system supported by the chosen Ruby
|
3128
2865
|
implementation.
|
3129
2866
|
|
3130
|
-
|
3131
|
-
|
3132
|
-
Sinatra currently doesn't run on Cardinal, SmallRuby, BlueRuby or any
|
3133
|
-
Ruby version prior to 2.2.
|
2867
|
+
Running Sinatra on a not officially supported Ruby flavor means that if things only break there we assume it's not our issue but theirs.
|
3134
2868
|
|
3135
2869
|
## The Bleeding Edge
|
3136
2870
|
|
3137
2871
|
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
3138
|
-
to run your application against the
|
2872
|
+
to run your application against the main branch, it should be rather
|
3139
2873
|
stable.
|
3140
2874
|
|
3141
2875
|
We also push out prerelease gems from time to time, so you can do a
|
@@ -3184,20 +2918,19 @@ SemVerTag.
|
|
3184
2918
|
|
3185
2919
|
## Further Reading
|
3186
2920
|
|
3187
|
-
* [Project Website](
|
2921
|
+
* [Project Website](https://sinatrarb.com/) - Additional documentation,
|
3188
2922
|
news, and links to other resources.
|
3189
|
-
* [Contributing](
|
2923
|
+
* [Contributing](https://sinatrarb.com/contributing) - Find a bug? Need
|
3190
2924
|
help? Have a patch?
|
3191
2925
|
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
3192
2926
|
* [Twitter](https://twitter.com/sinatra)
|
3193
2927
|
* [Mailing List](https://groups.google.com/forum/#!forum/sinatrarb)
|
3194
2928
|
* IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on [Freenode](https://freenode.net)
|
3195
|
-
* [Sinatra & Friends](https://
|
3196
|
-
([get an invite](https://sinatra-slack.herokuapp.com/))
|
2929
|
+
* [Sinatra & Friends](https://discord.gg/ncjsfsNHh7) on Discord
|
3197
2930
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book) - Cookbook Tutorial
|
3198
2931
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) - Community contributed
|
3199
2932
|
recipes
|
3200
|
-
* API documentation for the [latest release](
|
3201
|
-
or the [current HEAD](
|
3202
|
-
[RubyDoc](
|
3203
|
-
* [CI
|
2933
|
+
* API documentation for the [latest release](https://www.rubydoc.info/gems/sinatra)
|
2934
|
+
or the [current HEAD](https://www.rubydoc.info/github/sinatra/sinatra) on
|
2935
|
+
[RubyDoc](https://www.rubydoc.info/)
|
2936
|
+
* [CI Actions](https://github.com/sinatra/sinatra/actions)
|