sinatra 3.0.6 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml 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