sinatra 2.2.4 → 3.2.0
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.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/AUTHORS.md +14 -8
- data/CHANGELOG.md +143 -17
- data/CONTRIBUTING.md +11 -11
- data/Gemfile +52 -60
- data/MAINTENANCE.md +2 -2
- data/README.md +204 -487
- 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 +418 -336
- data/lib/sinatra/indifferent_hash.rb +35 -35
- data/lib/sinatra/main.rb +18 -16
- data/lib/sinatra/show_exceptions.rb +17 -15
- data/lib/sinatra/version.rb +3 -1
- data/lib/sinatra.rb +2 -0
- data/sinatra.gemspec +36 -33
- metadata +24 -31
- data/README.de.md +0 -3239
- data/README.es.md +0 -3231
- data/README.fr.md +0 -3111
- data/README.hu.md +0 -728
- data/README.ja.md +0 -2844
- 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
3
|
[](https://badge.fury.io/rb/sinatra)
|
4
|
-
[](https://dependabot.com/compatibility-score.html?dependency-name=sinatra&package-manager=bundler&version-scheme=semver)
|
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:
|
@@ -20,6 +19,7 @@ Install the gem:
|
|
20
19
|
|
21
20
|
```shell
|
22
21
|
gem install sinatra
|
22
|
+
gem install puma # or any other server
|
23
23
|
```
|
24
24
|
|
25
25
|
And run with:
|
@@ -31,101 +31,95 @@ ruby myapp.rb
|
|
31
31
|
View at: [http://localhost:4567](http://localhost:4567)
|
32
32
|
|
33
33
|
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
|
-
[
|
34
|
+
Please restart the server every time you change or use a code reloader
|
35
|
+
like [rerun](https://github.com/alexch/rerun) or
|
36
|
+
[rack-unreloader](https://github.com/jeremyevans/rack-unreloader).
|
36
37
|
|
37
38
|
It is recommended to also run `gem install puma`, which Sinatra will
|
38
39
|
pick up if available.
|
39
40
|
|
40
41
|
## Table of Contents
|
41
42
|
|
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)
|
43
|
+
- [Sinatra](#sinatra)
|
44
|
+
- [Table of Contents](#table-of-contents)
|
45
|
+
- [Routes](#routes)
|
46
|
+
- [Conditions](#conditions)
|
47
|
+
- [Return Values](#return-values)
|
48
|
+
- [Custom Route Matchers](#custom-route-matchers)
|
49
|
+
- [Static Files](#static-files)
|
50
|
+
- [Views / Templates](#views--templates)
|
51
|
+
- [Literal Templates](#literal-templates)
|
52
|
+
- [Available Template Languages](#available-template-languages)
|
53
|
+
- [Haml Templates](#haml-templates)
|
54
|
+
- [Erb Templates](#erb-templates)
|
55
|
+
- [Builder Templates](#builder-templates)
|
56
|
+
- [Nokogiri Templates](#nokogiri-templates)
|
57
|
+
- [Sass Templates](#sass-templates)
|
58
|
+
- [Scss Templates](#scss-templates)
|
59
|
+
- [Liquid Templates](#liquid-templates)
|
60
|
+
- [Markdown Templates](#markdown-templates)
|
61
|
+
- [RDoc Templates](#rdoc-templates)
|
62
|
+
- [AsciiDoc Templates](#asciidoc-templates)
|
63
|
+
- [Markaby Templates](#markaby-templates)
|
64
|
+
- [RABL Templates](#rabl-templates)
|
65
|
+
- [Slim Templates](#slim-templates)
|
66
|
+
- [Yajl Templates](#yajl-templates)
|
67
|
+
- [Accessing Variables in Templates](#accessing-variables-in-templates)
|
68
|
+
- [Templates with `yield` and nested layouts](#templates-with-yield-and-nested-layouts)
|
69
|
+
- [Inline Templates](#inline-templates)
|
70
|
+
- [Named Templates](#named-templates)
|
71
|
+
- [Associating File Extensions](#associating-file-extensions)
|
72
|
+
- [Adding Your Own Template Engine](#adding-your-own-template-engine)
|
73
|
+
- [Using Custom Logic for Template Lookup](#using-custom-logic-for-template-lookup)
|
74
|
+
- [Filters](#filters)
|
75
|
+
- [Helpers](#helpers)
|
76
|
+
- [Using Sessions](#using-sessions)
|
77
|
+
- [Session Secret Security](#session-secret-security)
|
78
|
+
- [Session Config](#session-config)
|
79
|
+
- [Choosing Your Own Session Middleware](#choosing-your-own-session-middleware)
|
80
|
+
- [Halting](#halting)
|
81
|
+
- [Passing](#passing)
|
82
|
+
- [Triggering Another Route](#triggering-another-route)
|
83
|
+
- [Setting Body, Status Code, and Headers](#setting-body-status-code-and-headers)
|
84
|
+
- [Streaming Responses](#streaming-responses)
|
85
|
+
- [Logging](#logging)
|
86
|
+
- [Mime Types](#mime-types)
|
87
|
+
- [Generating URLs](#generating-urls)
|
88
|
+
- [Browser Redirect](#browser-redirect)
|
89
|
+
- [Cache Control](#cache-control)
|
90
|
+
- [Sending Files](#sending-files)
|
91
|
+
- [Accessing the Request Object](#accessing-the-request-object)
|
92
|
+
- [Attachments](#attachments)
|
93
|
+
- [Dealing with Date and Time](#dealing-with-date-and-time)
|
94
|
+
- [Looking Up Template Files](#looking-up-template-files)
|
95
|
+
- [Configuration](#configuration)
|
96
|
+
- [Configuring attack protection](#configuring-attack-protection)
|
97
|
+
- [Available Settings](#available-settings)
|
98
|
+
- [Lifecycle Events](#lifecycle-events)
|
99
|
+
- [Environments](#environments)
|
100
|
+
- [Error Handling](#error-handling)
|
101
|
+
- [Not Found](#not-found)
|
102
|
+
- [Error](#error)
|
103
|
+
- [Rack Middleware](#rack-middleware)
|
104
|
+
- [Testing](#testing)
|
105
|
+
- [Sinatra::Base - Middleware, Libraries, and Modular Apps](#sinatrabase---middleware-libraries-and-modular-apps)
|
106
|
+
- [Modular vs. Classic Style](#modular-vs-classic-style)
|
107
|
+
- [Serving a Modular Application](#serving-a-modular-application)
|
108
|
+
- [Using a Classic Style Application with a config.ru](#using-a-classic-style-application-with-a-configru)
|
109
|
+
- [When to use a config.ru?](#when-to-use-a-configru)
|
110
|
+
- [Using Sinatra as Middleware](#using-sinatra-as-middleware)
|
111
|
+
- [Dynamic Application Creation](#dynamic-application-creation)
|
112
|
+
- [Scopes and Binding](#scopes-and-binding)
|
113
|
+
- [Application/Class Scope](#applicationclass-scope)
|
114
|
+
- [Request/Instance Scope](#requestinstance-scope)
|
115
|
+
- [Delegation Scope](#delegation-scope)
|
116
|
+
- [Command Line](#command-line)
|
117
|
+
- [Multi-threading](#multi-threading)
|
118
|
+
- [Requirement](#requirement)
|
119
|
+
- [The Bleeding Edge](#the-bleeding-edge)
|
120
|
+
- [With Bundler](#with-bundler)
|
121
|
+
- [Versioning](#versioning)
|
122
|
+
- [Further Reading](#further-reading)
|
129
123
|
|
130
124
|
## Routes
|
131
125
|
|
@@ -382,15 +376,16 @@ stop there. You can easily define your own matchers:
|
|
382
376
|
|
383
377
|
```ruby
|
384
378
|
class AllButPattern
|
385
|
-
Match = Struct.new(:captures)
|
386
|
-
|
387
379
|
def initialize(except)
|
388
|
-
@except
|
389
|
-
|
380
|
+
@except = except
|
381
|
+
end
|
382
|
+
|
383
|
+
def to_pattern(options)
|
384
|
+
return self
|
390
385
|
end
|
391
386
|
|
392
|
-
def
|
393
|
-
|
387
|
+
def params(route)
|
388
|
+
return {} unless @except === route
|
394
389
|
end
|
395
390
|
end
|
396
391
|
|
@@ -407,20 +402,12 @@ Note that the above example might be over-engineered, as it can also be
|
|
407
402
|
expressed as:
|
408
403
|
|
409
404
|
```ruby
|
410
|
-
get
|
405
|
+
get /.*/ do
|
411
406
|
pass if request.path_info == "/index"
|
412
407
|
# ...
|
413
408
|
end
|
414
409
|
```
|
415
410
|
|
416
|
-
Or, using negative look ahead:
|
417
|
-
|
418
|
-
```ruby
|
419
|
-
get %r{(?!/index)} do
|
420
|
-
# ...
|
421
|
-
end
|
422
|
-
```
|
423
|
-
|
424
411
|
## Static Files
|
425
412
|
|
426
413
|
Static files are served from the `./public` directory. You can specify
|
@@ -584,7 +571,7 @@ Some languages have multiple implementations. To specify what implementation
|
|
584
571
|
to use (and to be thread-safe), you should simply require it first:
|
585
572
|
|
586
573
|
```ruby
|
587
|
-
require 'rdiscount'
|
574
|
+
require 'rdiscount'
|
588
575
|
get('/') { markdown :index }
|
589
576
|
```
|
590
577
|
|
@@ -612,14 +599,12 @@ get('/') { markdown :index }
|
|
612
599
|
<td>Dependency</td>
|
613
600
|
<td>
|
614
601
|
<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
602
|
or erb (included in Ruby)
|
617
603
|
</td>
|
618
604
|
</tr>
|
619
605
|
<tr>
|
620
606
|
<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>
|
607
|
+
<td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubi</tt> (Erubi only)</td>
|
623
608
|
</tr>
|
624
609
|
<tr>
|
625
610
|
<td>Example</td>
|
@@ -672,7 +657,7 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
672
657
|
<table>
|
673
658
|
<tr>
|
674
659
|
<td>Dependency</td>
|
675
|
-
<td><a href="https://
|
660
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
676
661
|
</tr>
|
677
662
|
<tr>
|
678
663
|
<td>File Extension</td>
|
@@ -684,12 +669,12 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
684
669
|
</tr>
|
685
670
|
</table>
|
686
671
|
|
687
|
-
####
|
672
|
+
#### Scss Templates
|
688
673
|
|
689
674
|
<table>
|
690
675
|
<tr>
|
691
676
|
<td>Dependency</td>
|
692
|
-
<td><a href="https://
|
677
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
693
678
|
</tr>
|
694
679
|
<tr>
|
695
680
|
<td>File Extension</td>
|
@@ -701,23 +686,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
701
686
|
</tr>
|
702
687
|
</table>
|
703
688
|
|
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
689
|
#### Liquid Templates
|
722
690
|
|
723
691
|
<table>
|
@@ -747,9 +715,7 @@ template, you almost always want to pass locals to it.
|
|
747
715
|
Anyone of:
|
748
716
|
<a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
|
749
717
|
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
|
750
|
-
<a href="https://github.com/ged/bluecloth" title="BlueCloth">BlueCloth</a>,
|
751
718
|
<a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
|
752
|
-
<a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
|
753
719
|
<a href="https://github.com/gjtorikian/commonmarker" title="commonmarker">commonmarker</a>
|
754
720
|
<a href="https://github.com/alphabetum/pandoc-ruby" title="pandoc">pandoc</a>
|
755
721
|
</td>
|
@@ -784,42 +750,6 @@ Since you cannot call Ruby from Markdown, you cannot use layouts written in
|
|
784
750
|
Markdown. However, it is possible to use another rendering engine for the
|
785
751
|
template than for the layout by passing the `:layout_engine` option.
|
786
752
|
|
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
753
|
#### RDoc Templates
|
824
754
|
|
825
755
|
<table>
|
@@ -875,26 +805,6 @@ template than for the layout by passing the `:layout_engine` option.
|
|
875
805
|
Since you cannot call Ruby methods directly from an AsciiDoc template, you
|
876
806
|
almost always want to pass locals to it.
|
877
807
|
|
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
808
|
#### Markaby Templates
|
899
809
|
|
900
810
|
<table>
|
@@ -936,7 +846,7 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
936
846
|
<table>
|
937
847
|
<tr>
|
938
848
|
<td>Dependency</td>
|
939
|
-
<td><a href="
|
849
|
+
<td><a href="https://slim-template.github.io/" title="Slim Lang">Slim Lang</a></td>
|
940
850
|
</tr>
|
941
851
|
<tr>
|
942
852
|
<td>File Extension</td>
|
@@ -948,139 +858,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
948
858
|
</tr>
|
949
859
|
</table>
|
950
860
|
|
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
861
|
#### Yajl Templates
|
1085
862
|
|
1086
863
|
<table>
|
@@ -1122,27 +899,6 @@ var resource = {"foo":"bar","baz":"qux"};
|
|
1122
899
|
present(resource);
|
1123
900
|
```
|
1124
901
|
|
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
902
|
### Accessing Variables in Templates
|
1147
903
|
|
1148
904
|
Templates are evaluated within the same context as route handlers. Instance
|
@@ -1201,7 +957,7 @@ end
|
|
1201
957
|
```
|
1202
958
|
|
1203
959
|
Currently, the following rendering methods accept a block: `erb`, `haml`,
|
1204
|
-
`liquid`, `slim
|
960
|
+
`liquid`, `slim `. Also, the general `render` method accepts a block.
|
1205
961
|
|
1206
962
|
### Inline Templates
|
1207
963
|
|
@@ -1218,7 +974,7 @@ __END__
|
|
1218
974
|
|
1219
975
|
@@ layout
|
1220
976
|
%html
|
1221
|
-
|
977
|
+
!= yield
|
1222
978
|
|
1223
979
|
@@ index
|
1224
980
|
%div.title Hello world.
|
@@ -1261,10 +1017,10 @@ end
|
|
1261
1017
|
|
1262
1018
|
To associate a file extension with a template engine, use
|
1263
1019
|
`Tilt.register`. For instance, if you like to use the file extension
|
1264
|
-
`tt` for
|
1020
|
+
`tt` for Haml templates, you can do the following:
|
1265
1021
|
|
1266
1022
|
```ruby
|
1267
|
-
Tilt.register :
|
1023
|
+
Tilt.register Tilt[:haml], :tt
|
1268
1024
|
```
|
1269
1025
|
|
1270
1026
|
### Adding Your Own Template Engine
|
@@ -1272,7 +1028,7 @@ Tilt.register :tt, Tilt[:textile]
|
|
1272
1028
|
First, register your engine with Tilt, then create a rendering method:
|
1273
1029
|
|
1274
1030
|
```ruby
|
1275
|
-
Tilt.register :myat
|
1031
|
+
Tilt.register MyAwesomeTemplateEngine, :myat
|
1276
1032
|
|
1277
1033
|
helpers do
|
1278
1034
|
def myat(*args) render(:myat, *args) end
|
@@ -1443,22 +1199,6 @@ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
|
|
1443
1199
|
99ae8af...snip...ec0f262ac
|
1444
1200
|
```
|
1445
1201
|
|
1446
|
-
**Session Secret Generation (Bonus Points)**
|
1447
|
-
|
1448
|
-
Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
|
1449
|
-
use the 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
1202
|
**Session Secret Environment Variable**
|
1463
1203
|
|
1464
1204
|
Set a `SESSION_SECRET` environment variable for Sinatra to the value you
|
@@ -1473,14 +1213,10 @@ purposes only:
|
|
1473
1213
|
**Session Secret App Config**
|
1474
1214
|
|
1475
1215
|
Set up your app config to fail-safe to a secure random secret
|
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:
|
1216
|
+
if the `SESSION_SECRET` environment variable is not available:
|
1480
1217
|
|
1481
1218
|
```ruby
|
1482
1219
|
require 'securerandom'
|
1483
|
-
# -or- require 'sysrandom/securerandom'
|
1484
1220
|
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
|
1485
1221
|
```
|
1486
1222
|
|
@@ -1685,53 +1421,9 @@ to `stream` finishes executing. Streaming does not work at all with Shotgun.
|
|
1685
1421
|
|
1686
1422
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
1687
1423
|
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'
|
1424
|
+
execution flow.
|
1694
1425
|
|
1695
|
-
|
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
|
1719
|
-
|
1720
|
-
run App
|
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
|
-
```
|
1426
|
+
You can have a look at the [chat example](https://github.com/sinatra/sinatra/blob/main/examples/chat.rb)
|
1735
1427
|
|
1736
1428
|
It's also possible for the client to close the connection when trying to
|
1737
1429
|
write to the socket. Because of this, it's recommended to check
|
@@ -2136,7 +1828,7 @@ end
|
|
2136
1828
|
Another example would be using different directories for different engines:
|
2137
1829
|
|
2138
1830
|
```ruby
|
2139
|
-
set :views, :
|
1831
|
+
set :views, :haml => 'templates', :default => 'views'
|
2140
1832
|
|
2141
1833
|
helpers do
|
2142
1834
|
def find_template(views, name, engine, &block)
|
@@ -2213,7 +1905,7 @@ end
|
|
2213
1905
|
### Configuring attack protection
|
2214
1906
|
|
2215
1907
|
Sinatra is using
|
2216
|
-
[Rack::Protection](https://github.com/sinatra/sinatra/tree/
|
1908
|
+
[Rack::Protection](https://github.com/sinatra/sinatra/tree/main/rack-protection#readme) to
|
2217
1909
|
defend your application against common, opportunistic attacks. You can
|
2218
1910
|
easily disable this behavior (which will open up your application to tons
|
2219
1911
|
of common vulnerabilities):
|
@@ -2369,9 +2061,13 @@ set :protection, :session => true
|
|
2369
2061
|
|
2370
2062
|
<dt>raise_errors</dt>
|
2371
2063
|
<dd>
|
2372
|
-
Raise
|
2064
|
+
Raise unhandled errors (will stop application). Enabled by default when
|
2373
2065
|
<tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
|
2374
2066
|
</dd>
|
2067
|
+
<dd>
|
2068
|
+
Any explicitly defined error handlers always override this setting. See
|
2069
|
+
the "Error" section below.
|
2070
|
+
</dd>
|
2375
2071
|
|
2376
2072
|
<dt>run</dt>
|
2377
2073
|
<dd>
|
@@ -2464,6 +2160,24 @@ set :protection, :session => true
|
|
2464
2160
|
</dd>
|
2465
2161
|
</dl>
|
2466
2162
|
|
2163
|
+
## Lifecycle Events
|
2164
|
+
|
2165
|
+
There are 2 lifecycle events currently exposed by Sinatra. One when the server starts and one when it stops.
|
2166
|
+
|
2167
|
+
They can be used like this:
|
2168
|
+
|
2169
|
+
```ruby
|
2170
|
+
on_start do
|
2171
|
+
puts "===== Booting up ====="
|
2172
|
+
end
|
2173
|
+
|
2174
|
+
on_stop do
|
2175
|
+
puts "===== Shutting down ====="
|
2176
|
+
end
|
2177
|
+
```
|
2178
|
+
|
2179
|
+
Note that these callbacks only work when using Sinatra to start the web server.
|
2180
|
+
|
2467
2181
|
## Environments
|
2468
2182
|
|
2469
2183
|
There are three predefined `environments`: `"development"`,
|
@@ -2520,6 +2234,14 @@ show exceptions option to `:after_handler`:
|
|
2520
2234
|
set :show_exceptions, :after_handler
|
2521
2235
|
```
|
2522
2236
|
|
2237
|
+
A catch-all error handler can be defined with `error` and a block:
|
2238
|
+
|
2239
|
+
```ruby
|
2240
|
+
error do
|
2241
|
+
'Sorry there was a nasty error'
|
2242
|
+
end
|
2243
|
+
```
|
2244
|
+
|
2523
2245
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2524
2246
|
|
2525
2247
|
```ruby
|
@@ -2528,7 +2250,7 @@ error do
|
|
2528
2250
|
end
|
2529
2251
|
```
|
2530
2252
|
|
2531
|
-
|
2253
|
+
Pass an error class as an argument to create handlers for custom errors:
|
2532
2254
|
|
2533
2255
|
```ruby
|
2534
2256
|
error MyCustomError do
|
@@ -2574,6 +2296,51 @@ Sinatra installs special `not_found` and `error` handlers when
|
|
2574
2296
|
running under the development environment to display nice stack traces
|
2575
2297
|
and additional debugging information in your browser.
|
2576
2298
|
|
2299
|
+
### Behavior with `raise_errors` option
|
2300
|
+
|
2301
|
+
When `raise_errors` option is `true`, errors that are unhandled are raised
|
2302
|
+
outside of the application. Additionally, any errors that would have been
|
2303
|
+
caught by the catch-all error handler are raised.
|
2304
|
+
|
2305
|
+
For example, consider the following configuration:
|
2306
|
+
|
2307
|
+
```ruby
|
2308
|
+
# First handler
|
2309
|
+
error MyCustomError do
|
2310
|
+
'A custom message'
|
2311
|
+
end
|
2312
|
+
|
2313
|
+
# Second handler
|
2314
|
+
error do
|
2315
|
+
'A catch-all message'
|
2316
|
+
end
|
2317
|
+
```
|
2318
|
+
|
2319
|
+
If `raise_errors` is `false`:
|
2320
|
+
|
2321
|
+
* When `MyCustomError` or descendant is raised, the first handler is invoked.
|
2322
|
+
The HTTP response body will contain `"A custom message"`.
|
2323
|
+
* When any other error is raised, the second handler is invoked. The HTTP
|
2324
|
+
response body will contain `"A catch-all message"`.
|
2325
|
+
|
2326
|
+
If `raise_errors` is `true`:
|
2327
|
+
|
2328
|
+
* When `MyCustomError` or descendant is raised, the behavior is identical to
|
2329
|
+
when `raise_errors` is `false`, described above.
|
2330
|
+
* When any other error is raised, the second handler is *not* invoked, and
|
2331
|
+
the error is raised outside of the application.
|
2332
|
+
* If the environment is `production`, the HTTP response body will contain
|
2333
|
+
a generic error message, e.g. `"An unhandled lowlevel error occurred. The
|
2334
|
+
application logs may have details."`
|
2335
|
+
* If the environment is not `production`, the HTTP response body will contain
|
2336
|
+
the verbose error backtrace.
|
2337
|
+
* Regardless of environment, if `show_exceptions` is set to `:after_handler`,
|
2338
|
+
the HTTP response body will contain the verbose error backtrace.
|
2339
|
+
|
2340
|
+
In the `test` environment, `raise_errors` is set to `true` by default. This
|
2341
|
+
means that in order to write a test for a catch-all error handler,
|
2342
|
+
`raise_errors` must temporarily be set to `false` for that particular test.
|
2343
|
+
|
2577
2344
|
## Rack Middleware
|
2578
2345
|
|
2579
2346
|
Sinatra rides on [Rack](https://rack.github.io/), a minimal standard
|
@@ -2599,7 +2366,7 @@ end
|
|
2599
2366
|
```
|
2600
2367
|
|
2601
2368
|
The semantics of `use` are identical to those defined for the
|
2602
|
-
[Rack::Builder](
|
2369
|
+
[Rack::Builder](https://www.rubydoc.info/github/rack/rack/main/Rack/Builder) DSL
|
2603
2370
|
(most frequently used from rackup files). For example, the `use` method
|
2604
2371
|
accepts multiple/variable args as well as blocks:
|
2605
2372
|
|
@@ -2615,7 +2382,7 @@ many of these components automatically based on configuration so you
|
|
2615
2382
|
typically don't have to `use` them explicitly.
|
2616
2383
|
|
2617
2384
|
You can find useful middleware in
|
2618
|
-
[rack](https://github.com/rack/rack/tree/
|
2385
|
+
[rack](https://github.com/rack/rack/tree/main/lib/rack),
|
2619
2386
|
[rack-contrib](https://github.com/rack/rack-contrib#readme),
|
2620
2387
|
or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
2621
2388
|
|
@@ -2623,7 +2390,7 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2623
2390
|
|
2624
2391
|
Sinatra tests can be written using any Rack-based testing library or
|
2625
2392
|
framework.
|
2626
|
-
[Rack::Test](
|
2393
|
+
[Rack::Test](https://www.rubydoc.info/github/rack/rack-test/main/frames)
|
2627
2394
|
is recommended:
|
2628
2395
|
|
2629
2396
|
```ruby
|
@@ -3047,47 +2814,15 @@ by Konstantin_
|
|
3047
2814
|
Sinatra doesn't impose any concurrency model but leaves that to the
|
3048
2815
|
underlying Rack handler (server) like Puma or WEBrick. Sinatra
|
3049
2816
|
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
|
-
```
|
2817
|
+
uses a threaded model of concurrency.
|
3083
2818
|
|
3084
2819
|
## Requirement
|
3085
2820
|
|
3086
2821
|
The following Ruby versions are officially supported:
|
3087
2822
|
<dl>
|
3088
|
-
<dt>Ruby 2.
|
2823
|
+
<dt>Ruby 2.6</dt>
|
3089
2824
|
<dd>
|
3090
|
-
2.
|
2825
|
+
2.6 is fully supported and recommended. There are currently no plans to
|
3091
2826
|
drop official support for it.
|
3092
2827
|
</dd>
|
3093
2828
|
|
@@ -3105,37 +2840,20 @@ The following Ruby versions are officially supported:
|
|
3105
2840
|
</dd>
|
3106
2841
|
</dl>
|
3107
2842
|
|
3108
|
-
Versions of Ruby before 2.
|
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:
|
2843
|
+
Versions of Ruby before 2.6 are no longer supported as of Sinatra 3.0.0.
|
3114
2844
|
|
3115
|
-
|
3116
|
-
|
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.
|
2845
|
+
We also keep an eye on upcoming Ruby versions. Expect upcoming
|
2846
|
+
3.x releases to be fully supported.
|
3126
2847
|
|
3127
2848
|
Sinatra should work on any operating system supported by the chosen Ruby
|
3128
2849
|
implementation.
|
3129
2850
|
|
3130
|
-
|
3131
|
-
|
3132
|
-
Sinatra currently doesn't run on Cardinal, SmallRuby, BlueRuby or any
|
3133
|
-
Ruby version prior to 2.2.
|
2851
|
+
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
2852
|
|
3135
2853
|
## The Bleeding Edge
|
3136
2854
|
|
3137
2855
|
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
3138
|
-
to run your application against the
|
2856
|
+
to run your application against the main branch, it should be rather
|
3139
2857
|
stable.
|
3140
2858
|
|
3141
2859
|
We also push out prerelease gems from time to time, so you can do a
|
@@ -3184,20 +2902,19 @@ SemVerTag.
|
|
3184
2902
|
|
3185
2903
|
## Further Reading
|
3186
2904
|
|
3187
|
-
* [Project Website](
|
2905
|
+
* [Project Website](https://sinatrarb.com/) - Additional documentation,
|
3188
2906
|
news, and links to other resources.
|
3189
|
-
* [Contributing](
|
2907
|
+
* [Contributing](https://sinatrarb.com/contributing) - Find a bug? Need
|
3190
2908
|
help? Have a patch?
|
3191
2909
|
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
3192
2910
|
* [Twitter](https://twitter.com/sinatra)
|
3193
2911
|
* [Mailing List](https://groups.google.com/forum/#!forum/sinatrarb)
|
3194
2912
|
* 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/))
|
2913
|
+
* [Sinatra & Friends](https://discord.gg/ncjsfsNHh7) on Discord
|
3197
2914
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book) - Cookbook Tutorial
|
3198
2915
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) - Community contributed
|
3199
2916
|
recipes
|
3200
|
-
* API documentation for the [latest release](
|
3201
|
-
or the [current HEAD](
|
3202
|
-
[RubyDoc](
|
3203
|
-
* [CI
|
2917
|
+
* API documentation for the [latest release](https://www.rubydoc.info/gems/sinatra)
|
2918
|
+
or the [current HEAD](https://www.rubydoc.info/github/sinatra/sinatra) on
|
2919
|
+
[RubyDoc](https://www.rubydoc.info/)
|
2920
|
+
* [CI Actions](https://github.com/sinatra/sinatra/actions)
|