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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08567da318760f376b1c6c8ccafd4e1268ff19a800c90939d9f1448a7c85edcb'
4
- data.tar.gz: 4287d74952e33c257cd981ed731e732cd0811dbeaeeb7fa553817ef3ad44a9d8
3
+ metadata.gz: 6eddf8c0c677b8b8b7f15bb03834147034ead41bc6310bf773ac84712bb43a14
4
+ data.tar.gz: c35de3457f199d57a3c8a4419bd0ad113df38ba071cfffbcc79311db910bc1cb
5
5
  SHA512:
6
- metadata.gz: af4979f21e7a5bc8e2aebadc68138ad5885829d5c25060303c526fec354552d178d39ae050f5a49700da4bc4b4653264e5371c6dfda44df585a7f198353f65dc
7
- data.tar.gz: 3cd222fd4e5a5337cc63a6df8d813ec695cb2e4ea73294048de169e92c93dcee36a6d90f2bbb0a3525f3d27b86c3499f762f1c0b8904e79c7a012a9852095aeb
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
- * **Konstantin Haase** (maintainer)
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](http://heroku.com), [GitHub](https://github.com) and
24
- [Engine Yard](http://www.engineyard.com/), and is now taken care of by
25
- [Travis CI](http://travis-ci.com/).
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', github: 'rack/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
- gem 'activesupport', '~> 6.1'
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
- gem 'markaby'
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
- gem 'rainbows', platforms: [:mri] # uses #fork
50
- gem 'rdiscount', platforms: [:ruby]
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="http://slim-lang.com/" title="Slim Lang">Slim Lang</a></td>
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. This only works on evented servers, like Rainbows.
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
- # indicate client to connect again
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 exceptions (will stop application). Enabled by default when
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
- Custom errors:
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. This would mean that when starting
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 github repository'
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 -a -m '#{source_version} release' &&
207
- git tag -s v#{source_version} -m '#{source_version} release' &&
208
- git push && (git push origin || true) &&
209
- git push --tags && (git push origin --tags || true)
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
- * Contact the current security coordinator [Zachary Scott](mailto:zzak@ruby-lang.org) directly
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.6
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 (Rainbows!) implement an extended body object protocol, however,
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. This is only relevant for evented
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
- output.extend(ContentTyped).content_type = content_type if content_type
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 = Tilt::Cache.new
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
- msg = ["#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - #{boom.class} - #{boom.message}:", *boom.backtrace].join("\n\t")
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, Mongrel, or WEBrick (in that order). If given a block, will call
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='#{uri '/__sinatra__/404.png'}'>
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(:a=>1)
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.new(:a=>1)
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)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sinatra
4
- VERSION = '3.0.6'
4
+ VERSION = '3.2.0'
5
5
  end
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.6
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-04-11 00:00:00.000000000 Z
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.6
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.6
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/rainbows.conf
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.4.10
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: []
@@ -1,3 +0,0 @@
1
- Rainbows! do
2
- use :EventMachine
3
- end
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