sinatra 3.0.4 → 3.1.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/CHANGELOG.md +40 -0
- data/CONTRIBUTING.md +11 -11
- data/Gemfile +10 -3
- data/MAINTENANCE.md +2 -2
- data/README.md +126 -16
- data/Rakefile +8 -17
- data/VERSION +1 -1
- data/examples/chat.rb +20 -9
- data/examples/lifecycle_events.rb +20 -0
- data/examples/stream.ru +0 -1
- data/lib/sinatra/base.rb +93 -21
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 315dee3d85d7778ffa48e041bd60370e9e89ecd3c01dbf0cf9450e41c62dc0d8
|
4
|
+
data.tar.gz: '083a914c0b520684471e2715ec091c67ca8121bfb8b5d4cf410307d6e14e4ac5'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2790a4d58595f0f89667c5fd4530dde2de532ddaf02628f373162cc47d393732b1c9475ab59775c756750dfb52e60e7091118936ac8e70739fb266b46f82d3bd
|
7
|
+
data.tar.gz: eb74f34bf0b9a681557809c656754312eb266e66c3b68fcabbf95699c3273cf4d998e3969224b09df9127ff90f5d34fba5bc93b1ff0c321b4a7646ddfcc0b6b7
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,40 @@
|
|
2
2
|
|
3
3
|
* _Your new feature here._
|
4
4
|
|
5
|
+
## 3.1.0 / 2023-08-07
|
6
|
+
|
7
|
+
* New: Add sass support via sass-embedded [#1911] by なつき
|
8
|
+
|
9
|
+
* New: Add start and stop callbacks [#1913] by Jevin Sew
|
10
|
+
|
11
|
+
* New: Warn on dropping sessions [#1900] by Jonathan del Strother
|
12
|
+
|
13
|
+
* New: Make Puma the default server [#1924] by Patrik Ragnarsson
|
14
|
+
|
15
|
+
* Fix: Remove use of Tilt::Cache [#1922] by Jeremy Evans (allows use of Tilt 2.2.0 without deprecation warning)
|
16
|
+
|
17
|
+
* Fix: rack-protection: specify rack version requirement [#1932] by Patrik Ragnarsson
|
18
|
+
|
19
|
+
[#1913]: https://github.com/sinatra/sinatra/pull/1913
|
20
|
+
[#1900]: https://github.com/sinatra/sinatra/pull/1900
|
21
|
+
[#1924]: https://github.com/sinatra/sinatra/pull/1924
|
22
|
+
[#1922]: https://github.com/sinatra/sinatra/pull/1922
|
23
|
+
[#1932]: https://github.com/sinatra/sinatra/pull/1932
|
24
|
+
|
25
|
+
## 3.0.6 / 2023-04-11
|
26
|
+
|
27
|
+
* Fix: Add support to keep open streaming connections with Puma [#1858](https://github.com/sinatra/sinatra/pull/1858) by Jordan Owens
|
28
|
+
|
29
|
+
* Fix: Avoid crash in `uri` helper on Integer input [#1890](https://github.com/sinatra/sinatra/pull/1890) by Patrik Ragnarsson
|
30
|
+
|
31
|
+
* Fix: Rescue `RuntimeError` when trying to use `SecureRandom` [#1888](https://github.com/sinatra/sinatra/pull/1888) by Stefan Sundin
|
32
|
+
|
33
|
+
## 3.0.5 / 2022-12-16
|
34
|
+
|
35
|
+
* Fix: Add Zeitwerk compatibility. [#1831](https://github.com/sinatra/sinatra/pull/1831) by Dawid Janczak
|
36
|
+
|
37
|
+
* Fix: Allow CALLERS_TO_IGNORE to be overridden
|
38
|
+
|
5
39
|
## 3.0.4 / 2022-11-25
|
6
40
|
|
7
41
|
* Fix: Escape filename in the Content-Disposition header. [#1841](https://github.com/sinatra/sinatra/pull/1841) by Kunpei Sakai
|
@@ -66,6 +100,12 @@
|
|
66
100
|
|
67
101
|
* Docs: Japanese documentation: Make Session section reflect changes done to README.md. [#1731](https://github.com/sinatra/sinatra/pull/1731) by @shu-i-chi
|
68
102
|
|
103
|
+
## 2.2.3 / 2022-11-25
|
104
|
+
|
105
|
+
* Fix: Escape filename in the Content-Disposition header. [#1841](https://github.com/sinatra/sinatra/pull/1841) by Kunpei Sakai
|
106
|
+
|
107
|
+
* Fix: fixed ReDoS for Rack::Protection::IPSpoofing. [#1823](https://github.com/sinatra/sinatra/pull/1823) by @ooooooo-q
|
108
|
+
|
69
109
|
## 2.2.2 / 2022-07-23
|
70
110
|
|
71
111
|
* Update mustermann dependency to version 2.
|
data/CONTRIBUTING.md
CHANGED
@@ -65,21 +65,21 @@ track patch requests.
|
|
65
65
|
also has its own [Git repository](http://github.com/sinatra/sinatra-recipes).
|
66
66
|
|
67
67
|
* [The Introduction](http://www.sinatrarb.com/intro.html) is generated from
|
68
|
-
Sinatra's [README file](http://github.com/sinatra/sinatra/blob/
|
68
|
+
Sinatra's [README file](http://github.com/sinatra/sinatra/blob/main/README.md).
|
69
69
|
|
70
70
|
* If you want to help translating the documentation, the README is already
|
71
71
|
available in
|
72
|
-
[Japanese](http://github.com/sinatra/sinatra/blob/
|
73
|
-
[German](http://github.com/sinatra/sinatra/blob/
|
74
|
-
[Chinese](https://github.com/sinatra/sinatra/blob/
|
75
|
-
[Russian](https://github.com/sinatra/sinatra/blob/
|
76
|
-
[European](https://github.com/sinatra/sinatra/blob/
|
77
|
-
[Brazilian](https://github.com/sinatra/sinatra/blob/
|
72
|
+
[Japanese](http://github.com/sinatra/sinatra/blob/main/README.ja.md),
|
73
|
+
[German](http://github.com/sinatra/sinatra/blob/main/README.de.md),
|
74
|
+
[Chinese](https://github.com/sinatra/sinatra/blob/main/README.zh.md),
|
75
|
+
[Russian](https://github.com/sinatra/sinatra/blob/main/README.ru.md),
|
76
|
+
[European](https://github.com/sinatra/sinatra/blob/main/README.pt-pt.md) and
|
77
|
+
[Brazilian](https://github.com/sinatra/sinatra/blob/main/README.pt-br.md)
|
78
78
|
Portuguese,
|
79
|
-
[French](https://github.com/sinatra/sinatra/blob/
|
80
|
-
[Spanish](https://github.com/sinatra/sinatra/blob/
|
81
|
-
[Korean](https://github.com/sinatra/sinatra/blob/
|
82
|
-
[Hungarian](https://github.com/sinatra/sinatra/blob/
|
79
|
+
[French](https://github.com/sinatra/sinatra/blob/main/README.fr.md),
|
80
|
+
[Spanish](https://github.com/sinatra/sinatra/blob/main/README.es.md),
|
81
|
+
[Korean](https://github.com/sinatra/sinatra/blob/main/README.ko.md), and
|
82
|
+
[Hungarian](https://github.com/sinatra/sinatra/blob/main/README.hu.md).
|
83
83
|
The translations tend to fall behind the English version. Translations into
|
84
84
|
other languages would also be appreciated.
|
85
85
|
|
data/Gemfile
CHANGED
@@ -15,12 +15,12 @@ gem 'rake'
|
|
15
15
|
|
16
16
|
rack_version = ENV['rack'].to_s
|
17
17
|
rack_version = nil if rack_version.empty? || (rack_version == 'stable')
|
18
|
-
rack_version = { github: 'rack/rack' } if rack_version == '
|
18
|
+
rack_version = { github: 'rack/rack' } if rack_version == 'head'
|
19
19
|
gem 'rack', rack_version
|
20
20
|
|
21
21
|
puma_version = ENV['puma'].to_s
|
22
22
|
puma_version = nil if puma_version.empty? || (puma_version == 'stable')
|
23
|
-
puma_version = { github: 'puma/puma' } if puma_version == '
|
23
|
+
puma_version = { github: 'puma/puma' } if puma_version == 'head'
|
24
24
|
gem 'puma', puma_version
|
25
25
|
|
26
26
|
gem 'minitest', '~> 5.0'
|
@@ -31,6 +31,12 @@ gem 'yard'
|
|
31
31
|
gem 'rack-protection', path: 'rack-protection'
|
32
32
|
gem 'sinatra-contrib', path: 'sinatra-contrib'
|
33
33
|
|
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'
|
39
|
+
|
34
40
|
gem 'activesupport', '~> 6.1'
|
35
41
|
|
36
42
|
gem 'asciidoctor'
|
@@ -39,7 +45,7 @@ gem 'commonmarker', '~> 0.23.4', platforms: [:ruby]
|
|
39
45
|
gem 'erubi'
|
40
46
|
gem 'eventmachine'
|
41
47
|
gem 'falcon', '~> 0.40', platforms: [:ruby]
|
42
|
-
gem 'haml', '~>
|
48
|
+
gem 'haml', '~> 6'
|
43
49
|
gem 'kramdown'
|
44
50
|
gem 'liquid'
|
45
51
|
gem 'markaby'
|
@@ -50,6 +56,7 @@ gem 'rainbows', platforms: [:mri] # uses #fork
|
|
50
56
|
gem 'rdiscount', platforms: [:ruby]
|
51
57
|
gem 'rdoc'
|
52
58
|
gem 'redcarpet', platforms: [:ruby]
|
59
|
+
gem 'sass-embedded', '~> 1.54'
|
53
60
|
gem 'simplecov', require: false
|
54
61
|
gem 'slim', '~> 4'
|
55
62
|
gem 'yajl-ruby', platforms: [:ruby]
|
data/MAINTENANCE.md
CHANGED
@@ -4,13 +4,13 @@
|
|
4
4
|
|
5
5
|
### Releases
|
6
6
|
|
7
|
-
The next major version of Sinatra will be released from the
|
7
|
+
The next major version of Sinatra will be released from the main branch. Each version will be tagged so it will be possible to branch of should there be a need for bug fixes and other updates.
|
8
8
|
|
9
9
|
## Issues
|
10
10
|
|
11
11
|
### New features
|
12
12
|
|
13
|
-
New features will only be added to the
|
13
|
+
New features will only be added to the main branch and will not be made available in point releases.
|
14
14
|
|
15
15
|
### Bug fixes
|
16
16
|
|
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
|
|
@@ -984,7 +1020,7 @@ To associate a file extension with a template engine, use
|
|
984
1020
|
`tt` for Haml templates, you can do the following:
|
985
1021
|
|
986
1022
|
```ruby
|
987
|
-
Tilt.register
|
1023
|
+
Tilt.register Tilt[:haml], :tt
|
988
1024
|
```
|
989
1025
|
|
990
1026
|
### Adding Your Own Template Engine
|
@@ -992,7 +1028,7 @@ Tilt.register :tt, Tilt[:haml]
|
|
992
1028
|
First, register your engine with Tilt, then create a rendering method:
|
993
1029
|
|
994
1030
|
```ruby
|
995
|
-
Tilt.register :myat
|
1031
|
+
Tilt.register MyAwesomeTemplateEngine, :myat
|
996
1032
|
|
997
1033
|
helpers do
|
998
1034
|
def myat(*args) render(:myat, *args) end
|
@@ -1933,7 +1969,7 @@ end
|
|
1933
1969
|
### Configuring attack protection
|
1934
1970
|
|
1935
1971
|
Sinatra is using
|
1936
|
-
[Rack::Protection](https://github.com/sinatra/sinatra/tree/
|
1972
|
+
[Rack::Protection](https://github.com/sinatra/sinatra/tree/main/rack-protection#readme) to
|
1937
1973
|
defend your application against common, opportunistic attacks. You can
|
1938
1974
|
easily disable this behavior (which will open up your application to tons
|
1939
1975
|
of common vulnerabilities):
|
@@ -2089,9 +2125,13 @@ set :protection, :session => true
|
|
2089
2125
|
|
2090
2126
|
<dt>raise_errors</dt>
|
2091
2127
|
<dd>
|
2092
|
-
Raise
|
2128
|
+
Raise unhandled errors (will stop application). Enabled by default when
|
2093
2129
|
<tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
|
2094
2130
|
</dd>
|
2131
|
+
<dd>
|
2132
|
+
Any explicitly defined error handlers always override this setting. See
|
2133
|
+
the "Error" section below.
|
2134
|
+
</dd>
|
2095
2135
|
|
2096
2136
|
<dt>run</dt>
|
2097
2137
|
<dd>
|
@@ -2184,6 +2224,24 @@ set :protection, :session => true
|
|
2184
2224
|
</dd>
|
2185
2225
|
</dl>
|
2186
2226
|
|
2227
|
+
## Lifecycle Events
|
2228
|
+
|
2229
|
+
There are 2 lifecycle events currently exposed by Sinatra. One when the server starts and one when it stops.
|
2230
|
+
|
2231
|
+
They can be used like this:
|
2232
|
+
|
2233
|
+
```ruby
|
2234
|
+
on_start do
|
2235
|
+
puts "===== Booting up ====="
|
2236
|
+
end
|
2237
|
+
|
2238
|
+
on_stop do
|
2239
|
+
puts "===== Shutting down ====="
|
2240
|
+
end
|
2241
|
+
```
|
2242
|
+
|
2243
|
+
Note that these callbacks only work when using Sinatra to start the web server.
|
2244
|
+
|
2187
2245
|
## Environments
|
2188
2246
|
|
2189
2247
|
There are three predefined `environments`: `"development"`,
|
@@ -2240,6 +2298,14 @@ show exceptions option to `:after_handler`:
|
|
2240
2298
|
set :show_exceptions, :after_handler
|
2241
2299
|
```
|
2242
2300
|
|
2301
|
+
A catch-all error handler can be defined with `error` and a block:
|
2302
|
+
|
2303
|
+
```ruby
|
2304
|
+
error do
|
2305
|
+
'Sorry there was a nasty error'
|
2306
|
+
end
|
2307
|
+
```
|
2308
|
+
|
2243
2309
|
The exception object can be obtained from the `sinatra.error` Rack variable:
|
2244
2310
|
|
2245
2311
|
```ruby
|
@@ -2248,7 +2314,7 @@ error do
|
|
2248
2314
|
end
|
2249
2315
|
```
|
2250
2316
|
|
2251
|
-
|
2317
|
+
Pass an error class as an argument to create handlers for custom errors:
|
2252
2318
|
|
2253
2319
|
```ruby
|
2254
2320
|
error MyCustomError do
|
@@ -2294,6 +2360,51 @@ Sinatra installs special `not_found` and `error` handlers when
|
|
2294
2360
|
running under the development environment to display nice stack traces
|
2295
2361
|
and additional debugging information in your browser.
|
2296
2362
|
|
2363
|
+
### Behavior with `raise_errors` option
|
2364
|
+
|
2365
|
+
When `raise_errors` option is `true`, errors that are unhandled are raised
|
2366
|
+
outside of the application. Additionally, any errors that would have been
|
2367
|
+
caught by the catch-all error handler are raised.
|
2368
|
+
|
2369
|
+
For example, consider the following configuration:
|
2370
|
+
|
2371
|
+
```ruby
|
2372
|
+
# First handler
|
2373
|
+
error MyCustomError do
|
2374
|
+
'A custom message'
|
2375
|
+
end
|
2376
|
+
|
2377
|
+
# Second handler
|
2378
|
+
error do
|
2379
|
+
'A catch-all message'
|
2380
|
+
end
|
2381
|
+
```
|
2382
|
+
|
2383
|
+
If `raise_errors` is `false`:
|
2384
|
+
|
2385
|
+
* When `MyCustomError` or descendant is raised, the first handler is invoked.
|
2386
|
+
The HTTP response body will contain `"A custom message"`.
|
2387
|
+
* When any other error is raised, the second handler is invoked. The HTTP
|
2388
|
+
response body will contain `"A catch-all message"`.
|
2389
|
+
|
2390
|
+
If `raise_errors` is `true`:
|
2391
|
+
|
2392
|
+
* When `MyCustomError` or descendant is raised, the behavior is identical to
|
2393
|
+
when `raise_errors` is `false`, described above.
|
2394
|
+
* When any other error is raised, the second handler is *not* invoked, and
|
2395
|
+
the error is raised outside of the application.
|
2396
|
+
* If the environment is `production`, the HTTP response body will contain
|
2397
|
+
a generic error message, e.g. `"An unhandled lowlevel error occurred. The
|
2398
|
+
application logs may have details."`
|
2399
|
+
* If the environment is not `production`, the HTTP response body will contain
|
2400
|
+
the verbose error backtrace.
|
2401
|
+
* Regardless of environment, if `show_exceptions` is set to `:after_handler`,
|
2402
|
+
the HTTP response body will contain the verbose error backtrace.
|
2403
|
+
|
2404
|
+
In the `test` environment, `raise_errors` is set to `true` by default. This
|
2405
|
+
means that in order to write a test for a catch-all error handler,
|
2406
|
+
`raise_errors` must temporarily be set to `false` for that particular test.
|
2407
|
+
|
2297
2408
|
## Rack Middleware
|
2298
2409
|
|
2299
2410
|
Sinatra rides on [Rack](https://rack.github.io/), a minimal standard
|
@@ -2319,7 +2430,7 @@ end
|
|
2319
2430
|
```
|
2320
2431
|
|
2321
2432
|
The semantics of `use` are identical to those defined for the
|
2322
|
-
[Rack::Builder](
|
2433
|
+
[Rack::Builder](https://www.rubydoc.info/github/rack/rack/main/Rack/Builder) DSL
|
2323
2434
|
(most frequently used from rackup files). For example, the `use` method
|
2324
2435
|
accepts multiple/variable args as well as blocks:
|
2325
2436
|
|
@@ -2335,7 +2446,7 @@ many of these components automatically based on configuration so you
|
|
2335
2446
|
typically don't have to `use` them explicitly.
|
2336
2447
|
|
2337
2448
|
You can find useful middleware in
|
2338
|
-
[rack](https://github.com/rack/rack/tree/
|
2449
|
+
[rack](https://github.com/rack/rack/tree/main/lib/rack),
|
2339
2450
|
[rack-contrib](https://github.com/rack/rack-contrib#readme),
|
2340
2451
|
or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
2341
2452
|
|
@@ -2343,7 +2454,7 @@ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
|
|
2343
2454
|
|
2344
2455
|
Sinatra tests can be written using any Rack-based testing library or
|
2345
2456
|
framework.
|
2346
|
-
[Rack::Test](
|
2457
|
+
[Rack::Test](https://www.rubydoc.info/github/rack/rack-test/main/frames)
|
2347
2458
|
is recommended:
|
2348
2459
|
|
2349
2460
|
```ruby
|
@@ -2838,7 +2949,7 @@ Running Sinatra on a not officially supported Ruby flavor means that if things o
|
|
2838
2949
|
## The Bleeding Edge
|
2839
2950
|
|
2840
2951
|
If you would like to use Sinatra's latest bleeding-edge code, feel free
|
2841
|
-
to run your application against the
|
2952
|
+
to run your application against the main branch, it should be rather
|
2842
2953
|
stable.
|
2843
2954
|
|
2844
2955
|
We also push out prerelease gems from time to time, so you can do a
|
@@ -2887,20 +2998,19 @@ SemVerTag.
|
|
2887
2998
|
|
2888
2999
|
## Further Reading
|
2889
3000
|
|
2890
|
-
* [Project Website](
|
3001
|
+
* [Project Website](https://sinatrarb.com/) - Additional documentation,
|
2891
3002
|
news, and links to other resources.
|
2892
|
-
* [Contributing](
|
3003
|
+
* [Contributing](https://sinatrarb.com/contributing) - Find a bug? Need
|
2893
3004
|
help? Have a patch?
|
2894
3005
|
* [Issue tracker](https://github.com/sinatra/sinatra/issues)
|
2895
3006
|
* [Twitter](https://twitter.com/sinatra)
|
2896
3007
|
* [Mailing List](https://groups.google.com/forum/#!forum/sinatrarb)
|
2897
3008
|
* IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on [Freenode](https://freenode.net)
|
2898
|
-
* [Sinatra & Friends](https://
|
2899
|
-
([get an invite](https://sinatra-slack.herokuapp.com/))
|
3009
|
+
* [Sinatra & Friends](https://discord.gg/ncjsfsNHh7) on Discord
|
2900
3010
|
* [Sinatra Book](https://github.com/sinatra/sinatra-book) - Cookbook Tutorial
|
2901
3011
|
* [Sinatra Recipes](http://recipes.sinatrarb.com/) - Community contributed
|
2902
3012
|
recipes
|
2903
|
-
* API documentation for the [latest release](
|
2904
|
-
or the [current HEAD](
|
2905
|
-
[RubyDoc](
|
3013
|
+
* API documentation for the [latest release](https://www.rubydoc.info/gems/sinatra)
|
3014
|
+
or the [current HEAD](https://www.rubydoc.info/github/sinatra/sinatra) on
|
3015
|
+
[RubyDoc](https://www.rubydoc.info/)
|
2906
3016
|
* [CI Actions](https://github.com/sinatra/sinatra/actions)
|
data/Rakefile
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rake/clean'
|
4
|
-
require '
|
4
|
+
require 'minitest/test_task'
|
5
5
|
require 'fileutils'
|
6
6
|
require 'date'
|
7
7
|
|
8
8
|
task default: :test
|
9
|
-
task spec: :test
|
10
|
-
|
11
|
-
CLEAN.include '**/*.rbc'
|
12
9
|
|
13
10
|
def source_version
|
14
11
|
@source_version ||= File.read(File.expand_path('VERSION', __dir__)).strip
|
@@ -24,27 +21,20 @@ def prev_version
|
|
24
21
|
source_version.gsub(/\d+$/) { |s| s.to_i - 1 }
|
25
22
|
end
|
26
23
|
|
27
|
-
#
|
24
|
+
# Tests ===============================================================
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
t.ruby_opts = ['-r rubygems'] if defined? Gem
|
26
|
+
Minitest::TestTask.create # Default `test` task
|
27
|
+
Minitest::TestTask.create(:'test:core') do |t|
|
32
28
|
t.warning = true
|
33
|
-
|
34
|
-
|
35
|
-
Rake::TestTask.new(:'test:core') do |t|
|
36
|
-
core_tests = %w[
|
29
|
+
t.test_globs = %w[
|
37
30
|
base delegator encoding extensions filter
|
38
31
|
helpers mapped_error middleware rdoc
|
39
32
|
readme request response result route_added_hook
|
40
33
|
routing server settings sinatra static templates
|
41
|
-
]
|
42
|
-
t.test_files = core_tests.map { |n| "test/#{n}_test.rb" }
|
43
|
-
t.ruby_opts = ['-r rubygems'] if defined? Gem
|
44
|
-
t.warning = true
|
34
|
+
].map { |n| "test/#{n}_test.rb" }
|
45
35
|
end
|
46
36
|
|
47
|
-
#
|
37
|
+
# Test code coverage ==================================================
|
48
38
|
|
49
39
|
namespace :test do
|
50
40
|
desc 'Measures test coverage'
|
@@ -54,6 +44,7 @@ namespace :test do
|
|
54
44
|
Rake::Task['test'].invoke
|
55
45
|
end
|
56
46
|
end
|
47
|
+
CLEAN.include('coverage')
|
57
48
|
|
58
49
|
# Website =============================================================
|
59
50
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0
|
1
|
+
3.1.0
|
data/examples/chat.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby -I ../lib -I lib
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
# This example does *not* work properly with WEBrick or other
|
5
|
+
# servers that buffer output. To shut down the server, close any
|
6
|
+
# open browser tabs that are connected to the chat server.
|
5
7
|
|
6
8
|
require 'sinatra'
|
7
|
-
set :server, :
|
8
|
-
connections =
|
9
|
+
set :server, :puma
|
10
|
+
connections = Set.new
|
9
11
|
|
10
12
|
get '/' do
|
11
13
|
halt erb(:login) unless params[:user]
|
@@ -14,13 +16,22 @@ end
|
|
14
16
|
|
15
17
|
get '/stream', provides: 'text/event-stream' do
|
16
18
|
stream :keep_open do |out|
|
17
|
-
connections
|
18
|
-
|
19
|
+
if connections.add?(out)
|
20
|
+
out.callback { connections.delete(out) }
|
21
|
+
end
|
22
|
+
out << "heartbeat:\n"
|
23
|
+
sleep 1
|
24
|
+
rescue
|
25
|
+
out.close
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
29
|
post '/' do
|
23
|
-
connections.each
|
30
|
+
connections.each do |out|
|
31
|
+
out << "data: #{params[:msg]}\n\n"
|
32
|
+
rescue
|
33
|
+
out.close
|
34
|
+
end
|
24
35
|
204 # response without entity body
|
25
36
|
end
|
26
37
|
|
@@ -37,10 +48,10 @@ __END__
|
|
37
48
|
</html>
|
38
49
|
|
39
50
|
@@ login
|
40
|
-
<form action=
|
51
|
+
<form action="/">
|
41
52
|
<label for='user'>User Name:</label>
|
42
|
-
<input name=
|
43
|
-
<input type=
|
53
|
+
<input name="user" value="" />
|
54
|
+
<input type="submit" value="GO!" />
|
44
55
|
</form>
|
45
56
|
|
46
57
|
@@ chat
|
@@ -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
data/lib/sinatra/base.rb
CHANGED
@@ -19,7 +19,7 @@ require 'sinatra/version'
|
|
19
19
|
|
20
20
|
module Sinatra
|
21
21
|
# The request object. See Rack::Request for more info:
|
22
|
-
#
|
22
|
+
# https://rubydoc.info/github/rack/rack/main/Rack/Request
|
23
23
|
class Request < Rack::Request
|
24
24
|
HEADER_PARAM = /\s*[\w.]+=(?:[\w.]+|"(?:[^"\\]|\\.)*")?\s*/.freeze
|
25
25
|
HEADER_VALUE_WITH_PARAMS = %r{(?:(?:\w+|\*)/(?:\w+(?:\.|-|\+)?|\*)*)\s*(?:;#{HEADER_PARAM})*}.freeze
|
@@ -158,8 +158,8 @@ module Sinatra
|
|
158
158
|
|
159
159
|
# The response object. See Rack::Response and Rack::Response::Helpers for
|
160
160
|
# more info:
|
161
|
-
#
|
162
|
-
#
|
161
|
+
# https://rubydoc.info/github/rack/rack/main/Rack/Response
|
162
|
+
# https://rubydoc.info/github/rack/rack/main/Rack/Response/Helpers
|
163
163
|
class Response < Rack::Response
|
164
164
|
DROP_BODY_RESPONSES = [204, 304].freeze
|
165
165
|
|
@@ -291,7 +291,7 @@ module Sinatra
|
|
291
291
|
elsif value
|
292
292
|
# Rack 2.0 returns a Rack::File::Iterator here instead of
|
293
293
|
# Rack::File as it was in the previous API.
|
294
|
-
unless request.head? || value.is_a?(Rack::
|
294
|
+
unless request.head? || value.is_a?(Rack::Files::Iterator) || value.is_a?(Stream)
|
295
295
|
headers.delete 'Content-Length'
|
296
296
|
end
|
297
297
|
response.body = value
|
@@ -317,7 +317,7 @@ module Sinatra
|
|
317
317
|
# Generates the absolute URI for a given path in the app.
|
318
318
|
# Takes Rack routers and reverse proxies into account.
|
319
319
|
def uri(addr = nil, absolute = true, add_script_name = true)
|
320
|
-
return addr if addr =~ /\A[a-z][a-z0-9+.\-]*:/i
|
320
|
+
return addr if addr.to_s =~ /\A[a-z][a-z0-9+.\-]*:/i
|
321
321
|
|
322
322
|
uri = [host = String.new]
|
323
323
|
if absolute
|
@@ -429,7 +429,7 @@ module Sinatra
|
|
429
429
|
|
430
430
|
last_modified opts[:last_modified] if opts[:last_modified]
|
431
431
|
|
432
|
-
file = Rack::
|
432
|
+
file = Rack::Files.new(File.dirname(settings.app_file))
|
433
433
|
result = file.serving(request, path)
|
434
434
|
|
435
435
|
result[1].each { |k, v| headers[k] ||= v }
|
@@ -474,8 +474,9 @@ module Sinatra
|
|
474
474
|
@back.call(self)
|
475
475
|
rescue Exception => e
|
476
476
|
@scheduler.schedule { raise e }
|
477
|
+
ensure
|
478
|
+
close unless @keep_open
|
477
479
|
end
|
478
|
-
close unless @keep_open
|
479
480
|
end
|
480
481
|
end
|
481
482
|
|
@@ -506,7 +507,16 @@ module Sinatra
|
|
506
507
|
def stream(keep_open = false)
|
507
508
|
scheduler = env['async.callback'] ? EventMachine : Stream
|
508
509
|
current = @params.dup
|
509
|
-
|
510
|
+
stream = if scheduler == Stream && keep_open
|
511
|
+
Stream.new(scheduler, false) do |out|
|
512
|
+
until out.closed?
|
513
|
+
with_params(current) { yield(out) }
|
514
|
+
end
|
515
|
+
end
|
516
|
+
else
|
517
|
+
Stream.new(scheduler, keep_open) { |out| with_params(current) { yield(out) } }
|
518
|
+
end
|
519
|
+
body stream
|
510
520
|
end
|
511
521
|
|
512
522
|
# Specify response freshness policy for HTTP caches (Cache-Control header).
|
@@ -716,7 +726,7 @@ module Sinatra
|
|
716
726
|
# Possible options are:
|
717
727
|
# :content_type The content type to use, same arguments as content_type.
|
718
728
|
# :layout If set to something falsy, no layout is rendered, otherwise
|
719
|
-
# the specified layout is used
|
729
|
+
# the specified layout is used (Ignored for `sass`)
|
720
730
|
# :layout_engine Engine to use for rendering the layout.
|
721
731
|
# :locals A hash with local variables that should be available
|
722
732
|
# in the template
|
@@ -742,6 +752,20 @@ module Sinatra
|
|
742
752
|
render(:haml, template, options, locals, &block)
|
743
753
|
end
|
744
754
|
|
755
|
+
def sass(template, options = {}, locals = {})
|
756
|
+
options[:default_content_type] = :css
|
757
|
+
options[:exclude_outvar] = true
|
758
|
+
options[:layout] = nil
|
759
|
+
render :sass, template, options, locals
|
760
|
+
end
|
761
|
+
|
762
|
+
def scss(template, options = {}, locals = {})
|
763
|
+
options[:default_content_type] = :css
|
764
|
+
options[:exclude_outvar] = true
|
765
|
+
options[:layout] = nil
|
766
|
+
render :scss, template, options, locals
|
767
|
+
end
|
768
|
+
|
745
769
|
def builder(template = nil, options = {}, locals = {}, &block)
|
746
770
|
options[:default_content_type] = :xml
|
747
771
|
render_ruby(:builder, template, options, locals, &block)
|
@@ -852,7 +876,11 @@ module Sinatra
|
|
852
876
|
catch(:layout_missing) { return render(layout_engine, layout, options, locals) { output } }
|
853
877
|
end
|
854
878
|
|
855
|
-
|
879
|
+
if content_type
|
880
|
+
# sass-embedded returns a frozen string
|
881
|
+
output = +output
|
882
|
+
output.extend(ContentTyped).content_type = content_type
|
883
|
+
end
|
856
884
|
output
|
857
885
|
end
|
858
886
|
|
@@ -904,6 +932,35 @@ module Sinatra
|
|
904
932
|
end
|
905
933
|
end
|
906
934
|
|
935
|
+
# Extremely simple template cache implementation.
|
936
|
+
# * Not thread-safe.
|
937
|
+
# * Size is unbounded.
|
938
|
+
# * Keys are not copied defensively, and should not be modified after
|
939
|
+
# being passed to #fetch. More specifically, the values returned by
|
940
|
+
# key#hash and key#eql? should not change.
|
941
|
+
#
|
942
|
+
# Implementation copied from Tilt::Cache.
|
943
|
+
class TemplateCache
|
944
|
+
def initialize
|
945
|
+
@cache = {}
|
946
|
+
end
|
947
|
+
|
948
|
+
# Caches a value for key, or returns the previously cached value.
|
949
|
+
# If a value has been previously cached for key then it is
|
950
|
+
# returned. Otherwise, block is yielded to and its return value
|
951
|
+
# which may be nil, is cached under key and returned.
|
952
|
+
def fetch(*key)
|
953
|
+
@cache.fetch(key) do
|
954
|
+
@cache[key] = yield
|
955
|
+
end
|
956
|
+
end
|
957
|
+
|
958
|
+
# Clears the cache.
|
959
|
+
def clear
|
960
|
+
@cache = {}
|
961
|
+
end
|
962
|
+
end
|
963
|
+
|
907
964
|
# Base class for all Sinatra applications and middleware.
|
908
965
|
class Base
|
909
966
|
include Rack::Utils
|
@@ -918,7 +975,7 @@ module Sinatra
|
|
918
975
|
def initialize(app = nil, **_kwargs)
|
919
976
|
super()
|
920
977
|
@app = app
|
921
|
-
@template_cache =
|
978
|
+
@template_cache = TemplateCache.new
|
922
979
|
@pinned_response = nil # whether a before! filter pinned the content-type
|
923
980
|
yield self if block_given?
|
924
981
|
end
|
@@ -1216,10 +1273,15 @@ module Sinatra
|
|
1216
1273
|
%r{rubygems/(custom|core_ext/kernel)_require\.rb$}, # rubygems require hacks
|
1217
1274
|
/active_support/, # active_support require hacks
|
1218
1275
|
%r{bundler(/(?:runtime|inline))?\.rb}, # bundler require hacks
|
1219
|
-
/<internal
|
1276
|
+
/<internal:/, # internal in ruby >= 1.9.2
|
1277
|
+
%r{zeitwerk/kernel\.rb} # Zeitwerk kernel#require decorator
|
1220
1278
|
].freeze
|
1221
1279
|
|
1222
|
-
attr_reader :routes, :filters, :templates, :errors
|
1280
|
+
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
|
1281
|
+
|
1282
|
+
def callers_to_ignore
|
1283
|
+
CALLERS_TO_IGNORE
|
1284
|
+
end
|
1223
1285
|
|
1224
1286
|
# Removes all routes, filters, middleware and extension hooks from the
|
1225
1287
|
# current class (not routes/filters/... defined by its superclass).
|
@@ -1408,6 +1470,14 @@ module Sinatra
|
|
1408
1470
|
filters[type] << compile!(type, path, block, **options)
|
1409
1471
|
end
|
1410
1472
|
|
1473
|
+
def on_start(&on_start_callback)
|
1474
|
+
@on_start_callback = on_start_callback
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
def on_stop(&on_stop_callback)
|
1478
|
+
@on_stop_callback = on_stop_callback
|
1479
|
+
end
|
1480
|
+
|
1411
1481
|
# Add a route condition. The route is considered non-matching when the
|
1412
1482
|
# block returns false.
|
1413
1483
|
def condition(name = "#{caller.first[/`.*'/]} condition", &block)
|
@@ -1497,12 +1567,14 @@ module Sinatra
|
|
1497
1567
|
warn '== Sinatra has ended his set (crowd applauds)' unless suppress_messages?
|
1498
1568
|
set :running_server, nil
|
1499
1569
|
set :handler_name, nil
|
1570
|
+
|
1571
|
+
on_stop_callback.call unless on_stop_callback.nil?
|
1500
1572
|
end
|
1501
1573
|
|
1502
1574
|
alias stop! quit!
|
1503
1575
|
|
1504
1576
|
# Run the Sinatra app as a self-hosted server using
|
1505
|
-
# Puma, Falcon,
|
1577
|
+
# Puma, Falcon, or WEBrick (in that order). If given a block, will call
|
1506
1578
|
# with the constructed handler once we have taken the stage.
|
1507
1579
|
def run!(options = {}, &block)
|
1508
1580
|
return if running?
|
@@ -1584,7 +1656,7 @@ module Sinatra
|
|
1584
1656
|
set :running_server, server
|
1585
1657
|
set :handler_name, handler_name
|
1586
1658
|
server.threaded = settings.threaded if server.respond_to? :threaded=
|
1587
|
-
|
1659
|
+
on_start_callback.call unless on_start_callback.nil?
|
1588
1660
|
yield server if block_given?
|
1589
1661
|
end
|
1590
1662
|
end
|
@@ -1787,7 +1859,7 @@ module Sinatra
|
|
1787
1859
|
def cleaned_caller(keep = 3)
|
1788
1860
|
caller(1)
|
1789
1861
|
.map! { |line| line.split(/:(?=\d|in )/, 3)[0, keep] }
|
1790
|
-
.reject { |file, *_|
|
1862
|
+
.reject { |file, *_| callers_to_ignore.any? { |pattern| file =~ pattern } }
|
1791
1863
|
end
|
1792
1864
|
end
|
1793
1865
|
|
@@ -1833,8 +1905,9 @@ module Sinatra
|
|
1833
1905
|
begin
|
1834
1906
|
require 'securerandom'
|
1835
1907
|
set :session_secret, SecureRandom.hex(64)
|
1836
|
-
rescue LoadError, NotImplementedError
|
1908
|
+
rescue LoadError, NotImplementedError, RuntimeError
|
1837
1909
|
# SecureRandom raises a NotImplementedError if no random device is available
|
1910
|
+
# RuntimeError raised due to broken openssl backend: https://bugs.ruby-lang.org/issues/19230
|
1838
1911
|
set :session_secret, format('%064x', Kernel.rand((2**256) - 1))
|
1839
1912
|
end
|
1840
1913
|
|
@@ -1854,11 +1927,10 @@ module Sinatra
|
|
1854
1927
|
|
1855
1928
|
ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1856
1929
|
|
1857
|
-
server.unshift 'puma'
|
1858
|
-
server.unshift 'falcon' if ruby_engine != 'jruby'
|
1859
|
-
server.unshift 'mongrel' if ruby_engine.nil?
|
1860
1930
|
server.unshift 'thin' if ruby_engine != 'jruby'
|
1931
|
+
server.unshift 'falcon' if ruby_engine != 'jruby'
|
1861
1932
|
server.unshift 'trinidad' if ruby_engine == 'jruby'
|
1933
|
+
server.unshift 'puma'
|
1862
1934
|
|
1863
1935
|
set :absolute_redirects, true
|
1864
1936
|
set :prefixed_redirects, false
|
@@ -1975,7 +2047,7 @@ module Sinatra
|
|
1975
2047
|
delegate :get, :patch, :put, :post, :delete, :head, :options, :link, :unlink,
|
1976
2048
|
:template, :layout, :before, :after, :error, :not_found, :configure,
|
1977
2049
|
:set, :mime_type, :enable, :disable, :use, :development?, :test?,
|
1978
|
-
:production?, :helpers, :settings, :register
|
2050
|
+
:production?, :helpers, :settings, :register, :on_start, :on_stop
|
1979
2051
|
|
1980
2052
|
class << self
|
1981
2053
|
attr_accessor :target
|
data/lib/sinatra/version.rb
CHANGED
data/sinatra.gemspec
CHANGED
@@ -36,7 +36,7 @@ RubyGems 2.0 or newer is required to protect against public gem pushes. You can
|
|
36
36
|
|
37
37
|
s.metadata = {
|
38
38
|
'source_code_uri' => 'https://github.com/sinatra/sinatra',
|
39
|
-
'changelog_uri' => 'https://github.com/sinatra/sinatra/blob/
|
39
|
+
'changelog_uri' => 'https://github.com/sinatra/sinatra/blob/main/CHANGELOG.md',
|
40
40
|
'homepage_uri' => 'http://sinatrarb.com/',
|
41
41
|
'bug_tracker_uri' => 'https://github.com/sinatra/sinatra/issues',
|
42
42
|
'mailing_list_uri' => 'http://groups.google.com/group/sinatrarb',
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Mizerany
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2023-08-07 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.1.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.1.0
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: tilt
|
66
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- SECURITY.md
|
111
111
|
- VERSION
|
112
112
|
- examples/chat.rb
|
113
|
+
- examples/lifecycle_events.rb
|
113
114
|
- examples/rainbows.conf
|
114
115
|
- examples/rainbows.rb
|
115
116
|
- examples/simple.rb
|
@@ -128,7 +129,7 @@ licenses:
|
|
128
129
|
- MIT
|
129
130
|
metadata:
|
130
131
|
source_code_uri: https://github.com/sinatra/sinatra
|
131
|
-
changelog_uri: https://github.com/sinatra/sinatra/blob/
|
132
|
+
changelog_uri: https://github.com/sinatra/sinatra/blob/main/CHANGELOG.md
|
132
133
|
homepage_uri: http://sinatrarb.com/
|
133
134
|
bug_tracker_uri: https://github.com/sinatra/sinatra/issues
|
134
135
|
mailing_list_uri: http://groups.google.com/group/sinatrarb
|
@@ -154,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
155
|
- !ruby/object:Gem::Version
|
155
156
|
version: '0'
|
156
157
|
requirements: []
|
157
|
-
rubygems_version: 3.
|
158
|
+
rubygems_version: 3.4.18
|
158
159
|
signing_key:
|
159
160
|
specification_version: 4
|
160
161
|
summary: Classy web-development dressed in a DSL
|