sinatra 2.0.7 → 3.0.6
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/CHANGELOG.md +216 -0
- data/CONTRIBUTING.md +11 -11
- data/Gemfile +44 -61
- data/MAINTENANCE.md +3 -16
- data/README.md +205 -470
- data/Rakefile +66 -75
- data/VERSION +1 -1
- data/examples/chat.rb +25 -11
- data/examples/rainbows.conf +3 -0
- data/examples/rainbows.rb +22 -0
- data/examples/simple.rb +2 -0
- data/examples/stream.ru +6 -4
- data/lib/sinatra/base.rb +466 -398
- data/lib/sinatra/indifferent_hash.rb +51 -41
- data/lib/sinatra/main.rb +19 -17
- data/lib/sinatra/show_exceptions.rb +19 -52
- data/lib/sinatra/version.rb +3 -1
- data/lib/sinatra.rb +2 -0
- data/sinatra.gemspec +40 -41
- metadata +41 -43
- data/README.de.md +0 -3239
- data/README.es.md +0 -3202
- data/README.fr.md +0 -3014
- 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 -1760
- data/README.pt-pt.md +0 -791
- data/README.ru.md +0 -3207
- data/README.zh.md +0 -2934
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:
|
|
@@ -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,92 @@ 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
|
-
It is recommended to also run `gem install
|
|
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
|
-
* [Application/Class Scope](#applicationclass-scope)
|
|
120
|
-
* [Request/Instance Scope](#requestinstance-scope)
|
|
121
|
-
* [Delegation Scope](#delegation-scope)
|
|
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
|
+
- [Liquid Templates](#liquid-templates)
|
|
58
|
+
- [Markdown Templates](#markdown-templates)
|
|
59
|
+
- [RDoc Templates](#rdoc-templates)
|
|
60
|
+
- [AsciiDoc Templates](#asciidoc-templates)
|
|
61
|
+
- [Markaby Templates](#markaby-templates)
|
|
62
|
+
- [RABL Templates](#rabl-templates)
|
|
63
|
+
- [Slim Templates](#slim-templates)
|
|
64
|
+
- [Yajl Templates](#yajl-templates)
|
|
65
|
+
- [Accessing Variables in Templates](#accessing-variables-in-templates)
|
|
66
|
+
- [Templates with `yield` and nested layouts](#templates-with-yield-and-nested-layouts)
|
|
67
|
+
- [Inline Templates](#inline-templates)
|
|
68
|
+
- [Named Templates](#named-templates)
|
|
69
|
+
- [Associating File Extensions](#associating-file-extensions)
|
|
70
|
+
- [Adding Your Own Template Engine](#adding-your-own-template-engine)
|
|
71
|
+
- [Using Custom Logic for Template Lookup](#using-custom-logic-for-template-lookup)
|
|
72
|
+
- [Filters](#filters)
|
|
73
|
+
- [Helpers](#helpers)
|
|
74
|
+
- [Using Sessions](#using-sessions)
|
|
75
|
+
- [Session Secret Security](#session-secret-security)
|
|
76
|
+
- [Session Config](#session-config)
|
|
77
|
+
- [Choosing Your Own Session Middleware](#choosing-your-own-session-middleware)
|
|
78
|
+
- [Halting](#halting)
|
|
79
|
+
- [Passing](#passing)
|
|
80
|
+
- [Triggering Another Route](#triggering-another-route)
|
|
81
|
+
- [Setting Body, Status Code, and Headers](#setting-body-status-code-and-headers)
|
|
82
|
+
- [Streaming Responses](#streaming-responses)
|
|
83
|
+
- [Logging](#logging)
|
|
84
|
+
- [Mime Types](#mime-types)
|
|
85
|
+
- [Generating URLs](#generating-urls)
|
|
86
|
+
- [Browser Redirect](#browser-redirect)
|
|
87
|
+
- [Cache Control](#cache-control)
|
|
88
|
+
- [Sending Files](#sending-files)
|
|
89
|
+
- [Accessing the Request Object](#accessing-the-request-object)
|
|
90
|
+
- [Attachments](#attachments)
|
|
91
|
+
- [Dealing with Date and Time](#dealing-with-date-and-time)
|
|
92
|
+
- [Looking Up Template Files](#looking-up-template-files)
|
|
93
|
+
- [Configuration](#configuration)
|
|
94
|
+
- [Configuring attack protection](#configuring-attack-protection)
|
|
95
|
+
- [Available Settings](#available-settings)
|
|
96
|
+
- [Environments](#environments)
|
|
97
|
+
- [Error Handling](#error-handling)
|
|
98
|
+
- [Not Found](#not-found)
|
|
99
|
+
- [Error](#error)
|
|
100
|
+
- [Rack Middleware](#rack-middleware)
|
|
101
|
+
- [Testing](#testing)
|
|
102
|
+
- [Sinatra::Base - Middleware, Libraries, and Modular Apps](#sinatrabase---middleware-libraries-and-modular-apps)
|
|
103
|
+
- [Modular vs. Classic Style](#modular-vs-classic-style)
|
|
104
|
+
- [Serving a Modular Application](#serving-a-modular-application)
|
|
105
|
+
- [Using a Classic Style Application with a config.ru](#using-a-classic-style-application-with-a-configru)
|
|
106
|
+
- [When to use a config.ru?](#when-to-use-a-configru)
|
|
107
|
+
- [Using Sinatra as Middleware](#using-sinatra-as-middleware)
|
|
108
|
+
- [Dynamic Application Creation](#dynamic-application-creation)
|
|
109
|
+
- [Scopes and Binding](#scopes-and-binding)
|
|
110
|
+
- [Application/Class Scope](#applicationclass-scope)
|
|
111
|
+
- [Request/Instance Scope](#requestinstance-scope)
|
|
112
|
+
- [Delegation Scope](#delegation-scope)
|
|
113
|
+
- [Command Line](#command-line)
|
|
114
|
+
- [Multi-threading](#multi-threading)
|
|
115
|
+
- [Requirement](#requirement)
|
|
116
|
+
- [The Bleeding Edge](#the-bleeding-edge)
|
|
117
|
+
- [With Bundler](#with-bundler)
|
|
118
|
+
- [Versioning](#versioning)
|
|
119
|
+
- [Further Reading](#further-reading)
|
|
129
120
|
|
|
130
121
|
## Routes
|
|
131
122
|
|
|
@@ -344,11 +335,11 @@ end
|
|
|
344
335
|
## Return Values
|
|
345
336
|
|
|
346
337
|
The return value of a route block determines at least the response body
|
|
347
|
-
passed on to the HTTP client
|
|
338
|
+
passed on to the HTTP client or at least the next middleware in the
|
|
348
339
|
Rack stack. Most commonly, this is a string, as in the above examples.
|
|
349
340
|
But other values are also accepted.
|
|
350
341
|
|
|
351
|
-
You can return
|
|
342
|
+
You can return an object that would either be a valid Rack response, Rack
|
|
352
343
|
body object or HTTP status code:
|
|
353
344
|
|
|
354
345
|
* An Array with three elements: `[status (Integer), headers (Hash), response
|
|
@@ -372,7 +363,7 @@ get('/') { Stream.new }
|
|
|
372
363
|
```
|
|
373
364
|
|
|
374
365
|
You can also use the `stream` helper method ([described below](#streaming-responses)) to reduce
|
|
375
|
-
|
|
366
|
+
boilerplate and embed the streaming logic in the route.
|
|
376
367
|
|
|
377
368
|
## Custom Route Matchers
|
|
378
369
|
|
|
@@ -382,15 +373,16 @@ stop there. You can easily define your own matchers:
|
|
|
382
373
|
|
|
383
374
|
```ruby
|
|
384
375
|
class AllButPattern
|
|
385
|
-
Match = Struct.new(:captures)
|
|
386
|
-
|
|
387
376
|
def initialize(except)
|
|
388
|
-
@except
|
|
389
|
-
|
|
377
|
+
@except = except
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def to_pattern(options)
|
|
381
|
+
return self
|
|
390
382
|
end
|
|
391
383
|
|
|
392
|
-
def
|
|
393
|
-
|
|
384
|
+
def params(route)
|
|
385
|
+
return {} unless @except === route
|
|
394
386
|
end
|
|
395
387
|
end
|
|
396
388
|
|
|
@@ -407,27 +399,19 @@ Note that the above example might be over-engineered, as it can also be
|
|
|
407
399
|
expressed as:
|
|
408
400
|
|
|
409
401
|
```ruby
|
|
410
|
-
get
|
|
402
|
+
get /.*/ do
|
|
411
403
|
pass if request.path_info == "/index"
|
|
412
404
|
# ...
|
|
413
405
|
end
|
|
414
406
|
```
|
|
415
407
|
|
|
416
|
-
Or, using negative look ahead:
|
|
417
|
-
|
|
418
|
-
```ruby
|
|
419
|
-
get %r{(?!/index)} do
|
|
420
|
-
# ...
|
|
421
|
-
end
|
|
422
|
-
```
|
|
423
|
-
|
|
424
408
|
## Static Files
|
|
425
409
|
|
|
426
410
|
Static files are served from the `./public` directory. You can specify
|
|
427
411
|
a different location by setting the `:public_folder` option:
|
|
428
412
|
|
|
429
413
|
```ruby
|
|
430
|
-
set :public_folder,
|
|
414
|
+
set :public_folder, __dir__ + '/static'
|
|
431
415
|
```
|
|
432
416
|
|
|
433
417
|
Note that the public directory name is not included in the URL. A file
|
|
@@ -584,7 +568,7 @@ Some languages have multiple implementations. To specify what implementation
|
|
|
584
568
|
to use (and to be thread-safe), you should simply require it first:
|
|
585
569
|
|
|
586
570
|
```ruby
|
|
587
|
-
require 'rdiscount'
|
|
571
|
+
require 'rdiscount'
|
|
588
572
|
get('/') { markdown :index }
|
|
589
573
|
```
|
|
590
574
|
|
|
@@ -612,14 +596,12 @@ get('/') { markdown :index }
|
|
|
612
596
|
<td>Dependency</td>
|
|
613
597
|
<td>
|
|
614
598
|
<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
599
|
or erb (included in Ruby)
|
|
617
600
|
</td>
|
|
618
601
|
</tr>
|
|
619
602
|
<tr>
|
|
620
603
|
<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>
|
|
604
|
+
<td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubi</tt> (Erubi only)</td>
|
|
623
605
|
</tr>
|
|
624
606
|
<tr>
|
|
625
607
|
<td>Example</td>
|
|
@@ -667,56 +649,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
|
667
649
|
|
|
668
650
|
It also takes a block for inline templates (see [example](#inline-templates)).
|
|
669
651
|
|
|
670
|
-
#### Sass Templates
|
|
671
|
-
|
|
672
|
-
<table>
|
|
673
|
-
<tr>
|
|
674
|
-
<td>Dependency</td>
|
|
675
|
-
<td><a href="https://sass-lang.com/" title="sass">sass</a></td>
|
|
676
|
-
</tr>
|
|
677
|
-
<tr>
|
|
678
|
-
<td>File Extension</td>
|
|
679
|
-
<td><tt>.sass</tt></td>
|
|
680
|
-
</tr>
|
|
681
|
-
<tr>
|
|
682
|
-
<td>Example</td>
|
|
683
|
-
<td><tt>sass :stylesheet, :style => :expanded</tt></td>
|
|
684
|
-
</tr>
|
|
685
|
-
</table>
|
|
686
|
-
|
|
687
|
-
#### SCSS Templates
|
|
688
|
-
|
|
689
|
-
<table>
|
|
690
|
-
<tr>
|
|
691
|
-
<td>Dependency</td>
|
|
692
|
-
<td><a href="https://sass-lang.com/" title="sass">sass</a></td>
|
|
693
|
-
</tr>
|
|
694
|
-
<tr>
|
|
695
|
-
<td>File Extension</td>
|
|
696
|
-
<td><tt>.scss</tt></td>
|
|
697
|
-
</tr>
|
|
698
|
-
<tr>
|
|
699
|
-
<td>Example</td>
|
|
700
|
-
<td><tt>scss :stylesheet, :style => :expanded</tt></td>
|
|
701
|
-
</tr>
|
|
702
|
-
</table>
|
|
703
|
-
|
|
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
652
|
|
|
721
653
|
#### Liquid Templates
|
|
722
654
|
|
|
@@ -747,9 +679,7 @@ template, you almost always want to pass locals to it.
|
|
|
747
679
|
Anyone of:
|
|
748
680
|
<a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
|
|
749
681
|
<a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
|
|
750
|
-
<a href="https://github.com/ged/bluecloth" title="BlueCloth">BlueCloth</a>,
|
|
751
682
|
<a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
|
|
752
|
-
<a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
|
|
753
683
|
<a href="https://github.com/gjtorikian/commonmarker" title="commonmarker">commonmarker</a>
|
|
754
684
|
<a href="https://github.com/alphabetum/pandoc-ruby" title="pandoc">pandoc</a>
|
|
755
685
|
</td>
|
|
@@ -784,42 +714,6 @@ Since you cannot call Ruby from Markdown, you cannot use layouts written in
|
|
|
784
714
|
Markdown. However, it is possible to use another rendering engine for the
|
|
785
715
|
template than for the layout by passing the `:layout_engine` option.
|
|
786
716
|
|
|
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
717
|
#### RDoc Templates
|
|
824
718
|
|
|
825
719
|
<table>
|
|
@@ -875,26 +769,6 @@ template than for the layout by passing the `:layout_engine` option.
|
|
|
875
769
|
Since you cannot call Ruby methods directly from an AsciiDoc template, you
|
|
876
770
|
almost always want to pass locals to it.
|
|
877
771
|
|
|
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
772
|
#### Markaby Templates
|
|
899
773
|
|
|
900
774
|
<table>
|
|
@@ -948,139 +822,6 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
|
948
822
|
</tr>
|
|
949
823
|
</table>
|
|
950
824
|
|
|
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
825
|
#### Yajl Templates
|
|
1085
826
|
|
|
1086
827
|
<table>
|
|
@@ -1122,27 +863,6 @@ var resource = {"foo":"bar","baz":"qux"};
|
|
|
1122
863
|
present(resource);
|
|
1123
864
|
```
|
|
1124
865
|
|
|
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
866
|
### Accessing Variables in Templates
|
|
1147
867
|
|
|
1148
868
|
Templates are evaluated within the same context as route handlers. Instance
|
|
@@ -1201,7 +921,7 @@ end
|
|
|
1201
921
|
```
|
|
1202
922
|
|
|
1203
923
|
Currently, the following rendering methods accept a block: `erb`, `haml`,
|
|
1204
|
-
`liquid`, `slim
|
|
924
|
+
`liquid`, `slim `. Also, the general `render` method accepts a block.
|
|
1205
925
|
|
|
1206
926
|
### Inline Templates
|
|
1207
927
|
|
|
@@ -1218,13 +938,13 @@ __END__
|
|
|
1218
938
|
|
|
1219
939
|
@@ layout
|
|
1220
940
|
%html
|
|
1221
|
-
|
|
941
|
+
!= yield
|
|
1222
942
|
|
|
1223
943
|
@@ index
|
|
1224
944
|
%div.title Hello world.
|
|
1225
945
|
```
|
|
1226
946
|
|
|
1227
|
-
NOTE: Inline templates defined in the source file that requires
|
|
947
|
+
NOTE: Inline templates defined in the source file that requires Sinatra are
|
|
1228
948
|
automatically loaded. Call `enable :inline_templates` explicitly if you
|
|
1229
949
|
have inline templates in other source files.
|
|
1230
950
|
|
|
@@ -1261,10 +981,10 @@ end
|
|
|
1261
981
|
|
|
1262
982
|
To associate a file extension with a template engine, use
|
|
1263
983
|
`Tilt.register`. For instance, if you like to use the file extension
|
|
1264
|
-
`tt` for
|
|
984
|
+
`tt` for Haml templates, you can do the following:
|
|
1265
985
|
|
|
1266
986
|
```ruby
|
|
1267
|
-
Tilt.register :
|
|
987
|
+
Tilt.register Tilt[:haml], :tt
|
|
1268
988
|
```
|
|
1269
989
|
|
|
1270
990
|
### Adding Your Own Template Engine
|
|
@@ -1272,7 +992,7 @@ Tilt.register :tt, Tilt[:textile]
|
|
|
1272
992
|
First, register your engine with Tilt, then create a rendering method:
|
|
1273
993
|
|
|
1274
994
|
```ruby
|
|
1275
|
-
Tilt.register :myat
|
|
995
|
+
Tilt.register MyAwesomeTemplateEngine, :myat
|
|
1276
996
|
|
|
1277
997
|
helpers do
|
|
1278
998
|
def myat(*args) render(:myat, *args) end
|
|
@@ -1293,7 +1013,7 @@ own `#find_template` method:
|
|
|
1293
1013
|
|
|
1294
1014
|
```ruby
|
|
1295
1015
|
configure do
|
|
1296
|
-
set :views [ './views/a', './views/b' ]
|
|
1016
|
+
set :views, [ './views/a', './views/b' ]
|
|
1297
1017
|
end
|
|
1298
1018
|
|
|
1299
1019
|
def find_template(views, name, engine, &block)
|
|
@@ -1434,7 +1154,7 @@ For better security and usability it's
|
|
|
1434
1154
|
secret and store it in an environment variable on each host running your
|
|
1435
1155
|
application so that all of your application instances will share the same
|
|
1436
1156
|
secret. You should periodically rotate this session secret to a new value.
|
|
1437
|
-
Here are some examples of how you might create a 64
|
|
1157
|
+
Here are some examples of how you might create a 64-byte secret and set it:
|
|
1438
1158
|
|
|
1439
1159
|
**Session Secret Generation**
|
|
1440
1160
|
|
|
@@ -1446,7 +1166,7 @@ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
|
|
|
1446
1166
|
**Session Secret Generation (Bonus Points)**
|
|
1447
1167
|
|
|
1448
1168
|
Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
|
|
1449
|
-
|
|
1169
|
+
use the system RNG facilities to generate random values instead of
|
|
1450
1170
|
userspace `OpenSSL` which MRI Ruby currently defaults to:
|
|
1451
1171
|
|
|
1452
1172
|
```text
|
|
@@ -1472,7 +1192,7 @@ purposes only:
|
|
|
1472
1192
|
|
|
1473
1193
|
**Session Secret App Config**
|
|
1474
1194
|
|
|
1475
|
-
|
|
1195
|
+
Set up your app config to fail-safe to a secure random secret
|
|
1476
1196
|
if the `SESSION_SECRET` environment variable is not available.
|
|
1477
1197
|
|
|
1478
1198
|
For bonus points use the [sysrandom
|
|
@@ -1593,7 +1313,7 @@ matching route. If no matching route is found, a 404 is returned.
|
|
|
1593
1313
|
|
|
1594
1314
|
### Triggering Another Route
|
|
1595
1315
|
|
|
1596
|
-
Sometimes `pass` is not what you want, instead you would like to get the
|
|
1316
|
+
Sometimes `pass` is not what you want, instead, you would like to get the
|
|
1597
1317
|
result of calling another route. Simply use `call` to achieve this:
|
|
1598
1318
|
|
|
1599
1319
|
```ruby
|
|
@@ -1616,13 +1336,13 @@ than a duplicate, use `call!` instead of `call`.
|
|
|
1616
1336
|
|
|
1617
1337
|
Check out the Rack specification if you want to learn more about `call`.
|
|
1618
1338
|
|
|
1619
|
-
### Setting Body, Status Code and Headers
|
|
1339
|
+
### Setting Body, Status Code, and Headers
|
|
1620
1340
|
|
|
1621
1341
|
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
|
|
1342
|
+
the return value of the route block. However, in some scenarios, you might
|
|
1623
1343
|
want to set the body at an arbitrary point in the execution flow. You can do
|
|
1624
1344
|
so with the `body` helper method. If you do so, you can use that method from
|
|
1625
|
-
|
|
1345
|
+
thereon to access the body:
|
|
1626
1346
|
|
|
1627
1347
|
```ruby
|
|
1628
1348
|
get '/foo' do
|
|
@@ -1645,7 +1365,7 @@ get '/foo' do
|
|
|
1645
1365
|
headers \
|
|
1646
1366
|
"Allow" => "BREW, POST, GET, PROPFIND, WHEN",
|
|
1647
1367
|
"Refresh" => "Refresh: 20; https://ietf.org/rfc/rfc2324.txt"
|
|
1648
|
-
body "I'm a
|
|
1368
|
+
body "I'm a teapot!"
|
|
1649
1369
|
end
|
|
1650
1370
|
```
|
|
1651
1371
|
|
|
@@ -1678,43 +1398,59 @@ also be used to increase throughput if some but not all content depends on a
|
|
|
1678
1398
|
slow resource.
|
|
1679
1399
|
|
|
1680
1400
|
Note that the streaming behavior, especially the number of concurrent
|
|
1681
|
-
requests, highly depends on the
|
|
1401
|
+
requests, highly depends on the webserver used to serve the application.
|
|
1682
1402
|
Some servers might not even support streaming at all. If the server does not
|
|
1683
1403
|
support streaming, the body will be sent all at once after the block passed
|
|
1684
1404
|
to `stream` finishes executing. Streaming does not work at all with Shotgun.
|
|
1685
1405
|
|
|
1686
1406
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
|
1687
1407
|
the stream object, allowing you to close it at any later point in the
|
|
1688
|
-
execution flow. This only works on evented servers, like
|
|
1408
|
+
execution flow. This only works on evented servers, like Rainbows.
|
|
1689
1409
|
Other servers will still close the stream:
|
|
1690
1410
|
|
|
1691
1411
|
```ruby
|
|
1692
|
-
#
|
|
1693
|
-
|
|
1694
|
-
set :server, :thin
|
|
1695
|
-
connections = []
|
|
1412
|
+
# config.ru
|
|
1413
|
+
require 'sinatra/base'
|
|
1696
1414
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
#
|
|
1702
|
-
|
|
1415
|
+
class App < Sinatra::Base
|
|
1416
|
+
connections = []
|
|
1417
|
+
|
|
1418
|
+
get '/subscribe', provides: 'text/event-stream' do
|
|
1419
|
+
# register a client's interest in server events
|
|
1420
|
+
stream(:keep_open) do |out|
|
|
1421
|
+
connections << out
|
|
1422
|
+
# purge dead connections
|
|
1423
|
+
connections.reject!(&:closed?)
|
|
1424
|
+
end
|
|
1703
1425
|
end
|
|
1704
|
-
end
|
|
1705
1426
|
|
|
1706
|
-
post '
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1427
|
+
post '/' do
|
|
1428
|
+
connections.each do |out|
|
|
1429
|
+
# notify client that a new message has arrived
|
|
1430
|
+
out << "data: #{params[:msg]}\n\n"
|
|
1710
1431
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1432
|
+
# indicate client to connect again
|
|
1433
|
+
out.close
|
|
1434
|
+
end
|
|
1435
|
+
|
|
1436
|
+
204 # response without entity body
|
|
1713
1437
|
end
|
|
1438
|
+
end
|
|
1714
1439
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1440
|
+
run App
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
```ruby
|
|
1444
|
+
# rainbows.conf
|
|
1445
|
+
Rainbows! do
|
|
1446
|
+
use :EventMachine
|
|
1717
1447
|
end
|
|
1448
|
+
````
|
|
1449
|
+
|
|
1450
|
+
Run:
|
|
1451
|
+
|
|
1452
|
+
```shell
|
|
1453
|
+
rainbows -c rainbows.conf
|
|
1718
1454
|
```
|
|
1719
1455
|
|
|
1720
1456
|
It's also possible for the client to close the connection when trying to
|
|
@@ -1747,7 +1483,7 @@ class MyApp < Sinatra::Base
|
|
|
1747
1483
|
end
|
|
1748
1484
|
```
|
|
1749
1485
|
|
|
1750
|
-
To avoid any logging middleware to be set up, set the `logging`
|
|
1486
|
+
To avoid any logging middleware to be set up, set the `logging` option to
|
|
1751
1487
|
`nil`. However, keep in mind that `logger` will in that case return `nil`. A
|
|
1752
1488
|
common use case is when you want to set your own logger. Sinatra will use
|
|
1753
1489
|
whatever it will find in `env['rack.logger']`.
|
|
@@ -1781,7 +1517,7 @@ Haml:
|
|
|
1781
1517
|
%a{:href => url('/foo')} foo
|
|
1782
1518
|
```
|
|
1783
1519
|
|
|
1784
|
-
It takes reverse proxies and Rack routers into account
|
|
1520
|
+
It takes reverse proxies and Rack routers into account - if present.
|
|
1785
1521
|
|
|
1786
1522
|
This method is also aliased to `to` (see [below](#browser-redirect) for an example).
|
|
1787
1523
|
|
|
@@ -2120,7 +1856,7 @@ end
|
|
|
2120
1856
|
Another example would be using different directories for different engines:
|
|
2121
1857
|
|
|
2122
1858
|
```ruby
|
|
2123
|
-
set :views, :
|
|
1859
|
+
set :views, :haml => 'templates', :default => 'views'
|
|
2124
1860
|
|
|
2125
1861
|
helpers do
|
|
2126
1862
|
def find_template(views, name, engine, &block)
|
|
@@ -2131,7 +1867,7 @@ helpers do
|
|
|
2131
1867
|
end
|
|
2132
1868
|
```
|
|
2133
1869
|
|
|
2134
|
-
You can also easily wrap this up in an extension and share with others!
|
|
1870
|
+
You can also easily wrap this up in an extension and share it with others!
|
|
2135
1871
|
|
|
2136
1872
|
Note that `find_template` does not check if the file really exists but
|
|
2137
1873
|
rather calls the given block for all possible paths. This is not a
|
|
@@ -2197,7 +1933,7 @@ end
|
|
|
2197
1933
|
### Configuring attack protection
|
|
2198
1934
|
|
|
2199
1935
|
Sinatra is using
|
|
2200
|
-
[Rack::Protection](https://github.com/sinatra/sinatra/tree/
|
|
1936
|
+
[Rack::Protection](https://github.com/sinatra/sinatra/tree/main/rack-protection#readme) to
|
|
2201
1937
|
defend your application against common, opportunistic attacks. You can
|
|
2202
1938
|
easily disable this behavior (which will open up your application to tons
|
|
2203
1939
|
of common vulnerabilities):
|
|
@@ -2220,7 +1956,7 @@ set :protection, :except => [:path_traversal, :session_hijacking]
|
|
|
2220
1956
|
By default, Sinatra will only set up session based protection if `:sessions`
|
|
2221
1957
|
have been enabled. See '[Using Sessions](#using-sessions)'. Sometimes you may want to set up
|
|
2222
1958
|
sessions "outside" of the Sinatra app, such as in the config.ru or with a
|
|
2223
|
-
separate `Rack::Builder` instance. In that case you can still set up session
|
|
1959
|
+
separate `Rack::Builder` instance. In that case, you can still set up session
|
|
2224
1960
|
based protection by passing the `:session` option:
|
|
2225
1961
|
|
|
2226
1962
|
```ruby
|
|
@@ -2264,11 +2000,20 @@ set :protection, :session => true
|
|
|
2264
2000
|
used for built-in server.
|
|
2265
2001
|
</dd>
|
|
2266
2002
|
|
|
2003
|
+
<dt>default_content_type</dt>
|
|
2004
|
+
<dd>
|
|
2005
|
+
Content-Type to assume if unknown (defaults to <tt>"text/html"</tt>). Set
|
|
2006
|
+
to <tt>nil</tt> to not set a default Content-Type on every response; when
|
|
2007
|
+
configured so, you must set the Content-Type manually when emitting content
|
|
2008
|
+
or the user-agent will have to sniff it (or, if <tt>nosniff</tt> is enabled
|
|
2009
|
+
in Rack::Protection::XSSHeader, assume <tt>application/octet-stream</tt>).
|
|
2010
|
+
</dd>
|
|
2011
|
+
|
|
2267
2012
|
<dt>default_encoding</dt>
|
|
2268
2013
|
<dd>Encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
|
|
2269
2014
|
|
|
2270
2015
|
<dt>dump_errors</dt>
|
|
2271
|
-
<dd>Display errors in the log.</dd>
|
|
2016
|
+
<dd>Display errors in the log. Enabled by default unless environment is "test".</dd>
|
|
2272
2017
|
|
|
2273
2018
|
<dt>environment</dt>
|
|
2274
2019
|
<dd>
|
|
@@ -2368,7 +2113,7 @@ set :protection, :session => true
|
|
|
2368
2113
|
If you are using a WEBrick web server, presumably for your development
|
|
2369
2114
|
environment, you can pass a hash of options to <tt>server_settings</tt>,
|
|
2370
2115
|
such as <tt>SSLEnable</tt> or <tt>SSLVerifyClient</tt>. However, web
|
|
2371
|
-
servers such as Puma
|
|
2116
|
+
servers such as Puma do not support this, so you can set
|
|
2372
2117
|
<tt>server_settings</tt> by defining it as a method when you call
|
|
2373
2118
|
<tt>configure</tt>.
|
|
2374
2119
|
</dd>
|
|
@@ -2419,7 +2164,7 @@ set :protection, :session => true
|
|
|
2419
2164
|
|
|
2420
2165
|
<dt>threaded</dt>
|
|
2421
2166
|
<dd>
|
|
2422
|
-
If set to <tt>true</tt>, will tell
|
|
2167
|
+
If set to <tt>true</tt>, will tell server to use
|
|
2423
2168
|
<tt>EventMachine.defer</tt> for processing the request.
|
|
2424
2169
|
</dd>
|
|
2425
2170
|
|
|
@@ -2574,7 +2319,7 @@ end
|
|
|
2574
2319
|
```
|
|
2575
2320
|
|
|
2576
2321
|
The semantics of `use` are identical to those defined for the
|
|
2577
|
-
[Rack::Builder](
|
|
2322
|
+
[Rack::Builder](https://www.rubydoc.info/github/rack/rack/main/Rack/Builder) DSL
|
|
2578
2323
|
(most frequently used from rackup files). For example, the `use` method
|
|
2579
2324
|
accepts multiple/variable args as well as blocks:
|
|
2580
2325
|
|
|
@@ -2590,7 +2335,7 @@ many of these components automatically based on configuration so you
|
|
|
2590
2335
|
typically don't have to `use` them explicitly.
|
|
2591
2336
|
|
|
2592
2337
|
You can find useful middleware in
|
|
2593
|
-
[rack](https://github.com/rack/rack/tree/
|
|
2338
|
+
[rack](https://github.com/rack/rack/tree/main/lib/rack),
|
|
2594
2339
|
[rack-contrib](https://github.com/rack/rack-contrib#readme),
|
|
2595
2340
|
or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2596
2341
|
|
|
@@ -2598,7 +2343,7 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
|
2598
2343
|
|
|
2599
2344
|
Sinatra tests can be written using any Rack-based testing library or
|
|
2600
2345
|
framework.
|
|
2601
|
-
[Rack::Test](
|
|
2346
|
+
[Rack::Test](https://www.rubydoc.info/github/rack/rack-test/main/frames)
|
|
2602
2347
|
is recommended:
|
|
2603
2348
|
|
|
2604
2349
|
```ruby
|
|
@@ -2692,7 +2437,7 @@ modular application.
|
|
|
2692
2437
|
The main disadvantage of using the classic style rather than the modular
|
|
2693
2438
|
style is that you will only have one Sinatra application per Ruby
|
|
2694
2439
|
process. If you plan to use more than one, switch to the modular style.
|
|
2695
|
-
There is no reason you cannot mix the modular and
|
|
2440
|
+
There is no reason you cannot mix the modular and classic styles.
|
|
2696
2441
|
|
|
2697
2442
|
If switching from one style to the other, you should be aware of
|
|
2698
2443
|
slightly different default settings:
|
|
@@ -2821,7 +2566,7 @@ style for running with a `config.ru`.**
|
|
|
2821
2566
|
### Using Sinatra as Middleware
|
|
2822
2567
|
|
|
2823
2568
|
Not only is Sinatra able to use other Rack middleware, any Sinatra
|
|
2824
|
-
application can in turn be added in front of any Rack endpoint as
|
|
2569
|
+
application can, in turn, be added in front of any Rack endpoint as
|
|
2825
2570
|
middleware itself. This endpoint could be another Sinatra application,
|
|
2826
2571
|
or any other Rack-based application (Rails/Hanami/Roda/...):
|
|
2827
2572
|
|
|
@@ -2912,7 +2657,7 @@ available.
|
|
|
2912
2657
|
Every Sinatra application corresponds to a subclass of `Sinatra::Base`.
|
|
2913
2658
|
If you are using the top-level DSL (`require 'sinatra'`), then this
|
|
2914
2659
|
class is `Sinatra::Application`, otherwise it is the subclass you
|
|
2915
|
-
created explicitly. At class level you have methods like `get` or
|
|
2660
|
+
created explicitly. At the class level, you have methods like `get` or
|
|
2916
2661
|
`before`, but you cannot access the `request` or `session` objects, as
|
|
2917
2662
|
there is only a single application class for all requests.
|
|
2918
2663
|
|
|
@@ -2935,7 +2680,7 @@ You have the application scope binding inside:
|
|
|
2935
2680
|
* Your application class body
|
|
2936
2681
|
* Methods defined by extensions
|
|
2937
2682
|
* The block passed to `helpers`
|
|
2938
|
-
* Procs/blocks used as value for `set`
|
|
2683
|
+
* Procs/blocks used as a value for `set`
|
|
2939
2684
|
* The block passed to `Sinatra.new`
|
|
2940
2685
|
|
|
2941
2686
|
You can reach the scope object (the class) like this:
|
|
@@ -2986,7 +2731,7 @@ do not share variables/state with the class scope (read: you have a different
|
|
|
2986
2731
|
|
|
2987
2732
|
You have the delegate scope binding inside:
|
|
2988
2733
|
|
|
2989
|
-
* The top
|
|
2734
|
+
* The top-level binding, if you did `require "sinatra"`
|
|
2990
2735
|
* An object extended with the `Sinatra::Delegator` mixin
|
|
2991
2736
|
|
|
2992
2737
|
Have a look at the code for yourself: here's the
|
|
@@ -3008,7 +2753,7 @@ Options are:
|
|
|
3008
2753
|
-p # set the port (default is 4567)
|
|
3009
2754
|
-o # set the host (default is 0.0.0.0)
|
|
3010
2755
|
-e # set the environment (default is development)
|
|
3011
|
-
-s # specify rack server/handler (default is
|
|
2756
|
+
-s # specify rack server/handler (default is puma)
|
|
3012
2757
|
-q # turn on quiet mode for server (default is off)
|
|
3013
2758
|
-x # turn on the mutex lock (default is off)
|
|
3014
2759
|
```
|
|
@@ -3019,16 +2764,16 @@ _Paraphrasing from
|
|
|
3019
2764
|
[this StackOverflow answer](https://stackoverflow.com/a/6282999/5245129)
|
|
3020
2765
|
by Konstantin_
|
|
3021
2766
|
|
|
3022
|
-
Sinatra doesn't impose any concurrency model
|
|
3023
|
-
underlying Rack handler (server) like
|
|
2767
|
+
Sinatra doesn't impose any concurrency model but leaves that to the
|
|
2768
|
+
underlying Rack handler (server) like Puma or WEBrick. Sinatra
|
|
3024
2769
|
itself is thread-safe, so there won't be any problem if the Rack handler
|
|
3025
2770
|
uses a threaded model of concurrency. This would mean that when starting
|
|
3026
2771
|
the server, you'd have to specify the correct invocation method for the
|
|
3027
2772
|
specific Rack handler. The following example is a demonstration of how
|
|
3028
|
-
to start a multi-threaded
|
|
2773
|
+
to start a multi-threaded Rainbows server:
|
|
3029
2774
|
|
|
3030
2775
|
```ruby
|
|
3031
|
-
#
|
|
2776
|
+
# config.ru
|
|
3032
2777
|
|
|
3033
2778
|
require 'sinatra/base'
|
|
3034
2779
|
|
|
@@ -3038,23 +2783,31 @@ class App < Sinatra::Base
|
|
|
3038
2783
|
end
|
|
3039
2784
|
end
|
|
3040
2785
|
|
|
3041
|
-
App
|
|
2786
|
+
run App
|
|
2787
|
+
```
|
|
2788
|
+
|
|
2789
|
+
```ruby
|
|
2790
|
+
# rainbows.conf
|
|
3042
2791
|
|
|
2792
|
+
# Rainbows configurator is based on Unicorn.
|
|
2793
|
+
Rainbows! do
|
|
2794
|
+
use :ThreadSpawn
|
|
2795
|
+
end
|
|
3043
2796
|
```
|
|
3044
2797
|
|
|
3045
2798
|
To start the server, the command would be:
|
|
3046
2799
|
|
|
3047
2800
|
```shell
|
|
3048
|
-
|
|
2801
|
+
rainbows -c rainbows.conf
|
|
3049
2802
|
```
|
|
3050
2803
|
|
|
3051
2804
|
## Requirement
|
|
3052
2805
|
|
|
3053
2806
|
The following Ruby versions are officially supported:
|
|
3054
2807
|
<dl>
|
|
3055
|
-
<dt>Ruby 2.
|
|
2808
|
+
<dt>Ruby 2.6</dt>
|
|
3056
2809
|
<dd>
|
|
3057
|
-
2.
|
|
2810
|
+
2.6 is fully supported and recommended. There are currently no plans to
|
|
3058
2811
|
drop official support for it.
|
|
3059
2812
|
</dd>
|
|
3060
2813
|
|
|
@@ -3072,37 +2825,20 @@ The following Ruby versions are officially supported:
|
|
|
3072
2825
|
</dd>
|
|
3073
2826
|
</dl>
|
|
3074
2827
|
|
|
3075
|
-
Versions of Ruby
|
|
3076
|
-
|
|
3077
|
-
We also keep an eye on upcoming Ruby versions.
|
|
3078
|
-
|
|
3079
|
-
The following Ruby implementations are not officially supported but still are
|
|
3080
|
-
known to run Sinatra:
|
|
2828
|
+
Versions of Ruby before 2.6 are no longer supported as of Sinatra 3.0.0.
|
|
3081
2829
|
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
* MacRuby, Maglev, IronRuby
|
|
3085
|
-
* Ruby 1.9.0 and 1.9.1 (but we do recommend against using those)
|
|
3086
|
-
|
|
3087
|
-
Not being officially supported means if things only break there and not on a
|
|
3088
|
-
supported platform, we assume it's not our issue but theirs.
|
|
3089
|
-
|
|
3090
|
-
We also run our CI against ruby-head (future releases of MRI), but we
|
|
3091
|
-
can't guarantee anything, since it is constantly moving. Expect upcoming
|
|
3092
|
-
2.x releases to be fully supported.
|
|
2830
|
+
We also keep an eye on upcoming Ruby versions. Expect upcoming
|
|
2831
|
+
3.x releases to be fully supported.
|
|
3093
2832
|
|
|
3094
2833
|
Sinatra should work on any operating system supported by the chosen Ruby
|
|
3095
2834
|
implementation.
|
|
3096
2835
|
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
Sinatra currently doesn't run on Cardinal, SmallRuby, BlueRuby or any
|
|
3100
|
-
Ruby version prior to 2.2.
|
|
2836
|
+
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.
|
|
3101
2837
|
|
|
3102
2838
|
## The Bleeding Edge
|
|
3103
2839
|
|
|
3104
2840
|
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
|
3105
|
-
to run your application against the
|
|
2841
|
+
to run your application against the main branch, it should be rather
|
|
3106
2842
|
stable.
|
|
3107
2843
|
|
|
3108
2844
|
We also push out prerelease gems from time to time, so you can do a
|
|
@@ -3151,20 +2887,19 @@ SemVerTag.
|
|
|
3151
2887
|
|
|
3152
2888
|
## Further Reading
|
|
3153
2889
|
|
|
3154
|
-
* [Project Website](
|
|
2890
|
+
* [Project Website](https://sinatrarb.com/) - Additional documentation,
|
|
3155
2891
|
news, and links to other resources.
|
|
3156
|
-
* [Contributing](
|
|
2892
|
+
* [Contributing](https://sinatrarb.com/contributing) - Find a bug? Need
|
|
3157
2893
|
help? Have a patch?
|
|
3158
2894
|
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
|
3159
2895
|
* [Twitter](https://twitter.com/sinatra)
|
|
3160
2896
|
* [Mailing List](https://groups.google.com/forum/#!forum/sinatrarb)
|
|
3161
2897
|
* IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on [Freenode](https://freenode.net)
|
|
3162
|
-
* [Sinatra & Friends](https://
|
|
3163
|
-
([get an invite](https://sinatra-slack.herokuapp.com/))
|
|
2898
|
+
* [Sinatra & Friends](https://discord.gg/ncjsfsNHh7) on Discord
|
|
3164
2899
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book) - Cookbook Tutorial
|
|
3165
2900
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) - Community contributed
|
|
3166
2901
|
recipes
|
|
3167
|
-
* API documentation for the [latest release](
|
|
3168
|
-
or the [current HEAD](
|
|
3169
|
-
[RubyDoc](
|
|
3170
|
-
* [CI
|
|
2902
|
+
* API documentation for the [latest release](https://www.rubydoc.info/gems/sinatra)
|
|
2903
|
+
or the [current HEAD](https://www.rubydoc.info/github/sinatra/sinatra) on
|
|
2904
|
+
[RubyDoc](https://www.rubydoc.info/)
|
|
2905
|
+
* [CI Actions](https://github.com/sinatra/sinatra/actions)
|