sinatra 3.0.6 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/AUTHORS.md +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
|