sinatra 3.0.6 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHORS.md +14 -8
- data/CHANGELOG.md +44 -0
- data/Gemfile +22 -10
- data/README.md +118 -103
- data/Rakefile +17 -5
- data/SECURITY.md +1 -1
- data/VERSION +1 -1
- data/examples/lifecycle_events.rb +20 -0
- data/examples/stream.ru +0 -2
- data/lib/sinatra/base.rb +83 -15
- data/lib/sinatra/indifferent_hash.rb +10 -2
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +0 -2
- metadata +9 -24
- data/examples/rainbows.conf +0 -3
- data/examples/rainbows.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6eddf8c0c677b8b8b7f15bb03834147034ead41bc6310bf773ac84712bb43a14
|
4
|
+
data.tar.gz: c35de3457f199d57a3c8a4419bd0ad113df38ba071cfffbcc79311db910bc1cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33e0785425af5a32c7e09d95e2d11e02d83cdda1d907b34197c63642bfec81cd04a40ffc2e25486fe45af66d9a681f57c41d083d7bc56f24b69f1cf4b3a478f6
|
7
|
+
data.tar.gz: 6aa65f3b65c819171bcadb61a3a43c3ff7af748d29a9177dbd02549229e3b9fa64b338d0404383b97615e74aa5381dd8a4c997edbf86ca0e8a2970e0213b2ece
|
data/AUTHORS.md
CHANGED
@@ -2,31 +2,37 @@ Sinatra was designed and developed by Blake Mizerany in California.
|
|
2
2
|
|
3
3
|
### Current Team
|
4
4
|
|
5
|
-
* **
|
5
|
+
* **Eloy Perez**
|
6
|
+
* **Jordan Owens**
|
7
|
+
* **Olle Jonsson**
|
8
|
+
* **Patrik Ragnarsson**
|
6
9
|
* **Zachary Scott**
|
7
|
-
* **Kashyap Kondamudi**
|
8
|
-
* **Ashley Williams**
|
9
|
-
* **Trevor Bramble**
|
10
|
-
* **Kunpei Sakai**
|
11
10
|
|
12
11
|
### Alumni
|
13
12
|
|
14
13
|
* **Blake Mizerany** (creator)
|
14
|
+
* **Konstantin Haase** (maintainer)
|
15
15
|
* **Ryan Tomayko**
|
16
16
|
* **Simon Rozet**
|
17
17
|
* **Katrina Owen**
|
18
|
+
* **Kashyap Kondamudi**
|
19
|
+
* **Ashley Williams**
|
20
|
+
* **Trevor Bramble**
|
21
|
+
* **Kunpei Sakai**
|
18
22
|
|
19
23
|
### Thanks
|
20
24
|
|
21
25
|
Sinatra would not have been possible without strong company backing.
|
22
26
|
In the past, financial and emotional support have been provided mainly by
|
23
|
-
[Heroku](
|
24
|
-
[Engine Yard](http://www.engineyard.com/)
|
25
|
-
[
|
27
|
+
[Heroku](https://heroku.com), [GitHub](https://github.com),
|
28
|
+
[Engine Yard](http://www.engineyard.com/) and [Travis CI](https://travis-ci.com/),
|
29
|
+
and is now taken care of by [84codes](https://www.84codes.com/).
|
26
30
|
|
27
31
|
Special thanks to the following extraordinary individuals, without whom
|
28
32
|
Sinatra would not be possible:
|
29
33
|
|
34
|
+
* [Benoit Daloze](https://eregon.me/blog/) (eregon) for help around TruffleRuby
|
35
|
+
and keyword arguments use in mustermann.
|
30
36
|
* [Ryan Tomayko](http://tomayko.com/) (rtomayko) for constantly fixing
|
31
37
|
whitespace errors __60d5006__
|
32
38
|
* [Ezra Zygmuntowicz](http://brainspl.at/) (ezmobius) for initial help and
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,50 @@
|
|
2
2
|
|
3
3
|
* _Your new feature here._
|
4
4
|
|
5
|
+
## 3.2.0 / 2023-12-29
|
6
|
+
|
7
|
+
* New: Add `#except` method to `Sinatra::IndifferentHash` ([#1940])
|
8
|
+
|
9
|
+
* New: Use `Exception#detailed_message` to show backtrace ([#1952])
|
10
|
+
|
11
|
+
* New: Add `Sinatra::HamlHelpers` to sinatra-contrib ([#1960])
|
12
|
+
|
13
|
+
* Fix: Add `base64` to rack-protection runtime dependencies ([#1946])
|
14
|
+
|
15
|
+
* Fix: Avoid open-ended dependencies for sinatra-contrib and rack-protection ([#1949])
|
16
|
+
|
17
|
+
* Fix: Helpful message when `Sinatra::Runner` times out ([#1975])
|
18
|
+
|
19
|
+
* Fix: Ruby 3.3 + Bundler 2.5 compatibility ([#1975])
|
20
|
+
|
21
|
+
[#1940]: https://github.com/sinatra/sinatra/pull/1940
|
22
|
+
[#1946]: https://github.com/sinatra/sinatra/pull/1946
|
23
|
+
[#1949]: https://github.com/sinatra/sinatra/pull/1949
|
24
|
+
[#1952]: https://github.com/sinatra/sinatra/pull/1952
|
25
|
+
[#1960]: https://github.com/sinatra/sinatra/pull/1960
|
26
|
+
[#1975]: https://github.com/sinatra/sinatra/pull/1960
|
27
|
+
|
28
|
+
## 3.1.0 / 2023-08-07
|
29
|
+
|
30
|
+
* New: Add sass support via sass-embedded [#1911] by なつき
|
31
|
+
|
32
|
+
* New: Add start and stop callbacks [#1913] by Jevin Sew
|
33
|
+
|
34
|
+
* New: Warn on dropping sessions [#1900] by Jonathan del Strother
|
35
|
+
|
36
|
+
* New: Make Puma the default server [#1924] by Patrik Ragnarsson
|
37
|
+
|
38
|
+
* Fix: Remove use of Tilt::Cache [#1922] by Jeremy Evans (allows use of Tilt 2.2.0 without deprecation warning)
|
39
|
+
|
40
|
+
* Fix: rack-protection: specify rack version requirement [#1932] by Patrik Ragnarsson
|
41
|
+
|
42
|
+
[#1911]: https://github.com/sinatra/sinatra/pull/1911
|
43
|
+
[#1913]: https://github.com/sinatra/sinatra/pull/1913
|
44
|
+
[#1900]: https://github.com/sinatra/sinatra/pull/1900
|
45
|
+
[#1924]: https://github.com/sinatra/sinatra/pull/1924
|
46
|
+
[#1922]: https://github.com/sinatra/sinatra/pull/1922
|
47
|
+
[#1932]: https://github.com/sinatra/sinatra/pull/1932
|
48
|
+
|
5
49
|
## 3.0.6 / 2023-04-11
|
6
50
|
|
7
51
|
* Fix: Add support to keep open streaming connections with Puma [#1858](https://github.com/sinatra/sinatra/pull/1858) by Jordan Owens
|
data/Gemfile
CHANGED
@@ -24,17 +24,22 @@ puma_version = { github: 'puma/puma' } if puma_version == 'head'
|
|
24
24
|
gem 'puma', puma_version
|
25
25
|
|
26
26
|
gem 'minitest', '~> 5.0'
|
27
|
-
gem 'rack-test'
|
27
|
+
gem 'rack-test'
|
28
28
|
gem 'rubocop', '~> 1.32.0', require: false
|
29
|
-
gem 'yard'
|
29
|
+
gem 'yard' # used by rake doc
|
30
30
|
|
31
31
|
gem 'rack-protection', path: 'rack-protection'
|
32
32
|
gem 'sinatra-contrib', path: 'sinatra-contrib'
|
33
33
|
|
34
|
-
|
34
|
+
# traces 0.10.0 started to use Ruby 2.7 syntax without specifying required Ruby version
|
35
|
+
# https://github.com/socketry/traces/pull/8#discussion_r1237988182
|
36
|
+
# async-http 0.60.2 added traces 0.10.0 as dependency
|
37
|
+
# https://github.com/socketry/async-http/pull/124/files#r1237988899
|
38
|
+
gem 'traces', '< 0.10.0' if RUBY_VERSION >= '2.6.0' && RUBY_VERSION < '2.7.0'
|
35
39
|
|
36
40
|
gem 'asciidoctor'
|
37
41
|
gem 'builder'
|
42
|
+
gem 'childprocess'
|
38
43
|
gem 'commonmarker', '~> 0.23.4', platforms: [:ruby]
|
39
44
|
gem 'erubi'
|
40
45
|
gem 'eventmachine'
|
@@ -42,18 +47,25 @@ gem 'falcon', '~> 0.40', platforms: [:ruby]
|
|
42
47
|
gem 'haml', '~> 6'
|
43
48
|
gem 'kramdown'
|
44
49
|
gem 'liquid'
|
45
|
-
|
50
|
+
# markaby 0.9.1 introduced Ruby 2.7 syntax in https://github.com/markaby/markaby/pull/44
|
51
|
+
# and does not specify required_ruby_version
|
52
|
+
if RUBY_VERSION >= '2.6.0' && RUBY_VERSION < '2.7.0'
|
53
|
+
gem 'markaby', '< 0.9.1'
|
54
|
+
else
|
55
|
+
gem 'markaby'
|
56
|
+
end
|
46
57
|
gem 'nokogiri', '> 1.5.0'
|
47
58
|
gem 'pandoc-ruby', '~> 2.0.2'
|
48
59
|
gem 'rabl'
|
49
|
-
|
50
|
-
gem 'rdiscount',
|
60
|
+
if RUBY_ENGINE == 'truffleruby'
|
61
|
+
gem 'rdiscount', '< 2.2.7.2' # https://github.com/oracle/truffleruby/issues/3362
|
62
|
+
else
|
63
|
+
gem 'rdiscount', platforms: [:ruby]
|
64
|
+
end
|
51
65
|
gem 'rdoc'
|
52
66
|
gem 'redcarpet', platforms: [:ruby]
|
67
|
+
gem 'sass-embedded', '~> 1.54'
|
53
68
|
gem 'simplecov', require: false
|
54
69
|
gem 'slim', '~> 4'
|
55
70
|
gem 'yajl-ruby', platforms: [:ruby]
|
56
|
-
|
57
|
-
gem 'json', platforms: %i[jruby mri]
|
58
|
-
|
59
|
-
gem 'jar-dependencies', '= 0.4.1', platforms: [:jruby] # Gem::LoadError with jar-dependencies 0.4.2
|
71
|
+
gem 'zeitwerk'
|
data/README.md
CHANGED
@@ -54,6 +54,8 @@ pick up if available.
|
|
54
54
|
- [Erb Templates](#erb-templates)
|
55
55
|
- [Builder Templates](#builder-templates)
|
56
56
|
- [Nokogiri Templates](#nokogiri-templates)
|
57
|
+
- [Sass Templates](#sass-templates)
|
58
|
+
- [Scss Templates](#scss-templates)
|
57
59
|
- [Liquid Templates](#liquid-templates)
|
58
60
|
- [Markdown Templates](#markdown-templates)
|
59
61
|
- [RDoc Templates](#rdoc-templates)
|
@@ -93,6 +95,7 @@ pick up if available.
|
|
93
95
|
- [Configuration](#configuration)
|
94
96
|
- [Configuring attack protection](#configuring-attack-protection)
|
95
97
|
- [Available Settings](#available-settings)
|
98
|
+
- [Lifecycle Events](#lifecycle-events)
|
96
99
|
- [Environments](#environments)
|
97
100
|
- [Error Handling](#error-handling)
|
98
101
|
- [Not Found](#not-found)
|
@@ -649,6 +652,39 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
649
652
|
|
650
653
|
It also takes a block for inline templates (see [example](#inline-templates)).
|
651
654
|
|
655
|
+
#### Sass Templates
|
656
|
+
|
657
|
+
<table>
|
658
|
+
<tr>
|
659
|
+
<td>Dependency</td>
|
660
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
661
|
+
</tr>
|
662
|
+
<tr>
|
663
|
+
<td>File Extension</td>
|
664
|
+
<td><tt>.sass</tt></td>
|
665
|
+
</tr>
|
666
|
+
<tr>
|
667
|
+
<td>Example</td>
|
668
|
+
<td><tt>sass :stylesheet, :style => :expanded</tt></td>
|
669
|
+
</tr>
|
670
|
+
</table>
|
671
|
+
|
672
|
+
#### Scss Templates
|
673
|
+
|
674
|
+
<table>
|
675
|
+
<tr>
|
676
|
+
<td>Dependency</td>
|
677
|
+
<td><a href="https://github.com/ntkme/sass-embedded-host-ruby" title="sass-embedded">sass-embedded</a></td>
|
678
|
+
</tr>
|
679
|
+
<tr>
|
680
|
+
<td>File Extension</td>
|
681
|
+
<td><tt>.scss</tt></td>
|
682
|
+
</tr>
|
683
|
+
<tr>
|
684
|
+
<td>Example</td>
|
685
|
+
<td><tt>scss :stylesheet, :style => :expanded</tt></td>
|
686
|
+
</tr>
|
687
|
+
</table>
|
652
688
|
|
653
689
|
#### Liquid Templates
|
654
690
|
|
@@ -810,7 +846,7 @@ It also takes a block for inline templates (see [example](#inline-templates)).
|
|
810
846
|
<table>
|
811
847
|
<tr>
|
812
848
|
<td>Dependency</td>
|
813
|
-
<td><a href="
|
849
|
+
<td><a href="https://slim-template.github.io/" title="Slim Lang">Slim Lang</a></td>
|
814
850
|
</tr>
|
815
851
|
<tr>
|
816
852
|
<td>File Extension</td>
|
@@ -1163,22 +1199,6 @@ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
|
|
1163
1199
|
99ae8af...snip...ec0f262ac
|
1164
1200
|
```
|
1165
1201
|
|
1166
|
-
**Session Secret Generation (Bonus Points)**
|
1167
|
-
|
1168
|
-
Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
|
1169
|
-
use the system RNG facilities to generate random values instead of
|
1170
|
-
userspace `OpenSSL` which MRI Ruby currently defaults to:
|
1171
|
-
|
1172
|
-
```text
|
1173
|
-
$ gem install sysrandom
|
1174
|
-
Building native extensions. This could take a while...
|
1175
|
-
Successfully installed sysrandom-1.x
|
1176
|
-
1 gem installed
|
1177
|
-
|
1178
|
-
$ ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
|
1179
|
-
99ae8af...snip...ec0f262ac
|
1180
|
-
```
|
1181
|
-
|
1182
1202
|
**Session Secret Environment Variable**
|
1183
1203
|
|
1184
1204
|
Set a `SESSION_SECRET` environment variable for Sinatra to the value you
|
@@ -1193,14 +1213,10 @@ purposes only:
|
|
1193
1213
|
**Session Secret App Config**
|
1194
1214
|
|
1195
1215
|
Set up your app config to fail-safe to a secure random secret
|
1196
|
-
if the `SESSION_SECRET` environment variable is not available
|
1197
|
-
|
1198
|
-
For bonus points use the [sysrandom
|
1199
|
-
gem](https://github.com/cryptosphere/sysrandom#readme) here as well:
|
1216
|
+
if the `SESSION_SECRET` environment variable is not available:
|
1200
1217
|
|
1201
1218
|
```ruby
|
1202
1219
|
require 'securerandom'
|
1203
|
-
# -or- require 'sysrandom/securerandom'
|
1204
1220
|
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
|
1205
1221
|
```
|
1206
1222
|
|
@@ -1405,53 +1421,9 @@ to `stream` finishes executing. Streaming does not work at all with Shotgun.
|
|
1405
1421
|
|
1406
1422
|
If the optional parameter is set to `keep_open`, it will not call `close` on
|
1407
1423
|
the stream object, allowing you to close it at any later point in the
|
1408
|
-
execution flow.
|
1409
|
-
Other servers will still close the stream:
|
1410
|
-
|
1411
|
-
```ruby
|
1412
|
-
# config.ru
|
1413
|
-
require 'sinatra/base'
|
1414
|
-
|
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
|
1425
|
-
end
|
1426
|
-
|
1427
|
-
post '/' do
|
1428
|
-
connections.each do |out|
|
1429
|
-
# notify client that a new message has arrived
|
1430
|
-
out << "data: #{params[:msg]}\n\n"
|
1424
|
+
execution flow.
|
1431
1425
|
|
1432
|
-
|
1433
|
-
out.close
|
1434
|
-
end
|
1435
|
-
|
1436
|
-
204 # response without entity body
|
1437
|
-
end
|
1438
|
-
end
|
1439
|
-
|
1440
|
-
run App
|
1441
|
-
```
|
1442
|
-
|
1443
|
-
```ruby
|
1444
|
-
# rainbows.conf
|
1445
|
-
Rainbows! do
|
1446
|
-
use :EventMachine
|
1447
|
-
end
|
1448
|
-
````
|
1449
|
-
|
1450
|
-
Run:
|
1451
|
-
|
1452
|
-
```shell
|
1453
|
-
rainbows -c rainbows.conf
|
1454
|
-
```
|
1426
|
+
You can have a look at the [chat example](https://github.com/sinatra/sinatra/blob/main/examples/chat.rb)
|
1455
1427
|
|
1456
1428
|
It's also possible for the client to close the connection when trying to
|
1457
1429
|
write to the socket. Because of this, it's recommended to check
|
@@ -2089,9 +2061,13 @@ set :protection, :session => true
|
|
2089
2061
|
|
2090
2062
|
<dt>raise_errors</dt>
|
2091
2063
|
<dd>
|
2092
|
-
Raise
|
2064
|
+
Raise unhandled errors (will stop application). Enabled by default when
|
2093
2065
|
<tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
|
2094
2066
|
</dd>
|
2067
|
+
<dd>
|
2068
|
+
Any explicitly defined error handlers always override this setting. See
|
2069
|
+
the "Error" section below.
|
2070
|
+
</dd>
|
2095
2071
|
|
2096
2072
|
<dt>run</dt>
|
2097
2073
|
<dd>
|
@@ -2184,6 +2160,24 @@ set :protection, :session => true
|
|
2184
2160
|
</dd>
|
2185
2161
|
</dl>
|
2186
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
|
+
|
2187
2181
|
## Environments
|
2188
2182
|
|
2189
2183
|
There are three predefined `environments`: `"development"`,
|
@@ -2240,6 +2234,14 @@ show exceptions option to `:after_handler`:
|
|
2240
2234
|
set :show_exceptions, :after_handler
|
2241
2235
|
```
|
2242
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
|
+
|
2243
2245
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2244
2246
|
|
2245
2247
|
```ruby
|
@@ -2248,7 +2250,7 @@ error do
|
|
2248
2250
|
end
|
2249
2251
|
```
|
2250
2252
|
|
2251
|
-
|
2253
|
+
Pass an error class as an argument to create handlers for custom errors:
|
2252
2254
|
|
2253
2255
|
```ruby
|
2254
2256
|
error MyCustomError do
|
@@ -2294,6 +2296,51 @@ Sinatra installs special `not_found` and `error` handlers when
|
|
2294
2296
|
running under the development environment to display nice stack traces
|
2295
2297
|
and additional debugging information in your browser.
|
2296
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
|
+
|
2297
2344
|
## Rack Middleware
|
2298
2345
|
|
2299
2346
|
Sinatra rides on [Rack](https://rack.github.io/), a minimal standard
|
@@ -2767,39 +2814,7 @@ by Konstantin_
|
|
2767
2814
|
Sinatra doesn't impose any concurrency model but leaves that to the
|
2768
2815
|
underlying Rack handler (server) like Puma or WEBrick. Sinatra
|
2769
2816
|
itself is thread-safe, so there won't be any problem if the Rack handler
|
2770
|
-
uses a threaded model of concurrency.
|
2771
|
-
the server, you'd have to specify the correct invocation method for the
|
2772
|
-
specific Rack handler. The following example is a demonstration of how
|
2773
|
-
to start a multi-threaded Rainbows server:
|
2774
|
-
|
2775
|
-
```ruby
|
2776
|
-
# config.ru
|
2777
|
-
|
2778
|
-
require 'sinatra/base'
|
2779
|
-
|
2780
|
-
class App < Sinatra::Base
|
2781
|
-
get '/' do
|
2782
|
-
"Hello, World"
|
2783
|
-
end
|
2784
|
-
end
|
2785
|
-
|
2786
|
-
run App
|
2787
|
-
```
|
2788
|
-
|
2789
|
-
```ruby
|
2790
|
-
# rainbows.conf
|
2791
|
-
|
2792
|
-
# Rainbows configurator is based on Unicorn.
|
2793
|
-
Rainbows! do
|
2794
|
-
use :ThreadSpawn
|
2795
|
-
end
|
2796
|
-
```
|
2797
|
-
|
2798
|
-
To start the server, the command would be:
|
2799
|
-
|
2800
|
-
```shell
|
2801
|
-
rainbows -c rainbows.conf
|
2802
|
-
```
|
2817
|
+
uses a threaded model of concurrency.
|
2803
2818
|
|
2804
2819
|
## Requirement
|
2805
2820
|
|
data/Rakefile
CHANGED
@@ -191,7 +191,7 @@ if defined?(Gem)
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
|
-
desc 'Commits the version to
|
194
|
+
desc 'Commits the version to git (no push)'
|
195
195
|
task :commit_version do
|
196
196
|
%w[
|
197
197
|
lib/sinatra
|
@@ -203,10 +203,22 @@ if defined?(Gem)
|
|
203
203
|
end
|
204
204
|
|
205
205
|
sh <<-SH
|
206
|
-
git commit --allow-empty
|
207
|
-
|
208
|
-
|
209
|
-
|
206
|
+
git commit --allow-empty --all --message '#{source_version} release'
|
207
|
+
SH
|
208
|
+
end
|
209
|
+
|
210
|
+
desc 'Tags the version in git (no push)'
|
211
|
+
task :tag_version do
|
212
|
+
sh <<-SH
|
213
|
+
git tag --sign v#{source_version} --message '#{source_version} release'
|
214
|
+
SH
|
215
|
+
end
|
216
|
+
|
217
|
+
desc 'Watch the release workflow run'
|
218
|
+
task :watch do
|
219
|
+
sh <<-SH
|
220
|
+
runId=$(gh run list --workflow=release.yml --limit 1 --json databaseId --jq '.[].databaseId')
|
221
|
+
gh run watch --interval 1 --exit-status $runId
|
210
222
|
SH
|
211
223
|
end
|
212
224
|
|
data/SECURITY.md
CHANGED
@@ -6,7 +6,7 @@ After the initial reply to your report the security team will endeavor to keep y
|
|
6
6
|
|
7
7
|
If you have not received a reply to your email within 48 hours, or have not heard from the security team for the past five days there are a few steps you can take:
|
8
8
|
|
9
|
-
*
|
9
|
+
* Reach out to us on [discord](https://discord.gg/ncjsfsNHh7)
|
10
10
|
|
11
11
|
## Disclosure Policy
|
12
12
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0
|
1
|
+
3.2.0
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby -I ../lib -I lib
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'sinatra'
|
5
|
+
|
6
|
+
get('/') do
|
7
|
+
'This shows how lifecycle events work'
|
8
|
+
end
|
9
|
+
|
10
|
+
on_start do
|
11
|
+
puts "=============="
|
12
|
+
puts " Booting up"
|
13
|
+
puts "=============="
|
14
|
+
end
|
15
|
+
|
16
|
+
on_stop do
|
17
|
+
puts "================="
|
18
|
+
puts " Shutting down"
|
19
|
+
puts "================="
|
20
|
+
end
|
data/examples/stream.ru
CHANGED
@@ -4,10 +4,8 @@
|
|
4
4
|
#
|
5
5
|
# run *one* of these:
|
6
6
|
#
|
7
|
-
# rackup -s mongrel stream.ru # gem install mongrel
|
8
7
|
# unicorn stream.ru # gem install unicorn
|
9
8
|
# puma stream.ru # gem install puma
|
10
|
-
# rainbows -c rainbows.conf stream.ru # gem install rainbows eventmachine
|
11
9
|
|
12
10
|
require 'sinatra/base'
|
13
11
|
|
data/lib/sinatra/base.rb
CHANGED
@@ -209,7 +209,7 @@ module Sinatra
|
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
|
-
# Some Rack handlers
|
212
|
+
# Some Rack handlers implement an extended body object protocol, however,
|
213
213
|
# some middleware (namely Rack::Lint) will break it by not mirroring the methods in question.
|
214
214
|
# This middleware will detect an extended body object and will make sure it reaches the
|
215
215
|
# handler directly. We do this here, so our middleware and middleware set up by the app will
|
@@ -502,8 +502,7 @@ module Sinatra
|
|
502
502
|
# the response body have not yet been generated.
|
503
503
|
#
|
504
504
|
# The close parameter specifies whether Stream#close should be called
|
505
|
-
# after the block has been executed.
|
506
|
-
# servers like Rainbows.
|
505
|
+
# after the block has been executed.
|
507
506
|
def stream(keep_open = false)
|
508
507
|
scheduler = env['async.callback'] ? EventMachine : Stream
|
509
508
|
current = @params.dup
|
@@ -726,7 +725,7 @@ module Sinatra
|
|
726
725
|
# Possible options are:
|
727
726
|
# :content_type The content type to use, same arguments as content_type.
|
728
727
|
# :layout If set to something falsy, no layout is rendered, otherwise
|
729
|
-
# the specified layout is used
|
728
|
+
# the specified layout is used (Ignored for `sass`)
|
730
729
|
# :layout_engine Engine to use for rendering the layout.
|
731
730
|
# :locals A hash with local variables that should be available
|
732
731
|
# in the template
|
@@ -752,6 +751,20 @@ module Sinatra
|
|
752
751
|
render(:haml, template, options, locals, &block)
|
753
752
|
end
|
754
753
|
|
754
|
+
def sass(template, options = {}, locals = {})
|
755
|
+
options[:default_content_type] = :css
|
756
|
+
options[:exclude_outvar] = true
|
757
|
+
options[:layout] = nil
|
758
|
+
render :sass, template, options, locals
|
759
|
+
end
|
760
|
+
|
761
|
+
def scss(template, options = {}, locals = {})
|
762
|
+
options[:default_content_type] = :css
|
763
|
+
options[:exclude_outvar] = true
|
764
|
+
options[:layout] = nil
|
765
|
+
render :scss, template, options, locals
|
766
|
+
end
|
767
|
+
|
755
768
|
def builder(template = nil, options = {}, locals = {}, &block)
|
756
769
|
options[:default_content_type] = :xml
|
757
770
|
render_ruby(:builder, template, options, locals, &block)
|
@@ -862,7 +875,11 @@ module Sinatra
|
|
862
875
|
catch(:layout_missing) { return render(layout_engine, layout, options, locals) { output } }
|
863
876
|
end
|
864
877
|
|
865
|
-
|
878
|
+
if content_type
|
879
|
+
# sass-embedded returns a frozen string
|
880
|
+
output = +output
|
881
|
+
output.extend(ContentTyped).content_type = content_type
|
882
|
+
end
|
866
883
|
output
|
867
884
|
end
|
868
885
|
|
@@ -914,6 +931,35 @@ module Sinatra
|
|
914
931
|
end
|
915
932
|
end
|
916
933
|
|
934
|
+
# Extremely simple template cache implementation.
|
935
|
+
# * Not thread-safe.
|
936
|
+
# * Size is unbounded.
|
937
|
+
# * Keys are not copied defensively, and should not be modified after
|
938
|
+
# being passed to #fetch. More specifically, the values returned by
|
939
|
+
# key#hash and key#eql? should not change.
|
940
|
+
#
|
941
|
+
# Implementation copied from Tilt::Cache.
|
942
|
+
class TemplateCache
|
943
|
+
def initialize
|
944
|
+
@cache = {}
|
945
|
+
end
|
946
|
+
|
947
|
+
# Caches a value for key, or returns the previously cached value.
|
948
|
+
# If a value has been previously cached for key then it is
|
949
|
+
# returned. Otherwise, block is yielded to and its return value
|
950
|
+
# which may be nil, is cached under key and returned.
|
951
|
+
def fetch(*key)
|
952
|
+
@cache.fetch(key) do
|
953
|
+
@cache[key] = yield
|
954
|
+
end
|
955
|
+
end
|
956
|
+
|
957
|
+
# Clears the cache.
|
958
|
+
def clear
|
959
|
+
@cache = {}
|
960
|
+
end
|
961
|
+
end
|
962
|
+
|
917
963
|
# Base class for all Sinatra applications and middleware.
|
918
964
|
class Base
|
919
965
|
include Rack::Utils
|
@@ -928,7 +974,7 @@ module Sinatra
|
|
928
974
|
def initialize(app = nil, **_kwargs)
|
929
975
|
super()
|
930
976
|
@app = app
|
931
|
-
@template_cache =
|
977
|
+
@template_cache = TemplateCache.new
|
932
978
|
@pinned_response = nil # whether a before! filter pinned the content-type
|
933
979
|
yield self if block_given?
|
934
980
|
end
|
@@ -1214,7 +1260,19 @@ module Sinatra
|
|
1214
1260
|
end
|
1215
1261
|
|
1216
1262
|
def dump_errors!(boom)
|
1217
|
-
|
1263
|
+
if boom.respond_to?(:detailed_message)
|
1264
|
+
msg = boom.detailed_message(highlight: false)
|
1265
|
+
if msg =~ /\A(.*?)(?: \(#{ Regexp.quote(boom.class.to_s) }\))?\n/
|
1266
|
+
msg = $1
|
1267
|
+
additional_msg = $'.lines(chomp: true)
|
1268
|
+
else
|
1269
|
+
additional_msg = []
|
1270
|
+
end
|
1271
|
+
else
|
1272
|
+
msg = boom.message
|
1273
|
+
additional_msg = []
|
1274
|
+
end
|
1275
|
+
msg = ["#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - #{boom.class} - #{msg}:", *additional_msg, *boom.backtrace].join("\n\t")
|
1218
1276
|
@env['rack.errors'].puts(msg)
|
1219
1277
|
end
|
1220
1278
|
|
@@ -1223,6 +1281,7 @@ module Sinatra
|
|
1223
1281
|
%r{/sinatra(/(base|main|show_exceptions))?\.rb$}, # all sinatra code
|
1224
1282
|
%r{lib/tilt.*\.rb$}, # all tilt code
|
1225
1283
|
/^\(.*\)$/, # generated code
|
1284
|
+
/\/bundled_gems.rb$/, # ruby >= 3.3 with bundler >= 2.5
|
1226
1285
|
%r{rubygems/(custom|core_ext/kernel)_require\.rb$}, # rubygems require hacks
|
1227
1286
|
/active_support/, # active_support require hacks
|
1228
1287
|
%r{bundler(/(?:runtime|inline))?\.rb}, # bundler require hacks
|
@@ -1230,7 +1289,7 @@ module Sinatra
|
|
1230
1289
|
%r{zeitwerk/kernel\.rb} # Zeitwerk kernel#require decorator
|
1231
1290
|
].freeze
|
1232
1291
|
|
1233
|
-
attr_reader :routes, :filters, :templates, :errors
|
1292
|
+
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
|
1234
1293
|
|
1235
1294
|
def callers_to_ignore
|
1236
1295
|
CALLERS_TO_IGNORE
|
@@ -1423,6 +1482,14 @@ module Sinatra
|
|
1423
1482
|
filters[type] << compile!(type, path, block, **options)
|
1424
1483
|
end
|
1425
1484
|
|
1485
|
+
def on_start(&on_start_callback)
|
1486
|
+
@on_start_callback = on_start_callback
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
def on_stop(&on_stop_callback)
|
1490
|
+
@on_stop_callback = on_stop_callback
|
1491
|
+
end
|
1492
|
+
|
1426
1493
|
# Add a route condition. The route is considered non-matching when the
|
1427
1494
|
# block returns false.
|
1428
1495
|
def condition(name = "#{caller.first[/`.*'/]} condition", &block)
|
@@ -1512,12 +1579,14 @@ module Sinatra
|
|
1512
1579
|
warn '== Sinatra has ended his set (crowd applauds)' unless suppress_messages?
|
1513
1580
|
set :running_server, nil
|
1514
1581
|
set :handler_name, nil
|
1582
|
+
|
1583
|
+
on_stop_callback.call unless on_stop_callback.nil?
|
1515
1584
|
end
|
1516
1585
|
|
1517
1586
|
alias stop! quit!
|
1518
1587
|
|
1519
1588
|
# Run the Sinatra app as a self-hosted server using
|
1520
|
-
# Puma, Falcon,
|
1589
|
+
# Puma, Falcon, or WEBrick (in that order). If given a block, will call
|
1521
1590
|
# with the constructed handler once we have taken the stage.
|
1522
1591
|
def run!(options = {}, &block)
|
1523
1592
|
return if running?
|
@@ -1599,7 +1668,7 @@ module Sinatra
|
|
1599
1668
|
set :running_server, server
|
1600
1669
|
set :handler_name, handler_name
|
1601
1670
|
server.threaded = settings.threaded if server.respond_to? :threaded=
|
1602
|
-
|
1671
|
+
on_start_callback.call unless on_start_callback.nil?
|
1603
1672
|
yield server if block_given?
|
1604
1673
|
end
|
1605
1674
|
end
|
@@ -1870,11 +1939,10 @@ module Sinatra
|
|
1870
1939
|
|
1871
1940
|
ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1872
1941
|
|
1873
|
-
server.unshift 'puma'
|
1874
|
-
server.unshift 'falcon' if ruby_engine != 'jruby'
|
1875
|
-
server.unshift 'mongrel' if ruby_engine.nil?
|
1876
1942
|
server.unshift 'thin' if ruby_engine != 'jruby'
|
1943
|
+
server.unshift 'falcon' if ruby_engine != 'jruby'
|
1877
1944
|
server.unshift 'trinidad' if ruby_engine == 'jruby'
|
1945
|
+
server.unshift 'puma'
|
1878
1946
|
|
1879
1947
|
set :absolute_redirects, true
|
1880
1948
|
set :prefixed_redirects, false
|
@@ -1939,7 +2007,7 @@ module Sinatra
|
|
1939
2007
|
</head>
|
1940
2008
|
<body>
|
1941
2009
|
<h2>Sinatra doesn’t know this ditty.</h2>
|
1942
|
-
<img src='#{
|
2010
|
+
<img src='#{request.script_name}/__sinatra__/404.png'>
|
1943
2011
|
<div id="c">
|
1944
2012
|
Try this:
|
1945
2013
|
<pre>#{Rack::Utils.escape_html(code)}</pre>
|
@@ -1991,7 +2059,7 @@ module Sinatra
|
|
1991
2059
|
delegate :get, :patch, :put, :post, :delete, :head, :options, :link, :unlink,
|
1992
2060
|
:template, :layout, :before, :after, :error, :not_found, :configure,
|
1993
2061
|
:set, :mime_type, :enable, :disable, :use, :development?, :test?,
|
1994
|
-
:production?, :helpers, :settings, :register
|
2062
|
+
:production?, :helpers, :settings, :register, :on_start, :on_stop
|
1995
2063
|
|
1996
2064
|
class << self
|
1997
2065
|
attr_accessor :target
|
@@ -21,7 +21,8 @@ module Sinatra
|
|
21
21
|
# writing interface (calling e.g. <tt>[]=</tt>, <tt>merge</tt>). This mapping
|
22
22
|
# belongs to the public interface. For example, given:
|
23
23
|
#
|
24
|
-
# hash = Sinatra::IndifferentHash.new
|
24
|
+
# hash = Sinatra::IndifferentHash.new
|
25
|
+
# hash[:a] = 1
|
25
26
|
#
|
26
27
|
# You are guaranteed that the key is returned as a string:
|
27
28
|
#
|
@@ -29,7 +30,8 @@ module Sinatra
|
|
29
30
|
#
|
30
31
|
# Technically other types of keys are accepted:
|
31
32
|
#
|
32
|
-
# hash = Sinatra::IndifferentHash
|
33
|
+
# hash = Sinatra::IndifferentHash
|
34
|
+
# hash[:a] = 1
|
33
35
|
# hash[0] = 0
|
34
36
|
# hash # => { "a"=>1, 0=>0 }
|
35
37
|
#
|
@@ -186,6 +188,12 @@ module Sinatra
|
|
186
188
|
dup.tap(&:compact!)
|
187
189
|
end
|
188
190
|
|
191
|
+
def except(*keys)
|
192
|
+
keys.map!(&method(:convert_key))
|
193
|
+
|
194
|
+
super(*keys)
|
195
|
+
end if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0")
|
196
|
+
|
189
197
|
private
|
190
198
|
|
191
199
|
def convert_key(key)
|
data/lib/sinatra/version.rb
CHANGED
data/sinatra.gemspec
CHANGED
@@ -49,6 +49,4 @@ RubyGems 2.0 or newer is required to protect against public gem pushes. You can
|
|
49
49
|
s.add_dependency 'rack', '~> 2.2', '>= 2.2.4'
|
50
50
|
s.add_dependency 'rack-protection', version
|
51
51
|
s.add_dependency 'tilt', '~> 2.0'
|
52
|
-
|
53
|
-
s.add_development_dependency 'rack-test', '~> 2'
|
54
52
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Mizerany
|
8
8
|
- Ryan Tomayko
|
9
9
|
- Simon Rozet
|
10
10
|
- Konstantin Haase
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-12-29 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: mustermann
|
@@ -53,14 +53,14 @@ dependencies:
|
|
53
53
|
requirements:
|
54
54
|
- - '='
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 3.0
|
56
|
+
version: 3.2.0
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
61
|
- - '='
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 3.0
|
63
|
+
version: 3.2.0
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: tilt
|
66
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,20 +75,6 @@ dependencies:
|
|
75
75
|
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '2.0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: rack-test
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
requirements:
|
82
|
-
- - "~>"
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
version: '2'
|
85
|
-
type: :development
|
86
|
-
prerelease: false
|
87
|
-
version_requirements: !ruby/object:Gem::Requirement
|
88
|
-
requirements:
|
89
|
-
- - "~>"
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
version: '2'
|
92
78
|
description: Sinatra is a DSL for quickly creating web applications in Ruby with minimal
|
93
79
|
effort.
|
94
80
|
email: sinatrarb@googlegroups.com
|
@@ -110,8 +96,7 @@ files:
|
|
110
96
|
- SECURITY.md
|
111
97
|
- VERSION
|
112
98
|
- examples/chat.rb
|
113
|
-
- examples/
|
114
|
-
- examples/rainbows.rb
|
99
|
+
- examples/lifecycle_events.rb
|
115
100
|
- examples/simple.rb
|
116
101
|
- examples/stream.ru
|
117
102
|
- lib/sinatra.rb
|
@@ -133,7 +118,7 @@ metadata:
|
|
133
118
|
bug_tracker_uri: https://github.com/sinatra/sinatra/issues
|
134
119
|
mailing_list_uri: http://groups.google.com/group/sinatrarb
|
135
120
|
documentation_uri: https://www.rubydoc.info/gems/sinatra
|
136
|
-
post_install_message:
|
121
|
+
post_install_message:
|
137
122
|
rdoc_options:
|
138
123
|
- "--line-numbers"
|
139
124
|
- "--title"
|
@@ -154,8 +139,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
139
|
- !ruby/object:Gem::Version
|
155
140
|
version: '0'
|
156
141
|
requirements: []
|
157
|
-
rubygems_version: 3.
|
158
|
-
signing_key:
|
142
|
+
rubygems_version: 3.5.3
|
143
|
+
signing_key:
|
159
144
|
specification_version: 4
|
160
145
|
summary: Classy web-development dressed in a DSL
|
161
146
|
test_files: []
|
data/examples/rainbows.conf
DELETED
data/examples/rainbows.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rainbows'
|
4
|
-
|
5
|
-
module Rack
|
6
|
-
module Handler
|
7
|
-
class Rainbows
|
8
|
-
def self.run(app, **options)
|
9
|
-
rainbows_options = {
|
10
|
-
listeners: ["#{options[:Host]}:#{options[:Port]}"],
|
11
|
-
worker_processes: 1,
|
12
|
-
timeout: 30,
|
13
|
-
config_file: ::File.expand_path('rainbows.conf', __dir__)
|
14
|
-
}
|
15
|
-
|
16
|
-
::Rainbows::HttpServer.new(app, rainbows_options).start.join
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
register :rainbows, ::Rack::Handler::Rainbows
|
21
|
-
end
|
22
|
-
end
|