sinatra-rack-3-commonlit 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,3016 @@
1
+ # Sinatra
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/sinatra.svg)](https://badge.fury.io/rb/sinatra)
4
+ [![Testing](https://github.com/sinatra/sinatra/actions/workflows/test.yml/badge.svg)](https://github.com/sinatra/sinatra/actions/workflows/test.yml)
5
+
6
+ Sinatra is a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for
7
+ quickly creating web applications in Ruby with minimal effort:
8
+
9
+ ```ruby
10
+ # myapp.rb
11
+ require 'sinatra'
12
+
13
+ get '/' do
14
+ 'Hello world!'
15
+ end
16
+ ```
17
+
18
+ Install the gem:
19
+
20
+ ```shell
21
+ gem install sinatra
22
+ gem install puma # or any other server
23
+ ```
24
+
25
+ And run with:
26
+
27
+ ```shell
28
+ ruby myapp.rb
29
+ ```
30
+
31
+ View at: [http://localhost:4567](http://localhost:4567)
32
+
33
+ The code you changed will not take effect until you restart the server.
34
+ Please restart the server every time you change or use a code reloader
35
+ like [rerun](https://github.com/alexch/rerun) or
36
+ [rack-unreloader](https://github.com/jeremyevans/rack-unreloader).
37
+
38
+ It is recommended to also run `gem install puma`, which Sinatra will
39
+ pick up if available.
40
+
41
+ ## Table of Contents
42
+
43
+ - [Sinatra](#sinatra)
44
+ - [Table of Contents](#table-of-contents)
45
+ - [Routes](#routes)
46
+ - [Conditions](#conditions)
47
+ - [Return Values](#return-values)
48
+ - [Custom Route Matchers](#custom-route-matchers)
49
+ - [Static Files](#static-files)
50
+ - [Views / Templates](#views--templates)
51
+ - [Literal Templates](#literal-templates)
52
+ - [Available Template Languages](#available-template-languages)
53
+ - [Haml Templates](#haml-templates)
54
+ - [Erb Templates](#erb-templates)
55
+ - [Builder Templates](#builder-templates)
56
+ - [Nokogiri Templates](#nokogiri-templates)
57
+ - [Sass Templates](#sass-templates)
58
+ - [Scss Templates](#scss-templates)
59
+ - [Liquid Templates](#liquid-templates)
60
+ - [Markdown Templates](#markdown-templates)
61
+ - [RDoc Templates](#rdoc-templates)
62
+ - [AsciiDoc Templates](#asciidoc-templates)
63
+ - [Markaby Templates](#markaby-templates)
64
+ - [RABL Templates](#rabl-templates)
65
+ - [Slim Templates](#slim-templates)
66
+ - [Yajl Templates](#yajl-templates)
67
+ - [Accessing Variables in Templates](#accessing-variables-in-templates)
68
+ - [Templates with `yield` and nested layouts](#templates-with-yield-and-nested-layouts)
69
+ - [Inline Templates](#inline-templates)
70
+ - [Named Templates](#named-templates)
71
+ - [Associating File Extensions](#associating-file-extensions)
72
+ - [Adding Your Own Template Engine](#adding-your-own-template-engine)
73
+ - [Using Custom Logic for Template Lookup](#using-custom-logic-for-template-lookup)
74
+ - [Filters](#filters)
75
+ - [Helpers](#helpers)
76
+ - [Using Sessions](#using-sessions)
77
+ - [Session Secret Security](#session-secret-security)
78
+ - [Session Config](#session-config)
79
+ - [Choosing Your Own Session Middleware](#choosing-your-own-session-middleware)
80
+ - [Halting](#halting)
81
+ - [Passing](#passing)
82
+ - [Triggering Another Route](#triggering-another-route)
83
+ - [Setting Body, Status Code, and Headers](#setting-body-status-code-and-headers)
84
+ - [Streaming Responses](#streaming-responses)
85
+ - [Logging](#logging)
86
+ - [Mime Types](#mime-types)
87
+ - [Generating URLs](#generating-urls)
88
+ - [Browser Redirect](#browser-redirect)
89
+ - [Cache Control](#cache-control)
90
+ - [Sending Files](#sending-files)
91
+ - [Accessing the Request Object](#accessing-the-request-object)
92
+ - [Attachments](#attachments)
93
+ - [Dealing with Date and Time](#dealing-with-date-and-time)
94
+ - [Looking Up Template Files](#looking-up-template-files)
95
+ - [Configuration](#configuration)
96
+ - [Configuring attack protection](#configuring-attack-protection)
97
+ - [Available Settings](#available-settings)
98
+ - [Lifecycle Events](#lifecycle-events)
99
+ - [Environments](#environments)
100
+ - [Error Handling](#error-handling)
101
+ - [Not Found](#not-found)
102
+ - [Error](#error)
103
+ - [Rack Middleware](#rack-middleware)
104
+ - [Testing](#testing)
105
+ - [Sinatra::Base - Middleware, Libraries, and Modular Apps](#sinatrabase---middleware-libraries-and-modular-apps)
106
+ - [Modular vs. Classic Style](#modular-vs-classic-style)
107
+ - [Serving a Modular Application](#serving-a-modular-application)
108
+ - [Using a Classic Style Application with a config.ru](#using-a-classic-style-application-with-a-configru)
109
+ - [When to use a config.ru?](#when-to-use-a-configru)
110
+ - [Using Sinatra as Middleware](#using-sinatra-as-middleware)
111
+ - [Dynamic Application Creation](#dynamic-application-creation)
112
+ - [Scopes and Binding](#scopes-and-binding)
113
+ - [Application/Class Scope](#applicationclass-scope)
114
+ - [Request/Instance Scope](#requestinstance-scope)
115
+ - [Delegation Scope](#delegation-scope)
116
+ - [Command Line](#command-line)
117
+ - [Multi-threading](#multi-threading)
118
+ - [Requirement](#requirement)
119
+ - [The Bleeding Edge](#the-bleeding-edge)
120
+ - [With Bundler](#with-bundler)
121
+ - [Versioning](#versioning)
122
+ - [Further Reading](#further-reading)
123
+
124
+ ## Routes
125
+
126
+ In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
127
+ Each route is associated with a block:
128
+
129
+ ```ruby
130
+ get '/' do
131
+ .. show something ..
132
+ end
133
+
134
+ post '/' do
135
+ .. create something ..
136
+ end
137
+
138
+ put '/' do
139
+ .. replace something ..
140
+ end
141
+
142
+ patch '/' do
143
+ .. modify something ..
144
+ end
145
+
146
+ delete '/' do
147
+ .. annihilate something ..
148
+ end
149
+
150
+ options '/' do
151
+ .. appease something ..
152
+ end
153
+
154
+ link '/' do
155
+ .. affiliate something ..
156
+ end
157
+
158
+ unlink '/' do
159
+ .. separate something ..
160
+ end
161
+ ```
162
+
163
+ Routes are matched in the order they are defined. The first route that
164
+ matches the request is invoked.
165
+
166
+ Routes with trailing slashes are different from the ones without:
167
+
168
+ ```ruby
169
+ get '/foo' do
170
+ # Does not match "GET /foo/"
171
+ end
172
+ ```
173
+
174
+ Route patterns may include named parameters, accessible via the
175
+ `params` hash:
176
+
177
+ ```ruby
178
+ get '/hello/:name' do
179
+ # matches "GET /hello/foo" and "GET /hello/bar"
180
+ # params['name'] is 'foo' or 'bar'
181
+ "Hello #{params['name']}!"
182
+ end
183
+ ```
184
+
185
+ You can also access named parameters via block parameters:
186
+
187
+ ```ruby
188
+ get '/hello/:name' do |n|
189
+ # matches "GET /hello/foo" and "GET /hello/bar"
190
+ # params['name'] is 'foo' or 'bar'
191
+ # n stores params['name']
192
+ "Hello #{n}!"
193
+ end
194
+ ```
195
+
196
+ Route patterns may also include splat (or wildcard) parameters, accessible
197
+ via the `params['splat']` array:
198
+
199
+ ```ruby
200
+ get '/say/*/to/*' do
201
+ # matches /say/hello/to/world
202
+ params['splat'] # => ["hello", "world"]
203
+ end
204
+
205
+ get '/download/*.*' do
206
+ # matches /download/path/to/file.xml
207
+ params['splat'] # => ["path/to/file", "xml"]
208
+ end
209
+ ```
210
+
211
+ Or with block parameters:
212
+
213
+ ```ruby
214
+ get '/download/*.*' do |path, ext|
215
+ [path, ext] # => ["path/to/file", "xml"]
216
+ end
217
+ ```
218
+
219
+ Route matching with Regular Expressions:
220
+
221
+ ```ruby
222
+ get /\/hello\/([\w]+)/ do
223
+ "Hello, #{params['captures'].first}!"
224
+ end
225
+ ```
226
+
227
+ Or with a block parameter:
228
+
229
+ ```ruby
230
+ get %r{/hello/([\w]+)} do |c|
231
+ # Matches "GET /meta/hello/world", "GET /hello/world/1234" etc.
232
+ "Hello, #{c}!"
233
+ end
234
+ ```
235
+
236
+ Route patterns may have optional parameters:
237
+
238
+ ```ruby
239
+ get '/posts/:format?' do
240
+ # matches "GET /posts/" and any extension "GET /posts/json", "GET /posts/xml" etc
241
+ end
242
+ ```
243
+
244
+ Routes may also utilize query parameters:
245
+
246
+ ```ruby
247
+ get '/posts' do
248
+ # matches "GET /posts?title=foo&author=bar"
249
+ title = params['title']
250
+ author = params['author']
251
+ # uses title and author variables; query is optional to the /posts route
252
+ end
253
+ ```
254
+
255
+ By the way, unless you disable the path traversal attack protection (see
256
+ [below](#configuring-attack-protection)), the request path might be modified before
257
+ matching against your routes.
258
+
259
+ You may customize the [Mustermann](https://github.com/sinatra/mustermann#readme)
260
+ options used for a given route by passing in a `:mustermann_opts` hash:
261
+
262
+ ```ruby
263
+ get '\A/posts\z', :mustermann_opts => { :type => :regexp, :check_anchors => false } do
264
+ # matches /posts exactly, with explicit anchoring
265
+ "If you match an anchored pattern clap your hands!"
266
+ end
267
+ ```
268
+
269
+ It looks like a [condition](#conditions), but it isn't one! These options will
270
+ be merged into the global `:mustermann_opts` hash described
271
+ [below](#available-settings).
272
+
273
+ ## Conditions
274
+
275
+ Routes may include a variety of matching conditions, such as the user agent:
276
+
277
+ ```ruby
278
+ get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
279
+ "You're using Songbird version #{params['agent'][0]}"
280
+ end
281
+
282
+ get '/foo' do
283
+ # Matches non-songbird browsers
284
+ end
285
+ ```
286
+
287
+ Other available conditions are `host_name` and `provides`:
288
+
289
+ ```ruby
290
+ get '/', :host_name => /^admin\./ do
291
+ "Admin Area, Access denied!"
292
+ end
293
+
294
+ get '/', :provides => 'html' do
295
+ haml :index
296
+ end
297
+
298
+ get '/', :provides => ['rss', 'atom', 'xml'] do
299
+ builder :feed
300
+ end
301
+ ```
302
+ `provides` searches the request's Accept header.
303
+
304
+ You can easily define your own conditions:
305
+
306
+ ```ruby
307
+ set(:probability) { |value| condition { rand <= value } }
308
+
309
+ get '/win_a_car', :probability => 0.1 do
310
+ "You won!"
311
+ end
312
+
313
+ get '/win_a_car' do
314
+ "Sorry, you lost."
315
+ end
316
+ ```
317
+
318
+ For a condition that takes multiple values use a splat:
319
+
320
+ ```ruby
321
+ set(:auth) do |*roles| # <- notice the splat here
322
+ condition do
323
+ unless logged_in? && roles.any? {|role| current_user.in_role? role }
324
+ redirect "/login/", 303
325
+ end
326
+ end
327
+ end
328
+
329
+ get "/my/account/", :auth => [:user, :admin] do
330
+ "Your Account Details"
331
+ end
332
+
333
+ get "/only/admin/", :auth => :admin do
334
+ "Only admins are allowed here!"
335
+ end
336
+ ```
337
+
338
+ ## Return Values
339
+
340
+ The return value of a route block determines at least the response body
341
+ passed on to the HTTP client or at least the next middleware in the
342
+ Rack stack. Most commonly, this is a string, as in the above examples.
343
+ But other values are also accepted.
344
+
345
+ You can return an object that would either be a valid Rack response, Rack
346
+ body object or HTTP status code:
347
+
348
+ * An Array with three elements: `[status (Integer), headers (Hash), response
349
+ body (responds to #each)]`
350
+ * An Array with two elements: `[status (Integer), response body (responds to
351
+ #each)]`
352
+ * An object that responds to `#each` and passes nothing but strings to
353
+ the given block
354
+ * A Integer representing the status code
355
+
356
+ That way we can, for instance, easily implement a streaming example:
357
+
358
+ ```ruby
359
+ class Stream
360
+ def each
361
+ 100.times { |i| yield "#{i}\n" }
362
+ end
363
+ end
364
+
365
+ get('/') { Stream.new }
366
+ ```
367
+
368
+ You can also use the `stream` helper method ([described below](#streaming-responses)) to reduce
369
+ boilerplate and embed the streaming logic in the route.
370
+
371
+ ## Custom Route Matchers
372
+
373
+ As shown above, Sinatra ships with built-in support for using String
374
+ patterns and regular expressions as route matches. However, it does not
375
+ stop there. You can easily define your own matchers:
376
+
377
+ ```ruby
378
+ class AllButPattern
379
+ def initialize(except)
380
+ @except = except
381
+ end
382
+
383
+ def to_pattern(options)
384
+ return self
385
+ end
386
+
387
+ def params(route)
388
+ return {} unless @except === route
389
+ end
390
+ end
391
+
392
+ def all_but(pattern)
393
+ AllButPattern.new(pattern)
394
+ end
395
+
396
+ get all_but("/index") do
397
+ # ...
398
+ end
399
+ ```
400
+
401
+ Note that the above example might be over-engineered, as it can also be
402
+ expressed as:
403
+
404
+ ```ruby
405
+ get /.*/ do
406
+ pass if request.path_info == "/index"
407
+ # ...
408
+ end
409
+ ```
410
+
411
+ ## Static Files
412
+
413
+ Static files are served from the `./public` directory. You can specify
414
+ a different location by setting the `:public_folder` option:
415
+
416
+ ```ruby
417
+ set :public_folder, __dir__ + '/static'
418
+ ```
419
+
420
+ Note that the public directory name is not included in the URL. A file
421
+ `./public/css/style.css` is made available as
422
+ `http://example.com/css/style.css`.
423
+
424
+ Use the `:static_cache_control` setting (see [below](#cache-control)) to add
425
+ `Cache-Control` header info.
426
+
427
+ ## Views / Templates
428
+
429
+ Each template language is exposed via its own rendering method. These
430
+ methods simply return a string:
431
+
432
+ ```ruby
433
+ get '/' do
434
+ erb :index
435
+ end
436
+ ```
437
+
438
+ This renders `views/index.erb`.
439
+
440
+ Instead of a template name, you can also just pass in the template content
441
+ directly:
442
+
443
+ ```ruby
444
+ get '/' do
445
+ code = "<%= Time.now %>"
446
+ erb code
447
+ end
448
+ ```
449
+
450
+ Templates take a second argument, the options hash:
451
+
452
+ ```ruby
453
+ get '/' do
454
+ erb :index, :layout => :post
455
+ end
456
+ ```
457
+
458
+ This will render `views/index.erb` embedded in the
459
+ `views/post.erb` (default is `views/layout.erb`, if it exists).
460
+
461
+ Any options not understood by Sinatra will be passed on to the template
462
+ engine:
463
+
464
+ ```ruby
465
+ get '/' do
466
+ haml :index, :format => :html5
467
+ end
468
+ ```
469
+
470
+ You can also set options per template language in general:
471
+
472
+ ```ruby
473
+ set :haml, :format => :html5
474
+
475
+ get '/' do
476
+ haml :index
477
+ end
478
+ ```
479
+
480
+ Options passed to the render method override options set via `set`.
481
+
482
+ Available Options:
483
+
484
+ <dl>
485
+ <dt>locals</dt>
486
+ <dd>
487
+ List of locals passed to the document. Handy with partials.
488
+ Example: <tt>erb "<%= foo %>", :locals => {:foo => "bar"}</tt>
489
+ </dd>
490
+
491
+ <dt>default_encoding</dt>
492
+ <dd>
493
+ String encoding to use if uncertain. Defaults to
494
+ <tt>settings.default_encoding</tt>.
495
+ </dd>
496
+
497
+ <dt>views</dt>
498
+ <dd>
499
+ Views folder to load templates from. Defaults to <tt>settings.views</tt>.
500
+ </dd>
501
+
502
+ <dt>layout</dt>
503
+ <dd>
504
+ Whether to use a layout (<tt>true</tt> or <tt>false</tt>). If it's a
505
+ Symbol, specifies what template to use. Example:
506
+ <tt>erb :index, :layout => !request.xhr?</tt>
507
+ </dd>
508
+
509
+ <dt>content_type</dt>
510
+ <dd>
511
+ Content-Type the template produces. Default depends on template language.
512
+ </dd>
513
+
514
+ <dt>scope</dt>
515
+ <dd>
516
+ Scope to render template under. Defaults to the application
517
+ instance. If you change this, instance variables and helper methods
518
+ will not be available.
519
+ </dd>
520
+
521
+ <dt>layout_engine</dt>
522
+ <dd>
523
+ Template engine to use for rendering the layout. Useful for
524
+ languages that do not support layouts otherwise. Defaults to the
525
+ engine used for the template. Example: <tt>set :rdoc, :layout_engine
526
+ => :erb</tt>
527
+ </dd>
528
+
529
+ <dt>layout_options</dt>
530
+ <dd>
531
+ Special options only used for rendering the layout. Example:
532
+ <tt>set :rdoc, :layout_options => { :views => 'views/layouts' }</tt>
533
+ </dd>
534
+ </dl>
535
+
536
+ Templates are assumed to be located directly under the `./views`
537
+ directory. To use a different views directory:
538
+
539
+ ```ruby
540
+ set :views, settings.root + '/templates'
541
+ ```
542
+
543
+
544
+ One important thing to remember is that you always have to reference
545
+ templates with symbols, even if they're in a subdirectory (in this case,
546
+ use: `:'subdir/template'` or `'subdir/template'.to_sym`). You must use a
547
+ symbol because otherwise rendering methods will render any strings
548
+ passed to them directly.
549
+
550
+ ### Literal Templates
551
+
552
+ ```ruby
553
+ get '/' do
554
+ haml '%div.title Hello World'
555
+ end
556
+ ```
557
+
558
+ Renders the template string. You can optionally specify `:path` and
559
+ `:line` for a clearer backtrace if there is a filesystem path or line
560
+ associated with that string:
561
+
562
+ ```ruby
563
+ get '/' do
564
+ haml '%div.title Hello World', :path => 'examples/file.haml', :line => 3
565
+ end
566
+ ```
567
+
568
+ ### Available Template Languages
569
+
570
+ Some languages have multiple implementations. To specify what implementation
571
+ to use (and to be thread-safe), you should simply require it first:
572
+
573
+ ```ruby
574
+ require 'rdiscount'
575
+ get('/') { markdown :index }
576
+ ```
577
+
578
+ #### Haml Templates
579
+
580
+ <table>
581
+ <tr>
582
+ <td>Dependency</td>
583
+ <td><a href="http://haml.info/" title="haml">haml</a></td>
584
+ </tr>
585
+ <tr>
586
+ <td>File Extension</td>
587
+ <td><tt>.haml</tt></td>
588
+ </tr>
589
+ <tr>
590
+ <td>Example</td>
591
+ <td><tt>haml :index, :format => :html5</tt></td>
592
+ </tr>
593
+ </table>
594
+
595
+ #### Erb Templates
596
+
597
+ <table>
598
+ <tr>
599
+ <td>Dependency</td>
600
+ <td>
601
+ <a href="https://github.com/jeremyevans/erubi" title="erubi">erubi</a>
602
+ or erb (included in Ruby)
603
+ </td>
604
+ </tr>
605
+ <tr>
606
+ <td>File Extensions</td>
607
+ <td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubi</tt> (Erubi only)</td>
608
+ </tr>
609
+ <tr>
610
+ <td>Example</td>
611
+ <td><tt>erb :index</tt></td>
612
+ </tr>
613
+ </table>
614
+
615
+ #### Builder Templates
616
+
617
+ <table>
618
+ <tr>
619
+ <td>Dependency</td>
620
+ <td>
621
+ <a href="https://github.com/jimweirich/builder" title="builder">builder</a>
622
+ </td>
623
+ </tr>
624
+ <tr>
625
+ <td>File Extension</td>
626
+ <td><tt>.builder</tt></td>
627
+ </tr>
628
+ <tr>
629
+ <td>Example</td>
630
+ <td><tt>builder { |xml| xml.em "hi" }</tt></td>
631
+ </tr>
632
+ </table>
633
+
634
+ It also takes a block for inline templates (see [example](#inline-templates)).
635
+
636
+ #### Nokogiri Templates
637
+
638
+ <table>
639
+ <tr>
640
+ <td>Dependency</td>
641
+ <td><a href="http://www.nokogiri.org/" title="nokogiri">nokogiri</a></td>
642
+ </tr>
643
+ <tr>
644
+ <td>File Extension</td>
645
+ <td><tt>.nokogiri</tt></td>
646
+ </tr>
647
+ <tr>
648
+ <td>Example</td>
649
+ <td><tt>nokogiri { |xml| xml.em "hi" }</tt></td>
650
+ </tr>
651
+ </table>
652
+
653
+ It also takes a block for inline templates (see [example](#inline-templates)).
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>
688
+
689
+ #### Liquid Templates
690
+
691
+ <table>
692
+ <tr>
693
+ <td>Dependency</td>
694
+ <td><a href="https://shopify.github.io/liquid/" title="liquid">liquid</a></td>
695
+ </tr>
696
+ <tr>
697
+ <td>File Extension</td>
698
+ <td><tt>.liquid</tt></td>
699
+ </tr>
700
+ <tr>
701
+ <td>Example</td>
702
+ <td><tt>liquid :index, :locals => { :key => 'value' }</tt></td>
703
+ </tr>
704
+ </table>
705
+
706
+ Since you cannot call Ruby methods (except for `yield`) from a Liquid
707
+ template, you almost always want to pass locals to it.
708
+
709
+ #### Markdown Templates
710
+
711
+ <table>
712
+ <tr>
713
+ <td>Dependency</td>
714
+ <td>
715
+ Anyone of:
716
+ <a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
717
+ <a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
718
+ <a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
719
+ <a href="https://github.com/gjtorikian/commonmarker" title="commonmarker">commonmarker</a>
720
+ <a href="https://github.com/alphabetum/pandoc-ruby" title="pandoc">pandoc</a>
721
+ </td>
722
+ </tr>
723
+ <tr>
724
+ <td>File Extensions</td>
725
+ <td><tt>.markdown</tt>, <tt>.mkd</tt> and <tt>.md</tt></td>
726
+ </tr>
727
+ <tr>
728
+ <td>Example</td>
729
+ <td><tt>markdown :index, :layout_engine => :erb</tt></td>
730
+ </tr>
731
+ </table>
732
+
733
+ It is not possible to call methods from Markdown, nor to pass locals to it.
734
+ You therefore will usually use it in combination with another rendering
735
+ engine:
736
+
737
+ ```ruby
738
+ erb :overview, :locals => { :text => markdown(:introduction) }
739
+ ```
740
+
741
+ Note that you may also call the `markdown` method from within other
742
+ templates:
743
+
744
+ ```ruby
745
+ %h1 Hello From Haml!
746
+ %p= markdown(:greetings)
747
+ ```
748
+
749
+ Since you cannot call Ruby from Markdown, you cannot use layouts written in
750
+ Markdown. However, it is possible to use another rendering engine for the
751
+ template than for the layout by passing the `:layout_engine` option.
752
+
753
+ #### RDoc Templates
754
+
755
+ <table>
756
+ <tr>
757
+ <td>Dependency</td>
758
+ <td><a href="http://rdoc.sourceforge.net/" title="RDoc">RDoc</a></td>
759
+ </tr>
760
+ <tr>
761
+ <td>File Extension</td>
762
+ <td><tt>.rdoc</tt></td>
763
+ </tr>
764
+ <tr>
765
+ <td>Example</td>
766
+ <td><tt>rdoc :README, :layout_engine => :erb</tt></td>
767
+ </tr>
768
+ </table>
769
+
770
+ It is not possible to call methods from RDoc, nor to pass locals to it. You
771
+ therefore will usually use it in combination with another rendering engine:
772
+
773
+ ```ruby
774
+ erb :overview, :locals => { :text => rdoc(:introduction) }
775
+ ```
776
+
777
+ Note that you may also call the `rdoc` method from within other templates:
778
+
779
+ ```ruby
780
+ %h1 Hello From Haml!
781
+ %p= rdoc(:greetings)
782
+ ```
783
+
784
+ Since you cannot call Ruby from RDoc, you cannot use layouts written in
785
+ RDoc. However, it is possible to use another rendering engine for the
786
+ template than for the layout by passing the `:layout_engine` option.
787
+
788
+ #### AsciiDoc Templates
789
+
790
+ <table>
791
+ <tr>
792
+ <td>Dependency</td>
793
+ <td><a href="http://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td>
794
+ </tr>
795
+ <tr>
796
+ <td>File Extension</td>
797
+ <td><tt>.asciidoc</tt>, <tt>.adoc</tt> and <tt>.ad</tt></td>
798
+ </tr>
799
+ <tr>
800
+ <td>Example</td>
801
+ <td><tt>asciidoc :README, :layout_engine => :erb</tt></td>
802
+ </tr>
803
+ </table>
804
+
805
+ Since you cannot call Ruby methods directly from an AsciiDoc template, you
806
+ almost always want to pass locals to it.
807
+
808
+ #### Markaby Templates
809
+
810
+ <table>
811
+ <tr>
812
+ <td>Dependency</td>
813
+ <td><a href="https://markaby.github.io/" title="Markaby">Markaby</a></td>
814
+ </tr>
815
+ <tr>
816
+ <td>File Extension</td>
817
+ <td><tt>.mab</tt></td>
818
+ </tr>
819
+ <tr>
820
+ <td>Example</td>
821
+ <td><tt>markaby { h1 "Welcome!" }</tt></td>
822
+ </tr>
823
+ </table>
824
+
825
+ It also takes a block for inline templates (see [example](#inline-templates)).
826
+
827
+ #### RABL Templates
828
+
829
+ <table>
830
+ <tr>
831
+ <td>Dependency</td>
832
+ <td><a href="https://github.com/nesquena/rabl" title="Rabl">Rabl</a></td>
833
+ </tr>
834
+ <tr>
835
+ <td>File Extension</td>
836
+ <td><tt>.rabl</tt></td>
837
+ </tr>
838
+ <tr>
839
+ <td>Example</td>
840
+ <td><tt>rabl :index</tt></td>
841
+ </tr>
842
+ </table>
843
+
844
+ #### Slim Templates
845
+
846
+ <table>
847
+ <tr>
848
+ <td>Dependency</td>
849
+ <td><a href="http://slim-lang.com/" title="Slim Lang">Slim Lang</a></td>
850
+ </tr>
851
+ <tr>
852
+ <td>File Extension</td>
853
+ <td><tt>.slim</tt></td>
854
+ </tr>
855
+ <tr>
856
+ <td>Example</td>
857
+ <td><tt>slim :index</tt></td>
858
+ </tr>
859
+ </table>
860
+
861
+ #### Yajl Templates
862
+
863
+ <table>
864
+ <tr>
865
+ <td>Dependency</td>
866
+ <td><a href="https://github.com/brianmario/yajl-ruby" title="yajl-ruby">yajl-ruby</a></td>
867
+ </tr>
868
+ <tr>
869
+ <td>File Extension</td>
870
+ <td><tt>.yajl</tt></td>
871
+ </tr>
872
+ <tr>
873
+ <td>Example</td>
874
+ <td>
875
+ <tt>
876
+ yajl :index,
877
+ :locals => { :key => 'qux' },
878
+ :callback => 'present',
879
+ :variable => 'resource'
880
+ </tt>
881
+ </td>
882
+ </tr>
883
+ </table>
884
+
885
+
886
+ The template source is evaluated as a Ruby string, and the
887
+ resulting json variable is converted using `#to_json`:
888
+
889
+ ```ruby
890
+ json = { :foo => 'bar' }
891
+ json[:baz] = key
892
+ ```
893
+
894
+ The `:callback` and `:variable` options can be used to decorate the rendered
895
+ object:
896
+
897
+ ```javascript
898
+ var resource = {"foo":"bar","baz":"qux"};
899
+ present(resource);
900
+ ```
901
+
902
+ ### Accessing Variables in Templates
903
+
904
+ Templates are evaluated within the same context as route handlers. Instance
905
+ variables set in route handlers are directly accessible by templates:
906
+
907
+ ```ruby
908
+ get '/:id' do
909
+ @foo = Foo.find(params['id'])
910
+ haml '%h1= @foo.name'
911
+ end
912
+ ```
913
+
914
+ Or, specify an explicit Hash of local variables:
915
+
916
+ ```ruby
917
+ get '/:id' do
918
+ foo = Foo.find(params['id'])
919
+ haml '%h1= bar.name', :locals => { :bar => foo }
920
+ end
921
+ ```
922
+
923
+ This is typically used when rendering templates as partials from within
924
+ other templates.
925
+
926
+ ### Templates with `yield` and nested layouts
927
+
928
+ A layout is usually just a template that calls `yield`.
929
+ Such a template can be used either through the `:template` option as
930
+ described above, or it can be rendered with a block as follows:
931
+
932
+ ```ruby
933
+ erb :post, :layout => false do
934
+ erb :index
935
+ end
936
+ ```
937
+
938
+ This code is mostly equivalent to `erb :index, :layout => :post`.
939
+
940
+ Passing blocks to rendering methods is most useful for creating nested
941
+ layouts:
942
+
943
+ ```ruby
944
+ erb :main_layout, :layout => false do
945
+ erb :admin_layout do
946
+ erb :user
947
+ end
948
+ end
949
+ ```
950
+
951
+ This can also be done in fewer lines of code with:
952
+
953
+ ```ruby
954
+ erb :admin_layout, :layout => :main_layout do
955
+ erb :user
956
+ end
957
+ ```
958
+
959
+ Currently, the following rendering methods accept a block: `erb`, `haml`,
960
+ `liquid`, `slim `. Also, the general `render` method accepts a block.
961
+
962
+ ### Inline Templates
963
+
964
+ Templates may be defined at the end of the source file:
965
+
966
+ ```ruby
967
+ require 'sinatra'
968
+
969
+ get '/' do
970
+ haml :index
971
+ end
972
+
973
+ __END__
974
+
975
+ @@ layout
976
+ %html
977
+ != yield
978
+
979
+ @@ index
980
+ %div.title Hello world.
981
+ ```
982
+
983
+ NOTE: Inline templates defined in the source file that requires Sinatra are
984
+ automatically loaded. Call `enable :inline_templates` explicitly if you
985
+ have inline templates in other source files.
986
+
987
+ ### Named Templates
988
+
989
+ Templates may also be defined using the top-level `template` method:
990
+
991
+ ```ruby
992
+ template :layout do
993
+ "%html\n =yield\n"
994
+ end
995
+
996
+ template :index do
997
+ '%div.title Hello World!'
998
+ end
999
+
1000
+ get '/' do
1001
+ haml :index
1002
+ end
1003
+ ```
1004
+
1005
+ If a template named "layout" exists, it will be used each time a template
1006
+ is rendered. You can individually disable layouts by passing
1007
+ `:layout => false` or disable them by default via
1008
+ `set :haml, :layout => false`:
1009
+
1010
+ ```ruby
1011
+ get '/' do
1012
+ haml :index, :layout => !request.xhr?
1013
+ end
1014
+ ```
1015
+
1016
+ ### Associating File Extensions
1017
+
1018
+ To associate a file extension with a template engine, use
1019
+ `Tilt.register`. For instance, if you like to use the file extension
1020
+ `tt` for Haml templates, you can do the following:
1021
+
1022
+ ```ruby
1023
+ Tilt.register Tilt[:haml], :tt
1024
+ ```
1025
+
1026
+ ### Adding Your Own Template Engine
1027
+
1028
+ First, register your engine with Tilt, then create a rendering method:
1029
+
1030
+ ```ruby
1031
+ Tilt.register MyAwesomeTemplateEngine, :myat
1032
+
1033
+ helpers do
1034
+ def myat(*args) render(:myat, *args) end
1035
+ end
1036
+
1037
+ get '/' do
1038
+ myat :index
1039
+ end
1040
+ ```
1041
+
1042
+ Renders `./views/index.myat`. Learn more about
1043
+ [Tilt](https://github.com/rtomayko/tilt#readme).
1044
+
1045
+ ### Using Custom Logic for Template Lookup
1046
+
1047
+ To implement your own template lookup mechanism you can write your
1048
+ own `#find_template` method:
1049
+
1050
+ ```ruby
1051
+ configure do
1052
+ set :views, [ './views/a', './views/b' ]
1053
+ end
1054
+
1055
+ def find_template(views, name, engine, &block)
1056
+ Array(views).each do |v|
1057
+ super(v, name, engine, &block)
1058
+ end
1059
+ end
1060
+ ```
1061
+
1062
+ ## Filters
1063
+
1064
+ Before filters are evaluated before each request within the same context
1065
+ as the routes will be and can modify the request and response. Instance
1066
+ variables set in filters are accessible by routes and templates:
1067
+
1068
+ ```ruby
1069
+ before do
1070
+ @note = 'Hi!'
1071
+ request.path_info = '/foo/bar/baz'
1072
+ end
1073
+
1074
+ get '/foo/*' do
1075
+ @note #=> 'Hi!'
1076
+ params['splat'] #=> 'bar/baz'
1077
+ end
1078
+ ```
1079
+
1080
+ After filters are evaluated after each request within the same context
1081
+ as the routes will be and can also modify the request and response.
1082
+ Instance variables set in before filters and routes are accessible by
1083
+ after filters:
1084
+
1085
+ ```ruby
1086
+ after do
1087
+ puts response.status
1088
+ end
1089
+ ```
1090
+
1091
+ Note: Unless you use the `body` method rather than just returning a
1092
+ String from the routes, the body will not yet be available in the after
1093
+ filter, since it is generated later on.
1094
+
1095
+ Filters optionally take a pattern, causing them to be evaluated only if the
1096
+ request path matches that pattern:
1097
+
1098
+ ```ruby
1099
+ before '/protected/*' do
1100
+ authenticate!
1101
+ end
1102
+
1103
+ after '/create/:slug' do |slug|
1104
+ session[:last_slug] = slug
1105
+ end
1106
+ ```
1107
+
1108
+ Like routes, filters also take conditions:
1109
+
1110
+ ```ruby
1111
+ before :agent => /Songbird/ do
1112
+ # ...
1113
+ end
1114
+
1115
+ after '/blog/*', :host_name => 'example.com' do
1116
+ # ...
1117
+ end
1118
+ ```
1119
+
1120
+ ## Helpers
1121
+
1122
+ Use the top-level `helpers` method to define helper methods for use in
1123
+ route handlers and templates:
1124
+
1125
+ ```ruby
1126
+ helpers do
1127
+ def bar(name)
1128
+ "#{name}bar"
1129
+ end
1130
+ end
1131
+
1132
+ get '/:name' do
1133
+ bar(params['name'])
1134
+ end
1135
+ ```
1136
+
1137
+ Alternatively, helper methods can be separately defined in a module:
1138
+
1139
+ ```ruby
1140
+ module FooUtils
1141
+ def foo(name) "#{name}foo" end
1142
+ end
1143
+
1144
+ module BarUtils
1145
+ def bar(name) "#{name}bar" end
1146
+ end
1147
+
1148
+ helpers FooUtils, BarUtils
1149
+ ```
1150
+
1151
+ The effect is the same as including the modules in the application class.
1152
+
1153
+ ### Using Sessions
1154
+
1155
+ A session is used to keep state during requests. If activated, you have one
1156
+ session hash per user session:
1157
+
1158
+ ```ruby
1159
+ enable :sessions
1160
+
1161
+ get '/' do
1162
+ "value = " << session[:value].inspect
1163
+ end
1164
+
1165
+ get '/:value' do
1166
+ session['value'] = params['value']
1167
+ end
1168
+ ```
1169
+
1170
+ #### Session Secret Security
1171
+
1172
+ To improve security, the session data in the cookie is signed with a session
1173
+ secret using `HMAC-SHA1`. This session secret should optimally be a
1174
+ cryptographically secure random value of an appropriate length which for
1175
+ `HMAC-SHA1` is greater than or equal to 64 bytes (512 bits, 128 hex
1176
+ characters). You would be advised not to use a secret that is less than 32
1177
+ bytes of randomness (256 bits, 64 hex characters). It is therefore **very
1178
+ important** that you don't just make the secret up, but instead use a secure
1179
+ random number generator to create it. Humans are extremely bad at generating
1180
+ random values.
1181
+
1182
+ By default, a 32 byte secure random session secret is generated for you by
1183
+ Sinatra, but it will change with every restart of your application. If you
1184
+ have multiple instances of your application, and you let Sinatra generate the
1185
+ key, each instance would then have a different session key which is probably
1186
+ not what you want.
1187
+
1188
+ For better security and usability it's
1189
+ [recommended](https://12factor.net/config) that you generate a secure random
1190
+ secret and store it in an environment variable on each host running your
1191
+ application so that all of your application instances will share the same
1192
+ secret. You should periodically rotate this session secret to a new value.
1193
+ Here are some examples of how you might create a 64-byte secret and set it:
1194
+
1195
+ **Session Secret Generation**
1196
+
1197
+ ```text
1198
+ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
1199
+ 99ae8af...snip...ec0f262ac
1200
+ ```
1201
+
1202
+ **Session Secret Generation (Bonus Points)**
1203
+
1204
+ Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
1205
+ use the system RNG facilities to generate random values instead of
1206
+ userspace `OpenSSL` which MRI Ruby currently defaults to:
1207
+
1208
+ ```text
1209
+ $ gem install sysrandom
1210
+ Building native extensions. This could take a while...
1211
+ Successfully installed sysrandom-1.x
1212
+ 1 gem installed
1213
+
1214
+ $ ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
1215
+ 99ae8af...snip...ec0f262ac
1216
+ ```
1217
+
1218
+ **Session Secret Environment Variable**
1219
+
1220
+ Set a `SESSION_SECRET` environment variable for Sinatra to the value you
1221
+ generated. Make this value persistent across reboots of your host. Since the
1222
+ method for doing this will vary across systems this is for illustrative
1223
+ purposes only:
1224
+
1225
+ ```bash
1226
+ # echo "export SESSION_SECRET=99ae8af...snip...ec0f262ac" >> ~/.bashrc
1227
+ ```
1228
+
1229
+ **Session Secret App Config**
1230
+
1231
+ Set up your app config to fail-safe to a secure random secret
1232
+ if the `SESSION_SECRET` environment variable is not available.
1233
+
1234
+ For bonus points use the [sysrandom
1235
+ gem](https://github.com/cryptosphere/sysrandom#readme) here as well:
1236
+
1237
+ ```ruby
1238
+ require 'securerandom'
1239
+ # -or- require 'sysrandom/securerandom'
1240
+ set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
1241
+ ```
1242
+
1243
+ #### Session Config
1244
+
1245
+ If you want to configure it further, you may also store a hash with options
1246
+ in the `sessions` setting:
1247
+
1248
+ ```ruby
1249
+ set :sessions, :domain => 'foo.com'
1250
+ ```
1251
+
1252
+ To share your session across other apps on subdomains of foo.com, prefix the
1253
+ domain with a *.* like this instead:
1254
+
1255
+ ```ruby
1256
+ set :sessions, :domain => '.foo.com'
1257
+ ```
1258
+
1259
+ #### Choosing Your Own Session Middleware
1260
+
1261
+ Note that `enable :sessions` actually stores all data in a cookie. This
1262
+ might not always be what you want (storing lots of data will increase your
1263
+ traffic, for instance). You can use any Rack session middleware in order to
1264
+ do so, one of the following methods can be used:
1265
+
1266
+ ```ruby
1267
+ enable :sessions
1268
+ set :session_store, Rack::Session::Pool
1269
+ ```
1270
+
1271
+ Or to set up sessions with a hash of options:
1272
+
1273
+ ```ruby
1274
+ set :sessions, :expire_after => 2592000
1275
+ set :session_store, Rack::Session::Pool
1276
+ ```
1277
+
1278
+ Another option is to **not** call `enable :sessions`, but instead pull in
1279
+ your middleware of choice as you would any other middleware.
1280
+
1281
+ It is important to note that when using this method, session based
1282
+ protection **will not be enabled by default**.
1283
+
1284
+ The Rack middleware to do that will also need to be added:
1285
+
1286
+ ```ruby
1287
+ use Rack::Session::Pool, :expire_after => 2592000
1288
+ use Rack::Protection::RemoteToken
1289
+ use Rack::Protection::SessionHijacking
1290
+ ```
1291
+
1292
+ See '[Configuring attack protection](#configuring-attack-protection)' for more information.
1293
+
1294
+ ### Halting
1295
+
1296
+ To immediately stop a request within a filter or route use:
1297
+
1298
+ ```ruby
1299
+ halt
1300
+ ```
1301
+
1302
+ You can also specify the status when halting:
1303
+
1304
+ ```ruby
1305
+ halt 410
1306
+ ```
1307
+
1308
+ Or the body:
1309
+
1310
+ ```ruby
1311
+ halt 'this will be the body'
1312
+ ```
1313
+
1314
+ Or both:
1315
+
1316
+ ```ruby
1317
+ halt 401, 'go away!'
1318
+ ```
1319
+
1320
+ With headers:
1321
+
1322
+ ```ruby
1323
+ halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
1324
+ ```
1325
+
1326
+ It is of course possible to combine a template with `halt`:
1327
+
1328
+ ```ruby
1329
+ halt erb(:error)
1330
+ ```
1331
+
1332
+ ### Passing
1333
+
1334
+ A route can punt processing to the next matching route using `pass`:
1335
+
1336
+ ```ruby
1337
+ get '/guess/:who' do
1338
+ pass unless params['who'] == 'Frank'
1339
+ 'You got me!'
1340
+ end
1341
+
1342
+ get '/guess/*' do
1343
+ 'You missed!'
1344
+ end
1345
+ ```
1346
+
1347
+ The route block is immediately exited and control continues with the next
1348
+ matching route. If no matching route is found, a 404 is returned.
1349
+
1350
+ ### Triggering Another Route
1351
+
1352
+ Sometimes `pass` is not what you want, instead, you would like to get the
1353
+ result of calling another route. Simply use `call` to achieve this:
1354
+
1355
+ ```ruby
1356
+ get '/foo' do
1357
+ status, headers, body = call env.merge("PATH_INFO" => '/bar')
1358
+ [status, headers, body.map(&:upcase)]
1359
+ end
1360
+
1361
+ get '/bar' do
1362
+ "bar"
1363
+ end
1364
+ ```
1365
+
1366
+ Note that in the example above, you would ease testing and increase
1367
+ performance by simply moving `"bar"` into a helper used by both `/foo` and
1368
+ `/bar`.
1369
+
1370
+ If you want the request to be sent to the same application instance rather
1371
+ than a duplicate, use `call!` instead of `call`.
1372
+
1373
+ Check out the Rack specification if you want to learn more about `call`.
1374
+
1375
+ ### Setting Body, Status Code, and Headers
1376
+
1377
+ It is possible and recommended to set the status code and response body with
1378
+ the return value of the route block. However, in some scenarios, you might
1379
+ want to set the body at an arbitrary point in the execution flow. You can do
1380
+ so with the `body` helper method. If you do so, you can use that method from
1381
+ thereon to access the body:
1382
+
1383
+ ```ruby
1384
+ get '/foo' do
1385
+ body "bar"
1386
+ end
1387
+
1388
+ after do
1389
+ puts body
1390
+ end
1391
+ ```
1392
+
1393
+ It is also possible to pass a block to `body`, which will be executed by the
1394
+ Rack handler (this can be used to implement streaming, [see "Return Values"](#return-values)).
1395
+
1396
+ Similar to the body, you can also set the status code and headers:
1397
+
1398
+ ```ruby
1399
+ get '/foo' do
1400
+ status 418
1401
+ headers \
1402
+ "Allow" => "BREW, POST, GET, PROPFIND, WHEN",
1403
+ "Refresh" => "Refresh: 20; https://ietf.org/rfc/rfc2324.txt"
1404
+ body "I'm a teapot!"
1405
+ end
1406
+ ```
1407
+
1408
+ Like `body`, `headers` and `status` with no arguments can be used to access
1409
+ their current values.
1410
+
1411
+ ### Streaming Responses
1412
+
1413
+ Sometimes you want to start sending out data while still generating parts of
1414
+ the response body. In extreme examples, you want to keep sending data until
1415
+ the client closes the connection. You can use the `stream` helper to avoid
1416
+ creating your own wrapper:
1417
+
1418
+ ```ruby
1419
+ get '/' do
1420
+ stream do |out|
1421
+ out << "It's gonna be legen -\n"
1422
+ sleep 0.5
1423
+ out << " (wait for it) \n"
1424
+ sleep 1
1425
+ out << "- dary!\n"
1426
+ end
1427
+ end
1428
+ ```
1429
+
1430
+ This allows you to implement streaming APIs,
1431
+ [Server Sent Events](https://w3c.github.io/eventsource/), and can be used as
1432
+ the basis for [WebSockets](https://en.wikipedia.org/wiki/WebSocket). It can
1433
+ also be used to increase throughput if some but not all content depends on a
1434
+ slow resource.
1435
+
1436
+ Note that the streaming behavior, especially the number of concurrent
1437
+ requests, highly depends on the webserver used to serve the application.
1438
+ Some servers might not even support streaming at all. If the server does not
1439
+ support streaming, the body will be sent all at once after the block passed
1440
+ to `stream` finishes executing. Streaming does not work at all with Shotgun.
1441
+
1442
+ If the optional parameter is set to `keep_open`, it will not call `close` on
1443
+ the stream object, allowing you to close it at any later point in the
1444
+ execution flow. This only works on evented servers, like Rainbows.
1445
+ Other servers will still close the stream:
1446
+
1447
+ ```ruby
1448
+ # config.ru
1449
+ require 'sinatra/base'
1450
+
1451
+ class App < Sinatra::Base
1452
+ connections = []
1453
+
1454
+ get '/subscribe', provides: 'text/event-stream' do
1455
+ # register a client's interest in server events
1456
+ stream(:keep_open) do |out|
1457
+ connections << out
1458
+ # purge dead connections
1459
+ connections.reject!(&:closed?)
1460
+ end
1461
+ end
1462
+
1463
+ post '/' do
1464
+ connections.each do |out|
1465
+ # notify client that a new message has arrived
1466
+ out << "data: #{params[:msg]}\n\n"
1467
+
1468
+ # indicate client to connect again
1469
+ out.close
1470
+ end
1471
+
1472
+ 204 # response without entity body
1473
+ end
1474
+ end
1475
+
1476
+ run App
1477
+ ```
1478
+
1479
+ ```ruby
1480
+ # rainbows.conf
1481
+ Rainbows! do
1482
+ use :EventMachine
1483
+ end
1484
+ ````
1485
+
1486
+ Run:
1487
+
1488
+ ```shell
1489
+ rainbows -c rainbows.conf
1490
+ ```
1491
+
1492
+ It's also possible for the client to close the connection when trying to
1493
+ write to the socket. Because of this, it's recommended to check
1494
+ `out.closed?` before trying to write.
1495
+
1496
+ ### Logging
1497
+
1498
+ In the request scope, the `logger` helper exposes a `Logger` instance:
1499
+
1500
+ ```ruby
1501
+ get '/' do
1502
+ logger.info "loading data"
1503
+ # ...
1504
+ end
1505
+ ```
1506
+
1507
+ This logger will automatically take your Rack handler's logging settings into
1508
+ account. If logging is disabled, this method will return a dummy object, so
1509
+ you do not have to worry about it in your routes and filters.
1510
+
1511
+ Note that logging is only enabled for `Sinatra::Application` by default, so
1512
+ if you inherit from `Sinatra::Base`, you probably want to enable it yourself:
1513
+
1514
+ ```ruby
1515
+ class MyApp < Sinatra::Base
1516
+ configure :production, :development do
1517
+ enable :logging
1518
+ end
1519
+ end
1520
+ ```
1521
+
1522
+ To avoid any logging middleware to be set up, set the `logging` option to
1523
+ `nil`. However, keep in mind that `logger` will in that case return `nil`. A
1524
+ common use case is when you want to set your own logger. Sinatra will use
1525
+ whatever it will find in `env['rack.logger']`.
1526
+
1527
+ ### Mime Types
1528
+
1529
+ When using `send_file` or static files you may have mime types Sinatra
1530
+ doesn't understand. Use `mime_type` to register them by file extension:
1531
+
1532
+ ```ruby
1533
+ configure do
1534
+ mime_type :foo, 'text/foo'
1535
+ end
1536
+ ```
1537
+
1538
+ You can also use it with the `content_type` helper:
1539
+
1540
+ ```ruby
1541
+ get '/' do
1542
+ content_type :foo
1543
+ "foo foo foo"
1544
+ end
1545
+ ```
1546
+
1547
+ ### Generating URLs
1548
+
1549
+ For generating URLs you should use the `url` helper method, for instance, in
1550
+ Haml:
1551
+
1552
+ ```ruby
1553
+ %a{:href => url('/foo')} foo
1554
+ ```
1555
+
1556
+ It takes reverse proxies and Rack routers into account - if present.
1557
+
1558
+ This method is also aliased to `to` (see [below](#browser-redirect) for an example).
1559
+
1560
+ ### Browser Redirect
1561
+
1562
+ You can trigger a browser redirect with the `redirect` helper method:
1563
+
1564
+ ```ruby
1565
+ get '/foo' do
1566
+ redirect to('/bar')
1567
+ end
1568
+ ```
1569
+
1570
+ Any additional parameters are handled like arguments passed to `halt`:
1571
+
1572
+ ```ruby
1573
+ redirect to('/bar'), 303
1574
+ redirect 'http://www.google.com/', 'wrong place, buddy'
1575
+ ```
1576
+
1577
+ You can also easily redirect back to the page the user came from with
1578
+ `redirect back`:
1579
+
1580
+ ```ruby
1581
+ get '/foo' do
1582
+ "<a href='/bar'>do something</a>"
1583
+ end
1584
+
1585
+ get '/bar' do
1586
+ do_something
1587
+ redirect back
1588
+ end
1589
+ ```
1590
+
1591
+ To pass arguments with a redirect, either add them to the query:
1592
+
1593
+ ```ruby
1594
+ redirect to('/bar?sum=42')
1595
+ ```
1596
+
1597
+ Or use a session:
1598
+
1599
+ ```ruby
1600
+ enable :sessions
1601
+
1602
+ get '/foo' do
1603
+ session[:secret] = 'foo'
1604
+ redirect to('/bar')
1605
+ end
1606
+
1607
+ get '/bar' do
1608
+ session[:secret]
1609
+ end
1610
+ ```
1611
+
1612
+ ### Cache Control
1613
+
1614
+ Setting your headers correctly is the foundation for proper HTTP caching.
1615
+
1616
+ You can easily set the Cache-Control header like this:
1617
+
1618
+ ```ruby
1619
+ get '/' do
1620
+ cache_control :public
1621
+ "cache it!"
1622
+ end
1623
+ ```
1624
+
1625
+ Pro tip: Set up caching in a before filter:
1626
+
1627
+ ```ruby
1628
+ before do
1629
+ cache_control :public, :must_revalidate, :max_age => 60
1630
+ end
1631
+ ```
1632
+
1633
+ If you are using the `expires` helper to set the corresponding header,
1634
+ `Cache-Control` will be set automatically for you:
1635
+
1636
+ ```ruby
1637
+ before do
1638
+ expires 500, :public, :must_revalidate
1639
+ end
1640
+ ```
1641
+
1642
+ To properly use caches, you should consider using `etag` or `last_modified`.
1643
+ It is recommended to call those helpers *before* doing any heavy lifting, as
1644
+ they will immediately flush a response if the client already has the current
1645
+ version in its cache:
1646
+
1647
+ ```ruby
1648
+ get "/article/:id" do
1649
+ @article = Article.find params['id']
1650
+ last_modified @article.updated_at
1651
+ etag @article.sha1
1652
+ erb :article
1653
+ end
1654
+ ```
1655
+
1656
+ It is also possible to use a
1657
+ [weak ETag](https://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation):
1658
+
1659
+ ```ruby
1660
+ etag @article.sha1, :weak
1661
+ ```
1662
+
1663
+ These helpers will not do any caching for you, but rather feed the necessary
1664
+ information to your cache. If you are looking for a quick
1665
+ reverse-proxy caching solution, try
1666
+ [rack-cache](https://github.com/rtomayko/rack-cache#readme):
1667
+
1668
+ ```ruby
1669
+ require "rack/cache"
1670
+ require "sinatra"
1671
+
1672
+ use Rack::Cache
1673
+
1674
+ get '/' do
1675
+ cache_control :public, :max_age => 36000
1676
+ sleep 5
1677
+ "hello"
1678
+ end
1679
+ ```
1680
+
1681
+ Use the `:static_cache_control` setting (see [below](#cache-control)) to add
1682
+ `Cache-Control` header info to static files.
1683
+
1684
+ According to RFC 2616, your application should behave differently if the
1685
+ If-Match or If-None-Match header is set to `*`, depending on whether the
1686
+ resource requested is already in existence. Sinatra assumes resources for
1687
+ safe (like get) and idempotent (like put) requests are already in existence,
1688
+ whereas other resources (for instance post requests) are treated as new
1689
+ resources. You can change this behavior by passing in a `:new_resource`
1690
+ option:
1691
+
1692
+ ```ruby
1693
+ get '/create' do
1694
+ etag '', :new_resource => true
1695
+ Article.create
1696
+ erb :new_article
1697
+ end
1698
+ ```
1699
+
1700
+ If you still want to use a weak ETag, pass in a `:kind` option:
1701
+
1702
+ ```ruby
1703
+ etag '', :new_resource => true, :kind => :weak
1704
+ ```
1705
+
1706
+ ### Sending Files
1707
+
1708
+ To return the contents of a file as the response, you can use the `send_file`
1709
+ helper method:
1710
+
1711
+ ```ruby
1712
+ get '/' do
1713
+ send_file 'foo.png'
1714
+ end
1715
+ ```
1716
+
1717
+ It also takes options:
1718
+
1719
+ ```ruby
1720
+ send_file 'foo.png', :type => :jpg
1721
+ ```
1722
+
1723
+ The options are:
1724
+
1725
+ <dl>
1726
+ <dt>filename</dt>
1727
+ <dd>File name to be used in the response,
1728
+ defaults to the real file name.</dd>
1729
+ <dt>last_modified</dt>
1730
+ <dd>Value for Last-Modified header, defaults to the file's mtime.</dd>
1731
+
1732
+ <dt>type</dt>
1733
+ <dd>Value for Content-Type header, guessed from the file extension if
1734
+ missing.</dd>
1735
+
1736
+ <dt>disposition</dt>
1737
+ <dd>
1738
+ Value for Content-Disposition header, possible values: <tt>nil</tt>
1739
+ (default), <tt>:attachment</tt> and <tt>:inline</tt>
1740
+ </dd>
1741
+
1742
+ <dt>length</dt>
1743
+ <dd>Value for Content-Length header, defaults to file size.</dd>
1744
+
1745
+ <dt>status</dt>
1746
+ <dd>
1747
+ Status code to be sent. Useful when sending a static file as an error
1748
+ page. If supported by the Rack handler, other means than streaming
1749
+ from the Ruby process will be used. If you use this helper method,
1750
+ Sinatra will automatically handle range requests.
1751
+ </dd>
1752
+ </dl>
1753
+
1754
+ ### Accessing the Request Object
1755
+
1756
+ The incoming request object can be accessed from request level (filter,
1757
+ routes, error handlers) through the `request` method:
1758
+
1759
+ ```ruby
1760
+ # app running on http://example.com/example
1761
+ get '/foo' do
1762
+ t = %w[text/css text/html application/javascript]
1763
+ request.accept # ['text/html', '*/*']
1764
+ request.accept? 'text/xml' # true
1765
+ request.preferred_type(t) # 'text/html'
1766
+ request.body # request body sent by the client (see below)
1767
+ request.scheme # "http"
1768
+ request.script_name # "/example"
1769
+ request.path_info # "/foo"
1770
+ request.port # 80
1771
+ request.request_method # "GET"
1772
+ request.query_string # ""
1773
+ request.content_length # length of request.body
1774
+ request.media_type # media type of request.body
1775
+ request.host # "example.com"
1776
+ request.get? # true (similar methods for other verbs)
1777
+ request.form_data? # false
1778
+ request["some_param"] # value of some_param parameter. [] is a shortcut to the params hash.
1779
+ request.referrer # the referrer of the client or '/'
1780
+ request.user_agent # user agent (used by :agent condition)
1781
+ request.cookies # hash of browser cookies
1782
+ request.xhr? # is this an ajax request?
1783
+ request.url # "http://example.com/example/foo"
1784
+ request.path # "/example/foo"
1785
+ request.ip # client IP address
1786
+ request.secure? # false (would be true over ssl)
1787
+ request.forwarded? # true (if running behind a reverse proxy)
1788
+ request.env # raw env hash handed in by Rack
1789
+ end
1790
+ ```
1791
+
1792
+ Some options, like `script_name` or `path_info`, can also be written:
1793
+
1794
+ ```ruby
1795
+ before { request.path_info = "/" }
1796
+
1797
+ get "/" do
1798
+ "all requests end up here"
1799
+ end
1800
+ ```
1801
+
1802
+ The `request.body` is an IO or StringIO object:
1803
+
1804
+ ```ruby
1805
+ post "/api" do
1806
+ request.body.rewind # in case someone already read it
1807
+ data = JSON.parse request.body.read
1808
+ "Hello #{data['name']}!"
1809
+ end
1810
+ ```
1811
+
1812
+ ### Attachments
1813
+
1814
+ You can use the `attachment` helper to tell the browser the response should
1815
+ be stored on disk rather than displayed in the browser:
1816
+
1817
+ ```ruby
1818
+ get '/' do
1819
+ attachment
1820
+ "store it!"
1821
+ end
1822
+ ```
1823
+
1824
+ You can also pass it a file name:
1825
+
1826
+ ```ruby
1827
+ get '/' do
1828
+ attachment "info.txt"
1829
+ "store it!"
1830
+ end
1831
+ ```
1832
+
1833
+ ### Dealing with Date and Time
1834
+
1835
+ Sinatra offers a `time_for` helper method that generates a Time object from
1836
+ the given value. It is also able to convert `DateTime`, `Date` and similar
1837
+ classes:
1838
+
1839
+ ```ruby
1840
+ get '/' do
1841
+ pass if Time.now > time_for('Dec 23, 2016')
1842
+ "still time"
1843
+ end
1844
+ ```
1845
+
1846
+ This method is used internally by `expires`, `last_modified` and akin. You
1847
+ can therefore easily extend the behavior of those methods by overriding
1848
+ `time_for` in your application:
1849
+
1850
+ ```ruby
1851
+ helpers do
1852
+ def time_for(value)
1853
+ case value
1854
+ when :yesterday then Time.now - 24*60*60
1855
+ when :tomorrow then Time.now + 24*60*60
1856
+ else super
1857
+ end
1858
+ end
1859
+ end
1860
+
1861
+ get '/' do
1862
+ last_modified :yesterday
1863
+ expires :tomorrow
1864
+ "hello"
1865
+ end
1866
+ ```
1867
+
1868
+ ### Looking Up Template Files
1869
+
1870
+ The `find_template` helper is used to find template files for rendering:
1871
+
1872
+ ```ruby
1873
+ find_template settings.views, 'foo', Tilt[:haml] do |file|
1874
+ puts "could be #{file}"
1875
+ end
1876
+ ```
1877
+
1878
+ This is not really useful. But it is useful that you can actually override
1879
+ this method to hook in your own lookup mechanism. For instance, if you want
1880
+ to be able to use more than one view directory:
1881
+
1882
+ ```ruby
1883
+ set :views, ['views', 'templates']
1884
+
1885
+ helpers do
1886
+ def find_template(views, name, engine, &block)
1887
+ Array(views).each { |v| super(v, name, engine, &block) }
1888
+ end
1889
+ end
1890
+ ```
1891
+
1892
+ Another example would be using different directories for different engines:
1893
+
1894
+ ```ruby
1895
+ set :views, :haml => 'templates', :default => 'views'
1896
+
1897
+ helpers do
1898
+ def find_template(views, name, engine, &block)
1899
+ _, folder = views.detect { |k,v| engine == Tilt[k] }
1900
+ folder ||= views[:default]
1901
+ super(folder, name, engine, &block)
1902
+ end
1903
+ end
1904
+ ```
1905
+
1906
+ You can also easily wrap this up in an extension and share it with others!
1907
+
1908
+ Note that `find_template` does not check if the file really exists but
1909
+ rather calls the given block for all possible paths. This is not a
1910
+ performance issue, since `render` will use `break` as soon as a file is
1911
+ found. Also, template locations (and content) will be cached if you are not
1912
+ running in development mode. You should keep that in mind if you write a
1913
+ really crazy method.
1914
+
1915
+ ## Configuration
1916
+
1917
+ Run once, at startup, in any environment:
1918
+
1919
+ ```ruby
1920
+ configure do
1921
+ # setting one option
1922
+ set :option, 'value'
1923
+
1924
+ # setting multiple options
1925
+ set :a => 1, :b => 2
1926
+
1927
+ # same as `set :option, true`
1928
+ enable :option
1929
+
1930
+ # same as `set :option, false`
1931
+ disable :option
1932
+
1933
+ # you can also have dynamic settings with blocks
1934
+ set(:css_dir) { File.join(views, 'css') }
1935
+ end
1936
+ ```
1937
+
1938
+ Run only when the environment (`APP_ENV` environment variable) is set to
1939
+ `:production`:
1940
+
1941
+ ```ruby
1942
+ configure :production do
1943
+ ...
1944
+ end
1945
+ ```
1946
+
1947
+ Run when the environment is set to either `:production` or `:test`:
1948
+
1949
+ ```ruby
1950
+ configure :production, :test do
1951
+ ...
1952
+ end
1953
+ ```
1954
+
1955
+ You can access those options via `settings`:
1956
+
1957
+ ```ruby
1958
+ configure do
1959
+ set :foo, 'bar'
1960
+ end
1961
+
1962
+ get '/' do
1963
+ settings.foo? # => true
1964
+ settings.foo # => 'bar'
1965
+ ...
1966
+ end
1967
+ ```
1968
+
1969
+ ### Configuring attack protection
1970
+
1971
+ Sinatra is using
1972
+ [Rack::Protection](https://github.com/sinatra/sinatra/tree/main/rack-protection#readme) to
1973
+ defend your application against common, opportunistic attacks. You can
1974
+ easily disable this behavior (which will open up your application to tons
1975
+ of common vulnerabilities):
1976
+
1977
+ ```ruby
1978
+ disable :protection
1979
+ ```
1980
+
1981
+ To skip a single defense layer, set `protection` to an options hash:
1982
+
1983
+ ```ruby
1984
+ set :protection, :except => :path_traversal
1985
+ ```
1986
+ You can also hand in an array in order to disable a list of protections:
1987
+
1988
+ ```ruby
1989
+ set :protection, :except => [:path_traversal, :session_hijacking]
1990
+ ```
1991
+
1992
+ By default, Sinatra will only set up session based protection if `:sessions`
1993
+ have been enabled. See '[Using Sessions](#using-sessions)'. Sometimes you may want to set up
1994
+ sessions "outside" of the Sinatra app, such as in the config.ru or with a
1995
+ separate `Rack::Builder` instance. In that case, you can still set up session
1996
+ based protection by passing the `:session` option:
1997
+
1998
+ ```ruby
1999
+ set :protection, :session => true
2000
+ ```
2001
+
2002
+ ### Available Settings
2003
+
2004
+ <dl>
2005
+ <dt>absolute_redirects</dt>
2006
+ <dd>
2007
+ If disabled, Sinatra will allow relative redirects, however, Sinatra
2008
+ will no longer conform with RFC 2616 (HTTP 1.1), which only allows
2009
+ absolute redirects.
2010
+ </dd>
2011
+ <dd>
2012
+ Enable if your app is running behind a reverse proxy that has not been
2013
+ set up properly. Note that the <tt>url</tt> helper will still produce
2014
+ absolute URLs, unless you pass in <tt>false</tt> as the second
2015
+ parameter.
2016
+ </dd>
2017
+ <dd>Disabled by default.</dd>
2018
+
2019
+ <dt>add_charset</dt>
2020
+ <dd>
2021
+ Mime types the <tt>content_type</tt> helper will automatically add the
2022
+ charset info to. You should add to it rather than overriding this
2023
+ option: <tt>settings.add_charset << "application/foobar"</tt>
2024
+ </dd>
2025
+
2026
+ <dt>app_file</dt>
2027
+ <dd>
2028
+ Path to the main application file, used to detect project root, views
2029
+ and public folder and inline templates.
2030
+ </dd>
2031
+
2032
+ <dt>bind</dt>
2033
+ <dd>
2034
+ IP address to bind to (default: <tt>0.0.0.0</tt> <em>or</em>
2035
+ <tt>localhost</tt> if your `environment` is set to development). Only
2036
+ used for built-in server.
2037
+ </dd>
2038
+
2039
+ <dt>default_content_type</dt>
2040
+ <dd>
2041
+ Content-Type to assume if unknown (defaults to <tt>"text/html"</tt>). Set
2042
+ to <tt>nil</tt> to not set a default Content-Type on every response; when
2043
+ configured so, you must set the Content-Type manually when emitting content
2044
+ or the user-agent will have to sniff it (or, if <tt>nosniff</tt> is enabled
2045
+ in Rack::Protection::XSSHeader, assume <tt>application/octet-stream</tt>).
2046
+ </dd>
2047
+
2048
+ <dt>default_encoding</dt>
2049
+ <dd>Encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
2050
+
2051
+ <dt>dump_errors</dt>
2052
+ <dd>Display errors in the log. Enabled by default unless environment is "test".</dd>
2053
+
2054
+ <dt>environment</dt>
2055
+ <dd>
2056
+ Current environment. Defaults to <tt>ENV['APP_ENV']</tt>, or
2057
+ <tt>"development"</tt> if not available.
2058
+ </dd>
2059
+
2060
+ <dt>logging</dt>
2061
+ <dd>Use the logger.</dd>
2062
+
2063
+ <dt>lock</dt>
2064
+ <dd>
2065
+ Places a lock around every request, only running processing on request
2066
+ per Ruby process concurrently.
2067
+ </dd>
2068
+ <dd>Enabled if your app is not thread-safe. Disabled by default.</dd>
2069
+
2070
+ <dt>method_override</dt>
2071
+ <dd>
2072
+ Use <tt>_method</tt> magic to allow put/delete forms in browsers that
2073
+ don't support it.
2074
+ </dd>
2075
+
2076
+ <dt>mustermann_opts</dt>
2077
+ <dd>
2078
+ A default hash of options to pass to Mustermann.new when compiling routing
2079
+ paths.
2080
+ </dd>
2081
+
2082
+ <dt>port</dt>
2083
+ <dd>Port to listen on. Only used for built-in server.</dd>
2084
+
2085
+ <dt>prefixed_redirects</dt>
2086
+ <dd>
2087
+ Whether or not to insert <tt>request.script_name</tt> into redirects
2088
+ if no absolute path is given. That way <tt>redirect '/foo'</tt> would
2089
+ behave like <tt>redirect to('/foo')</tt>. Disabled by default.
2090
+ </dd>
2091
+
2092
+ <dt>protection</dt>
2093
+ <dd>
2094
+ Whether or not to enable web attack protections. See protection section
2095
+ above.
2096
+ </dd>
2097
+
2098
+ <dt>public_dir</dt>
2099
+ <dd>Alias for <tt>public_folder</tt>. See below.</dd>
2100
+
2101
+ <dt>public_folder</dt>
2102
+ <dd>
2103
+ Path to the folder public files are served from. Only used if static
2104
+ file serving is enabled (see <tt>static</tt> setting below). Inferred
2105
+ from <tt>app_file</tt> setting if not set.
2106
+ </dd>
2107
+
2108
+ <dt>quiet</dt>
2109
+ <dd>
2110
+ Disables logs generated by Sinatra's start and stop commands.
2111
+ <tt>false</tt> by default.
2112
+ </dd>
2113
+
2114
+ <dt>reload_templates</dt>
2115
+ <dd>
2116
+ Whether or not to reload templates between requests. Enabled in
2117
+ development mode.
2118
+ </dd>
2119
+
2120
+ <dt>root</dt>
2121
+ <dd>
2122
+ Path to project root folder. Inferred from <tt>app_file</tt> setting
2123
+ if not set.
2124
+ </dd>
2125
+
2126
+ <dt>raise_errors</dt>
2127
+ <dd>
2128
+ Raise unhandled errors (will stop application). Enabled by default when
2129
+ <tt>environment</tt> is set to <tt>"test"</tt>, disabled otherwise.
2130
+ </dd>
2131
+ <dd>
2132
+ Any explicitly defined error handlers always override this setting. See
2133
+ the "Error" section below.
2134
+ </dd>
2135
+
2136
+ <dt>run</dt>
2137
+ <dd>
2138
+ If enabled, Sinatra will handle starting the web server. Do not
2139
+ enable if using rackup or other means.
2140
+ </dd>
2141
+
2142
+ <dt>running</dt>
2143
+ <dd>Is the built-in server running now? Do not change this setting!</dd>
2144
+
2145
+ <dt>server</dt>
2146
+ <dd>
2147
+ Server or list of servers to use for built-in server. Order indicates
2148
+ priority, default depends on Ruby implementation.
2149
+ </dd>
2150
+
2151
+ <dt>server_settings</dt>
2152
+ <dd>
2153
+ If you are using a WEBrick web server, presumably for your development
2154
+ environment, you can pass a hash of options to <tt>server_settings</tt>,
2155
+ such as <tt>SSLEnable</tt> or <tt>SSLVerifyClient</tt>. However, web
2156
+ servers such as Puma do not support this, so you can set
2157
+ <tt>server_settings</tt> by defining it as a method when you call
2158
+ <tt>configure</tt>.
2159
+ </dd>
2160
+
2161
+ <dt>sessions</dt>
2162
+ <dd>
2163
+ Enable cookie-based sessions support using
2164
+ <tt>Rack::Session::Cookie</tt>. See 'Using Sessions' section for more
2165
+ information.
2166
+ </dd>
2167
+
2168
+ <dt>session_store</dt>
2169
+ <dd>
2170
+ The Rack session middleware used. Defaults to
2171
+ <tt>Rack::Session::Cookie</tt>. See 'Using Sessions' section for more
2172
+ information.
2173
+ </dd>
2174
+
2175
+ <dt>show_exceptions</dt>
2176
+ <dd>
2177
+ Show a stack trace in the browser when an exception happens. Enabled by
2178
+ default when <tt>environment</tt> is set to <tt>"development"</tt>,
2179
+ disabled otherwise.
2180
+ </dd>
2181
+ <dd>
2182
+ Can also be set to <tt>:after_handler</tt> to trigger app-specified
2183
+ error handling before showing a stack trace in the browser.
2184
+ </dd>
2185
+
2186
+ <dt>static</dt>
2187
+ <dd>Whether Sinatra should handle serving static files.</dd>
2188
+ <dd>Disable when using a server able to do this on its own.</dd>
2189
+ <dd>Disabling will boost performance.</dd>
2190
+ <dd>
2191
+ Enabled by default in classic style, disabled for modular apps.
2192
+ </dd>
2193
+
2194
+ <dt>static_cache_control</dt>
2195
+ <dd>
2196
+ When Sinatra is serving static files, set this to add
2197
+ <tt>Cache-Control</tt> headers to the responses. Uses the
2198
+ <tt>cache_control</tt> helper. Disabled by default.
2199
+ </dd>
2200
+ <dd>
2201
+ Use an explicit array when setting multiple values:
2202
+ <tt>set :static_cache_control, [:public, :max_age => 300]</tt>
2203
+ </dd>
2204
+
2205
+ <dt>threaded</dt>
2206
+ <dd>
2207
+ If set to <tt>true</tt>, will tell server to use
2208
+ <tt>EventMachine.defer</tt> for processing the request.
2209
+ </dd>
2210
+
2211
+ <dt>traps</dt>
2212
+ <dd>Whether Sinatra should handle system signals.</dd>
2213
+
2214
+ <dt>views</dt>
2215
+ <dd>
2216
+ Path to the views folder. Inferred from <tt>app_file</tt> setting if
2217
+ not set.
2218
+ </dd>
2219
+
2220
+ <dt>x_cascade</dt>
2221
+ <dd>
2222
+ Whether or not to set the X-Cascade header if no route matches.
2223
+ Defaults to <tt>true</tt>.
2224
+ </dd>
2225
+ </dl>
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
+
2245
+ ## Environments
2246
+
2247
+ There are three predefined `environments`: `"development"`,
2248
+ `"production"` and `"test"`. Environments can be set through the
2249
+ `APP_ENV` environment variable. The default value is `"development"`.
2250
+ In the `"development"` environment all templates are reloaded between
2251
+ requests, and special `not_found` and `error` handlers display stack
2252
+ traces in your browser. In the `"production"` and `"test"` environments,
2253
+ templates are cached by default.
2254
+
2255
+ To run different environments, set the `APP_ENV` environment variable:
2256
+
2257
+ ```shell
2258
+ APP_ENV=production ruby my_app.rb
2259
+ ```
2260
+
2261
+ You can use predefined methods: `development?`, `test?` and `production?` to
2262
+ check the current environment setting:
2263
+
2264
+ ```ruby
2265
+ get '/' do
2266
+ if settings.development?
2267
+ "development!"
2268
+ else
2269
+ "not development!"
2270
+ end
2271
+ end
2272
+ ```
2273
+
2274
+ ## Error Handling
2275
+
2276
+ Error handlers run within the same context as routes and before filters,
2277
+ which means you get all the goodies it has to offer, like `haml`, `erb`,
2278
+ `halt`, etc.
2279
+
2280
+ ### Not Found
2281
+
2282
+ When a `Sinatra::NotFound` exception is raised, or the response's status
2283
+ code is 404, the `not_found` handler is invoked:
2284
+
2285
+ ```ruby
2286
+ not_found do
2287
+ 'This is nowhere to be found.'
2288
+ end
2289
+ ```
2290
+
2291
+ ### Error
2292
+
2293
+ The `error` handler is invoked any time an exception is raised from a route
2294
+ block or a filter. But note in development it will only run if you set the
2295
+ show exceptions option to `:after_handler`:
2296
+
2297
+ ```ruby
2298
+ set :show_exceptions, :after_handler
2299
+ ```
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
+
2309
+ The exception object can be obtained from the `sinatra.error` Rack variable:
2310
+
2311
+ ```ruby
2312
+ error do
2313
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].message
2314
+ end
2315
+ ```
2316
+
2317
+ Pass an error class as an argument to create handlers for custom errors:
2318
+
2319
+ ```ruby
2320
+ error MyCustomError do
2321
+ 'So what happened was...' + env['sinatra.error'].message
2322
+ end
2323
+ ```
2324
+
2325
+ Then, if this happens:
2326
+
2327
+ ```ruby
2328
+ get '/' do
2329
+ raise MyCustomError, 'something bad'
2330
+ end
2331
+ ```
2332
+
2333
+ You get this:
2334
+
2335
+ ```
2336
+ So what happened was... something bad
2337
+ ```
2338
+
2339
+ Alternatively, you can install an error handler for a status code:
2340
+
2341
+ ```ruby
2342
+ error 403 do
2343
+ 'Access forbidden'
2344
+ end
2345
+
2346
+ get '/secret' do
2347
+ 403
2348
+ end
2349
+ ```
2350
+
2351
+ Or a range:
2352
+
2353
+ ```ruby
2354
+ error 400..510 do
2355
+ 'Boom'
2356
+ end
2357
+ ```
2358
+
2359
+ Sinatra installs special `not_found` and `error` handlers when
2360
+ running under the development environment to display nice stack traces
2361
+ and additional debugging information in your browser.
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
+
2408
+ ## Rack Middleware
2409
+
2410
+ Sinatra rides on [Rack](https://rack.github.io/), a minimal standard
2411
+ interface for Ruby web frameworks. One of Rack's most interesting
2412
+ capabilities for application developers is support for "middleware" --
2413
+ components that sit between the server and your application monitoring
2414
+ and/or manipulating the HTTP request/response to provide various types
2415
+ of common functionality.
2416
+
2417
+ Sinatra makes building Rack middleware pipelines a cinch via a top-level
2418
+ `use` method:
2419
+
2420
+ ```ruby
2421
+ require 'sinatra'
2422
+ require 'my_custom_middleware'
2423
+
2424
+ use Rack::Lint
2425
+ use MyCustomMiddleware
2426
+
2427
+ get '/hello' do
2428
+ 'Hello World'
2429
+ end
2430
+ ```
2431
+
2432
+ The semantics of `use` are identical to those defined for the
2433
+ [Rack::Builder](https://www.rubydoc.info/github/rack/rack/main/Rack/Builder) DSL
2434
+ (most frequently used from rackup files). For example, the `use` method
2435
+ accepts multiple/variable args as well as blocks:
2436
+
2437
+ ```ruby
2438
+ use Rack::Auth::Basic do |username, password|
2439
+ username == 'admin' && password == 'secret'
2440
+ end
2441
+ ```
2442
+
2443
+ Rack is distributed with a variety of standard middleware for logging,
2444
+ debugging, URL routing, authentication, and session handling. Sinatra uses
2445
+ many of these components automatically based on configuration so you
2446
+ typically don't have to `use` them explicitly.
2447
+
2448
+ You can find useful middleware in
2449
+ [rack](https://github.com/rack/rack/tree/main/lib/rack),
2450
+ [rack-contrib](https://github.com/rack/rack-contrib#readme),
2451
+ or in the [Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware).
2452
+
2453
+ ## Testing
2454
+
2455
+ Sinatra tests can be written using any Rack-based testing library or
2456
+ framework.
2457
+ [Rack::Test](https://www.rubydoc.info/github/rack/rack-test/main/frames)
2458
+ is recommended:
2459
+
2460
+ ```ruby
2461
+ require 'my_sinatra_app'
2462
+ require 'minitest/autorun'
2463
+ require 'rack/test'
2464
+
2465
+ class MyAppTest < Minitest::Test
2466
+ include Rack::Test::Methods
2467
+
2468
+ def app
2469
+ Sinatra::Application
2470
+ end
2471
+
2472
+ def test_my_default
2473
+ get '/'
2474
+ assert_equal 'Hello World!', last_response.body
2475
+ end
2476
+
2477
+ def test_with_params
2478
+ get '/meet', :name => 'Frank'
2479
+ assert_equal 'Hello Frank!', last_response.body
2480
+ end
2481
+
2482
+ def test_with_user_agent
2483
+ get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
2484
+ assert_equal "You're using Songbird!", last_response.body
2485
+ end
2486
+ end
2487
+ ```
2488
+
2489
+ Note: If you are using Sinatra in the modular style, replace
2490
+ `Sinatra::Application` above with the class name of your app.
2491
+
2492
+ ## Sinatra::Base - Middleware, Libraries, and Modular Apps
2493
+
2494
+ Defining your app at the top-level works well for micro-apps but has
2495
+ considerable drawbacks when building reusable components such as Rack
2496
+ middleware, Rails metal, simple libraries with a server component, or even
2497
+ Sinatra extensions. The top-level assumes a micro-app style configuration
2498
+ (e.g., a single application file, `./public` and `./views`
2499
+ directories, logging, exception detail page, etc.). That's where
2500
+ `Sinatra::Base` comes into play:
2501
+
2502
+ ```ruby
2503
+ require 'sinatra/base'
2504
+
2505
+ class MyApp < Sinatra::Base
2506
+ set :sessions, true
2507
+ set :foo, 'bar'
2508
+
2509
+ get '/' do
2510
+ 'Hello world!'
2511
+ end
2512
+ end
2513
+ ```
2514
+
2515
+ The methods available to `Sinatra::Base` subclasses are exactly the same
2516
+ as those available via the top-level DSL. Most top-level apps can be
2517
+ converted to `Sinatra::Base` components with two modifications:
2518
+
2519
+ * Your file should require `sinatra/base` instead of `sinatra`;
2520
+ otherwise, all of Sinatra's DSL methods are imported into the main
2521
+ namespace.
2522
+ * Put your app's routes, error handlers, filters, and options in a subclass
2523
+ of `Sinatra::Base`.
2524
+
2525
+ `Sinatra::Base` is a blank slate. Most options are disabled by default,
2526
+ including the built-in server. See [Configuring
2527
+ Settings](http://www.sinatrarb.com/configuration.html) for details on
2528
+ available options and their behavior. If you want behavior more similar
2529
+ to when you define your app at the top level (also known as Classic
2530
+ style), you can subclass `Sinatra::Application`:
2531
+
2532
+ ```ruby
2533
+ require 'sinatra/base'
2534
+
2535
+ class MyApp < Sinatra::Application
2536
+ get '/' do
2537
+ 'Hello world!'
2538
+ end
2539
+ end
2540
+ ```
2541
+
2542
+ ### Modular vs. Classic Style
2543
+
2544
+ Contrary to common belief, there is nothing wrong with the classic
2545
+ style. If it suits your application, you do not have to switch to a
2546
+ modular application.
2547
+
2548
+ The main disadvantage of using the classic style rather than the modular
2549
+ style is that you will only have one Sinatra application per Ruby
2550
+ process. If you plan to use more than one, switch to the modular style.
2551
+ There is no reason you cannot mix the modular and classic styles.
2552
+
2553
+ If switching from one style to the other, you should be aware of
2554
+ slightly different default settings:
2555
+
2556
+ <table>
2557
+ <tr>
2558
+ <th>Setting</th>
2559
+ <th>Classic</th>
2560
+ <th>Modular</th>
2561
+ <th>Modular</th>
2562
+ </tr>
2563
+
2564
+ <tr>
2565
+ <td>app_file</td>
2566
+ <td>file loading sinatra</td>
2567
+ <td>file subclassing Sinatra::Base</td>
2568
+ <td>file subclassing Sinatra::Application</td>
2569
+ </tr>
2570
+
2571
+ <tr>
2572
+ <td>run</td>
2573
+ <td>$0 == app_file</td>
2574
+ <td>false</td>
2575
+ <td>false</td>
2576
+ </tr>
2577
+
2578
+ <tr>
2579
+ <td>logging</td>
2580
+ <td>true</td>
2581
+ <td>false</td>
2582
+ <td>true</td>
2583
+ </tr>
2584
+
2585
+ <tr>
2586
+ <td>method_override</td>
2587
+ <td>true</td>
2588
+ <td>false</td>
2589
+ <td>true</td>
2590
+ </tr>
2591
+
2592
+ <tr>
2593
+ <td>inline_templates</td>
2594
+ <td>true</td>
2595
+ <td>false</td>
2596
+ <td>true</td>
2597
+ </tr>
2598
+
2599
+ <tr>
2600
+ <td>static</td>
2601
+ <td>true</td>
2602
+ <td>File.exist?(public_folder)</td>
2603
+ <td>true</td>
2604
+ </tr>
2605
+ </table>
2606
+
2607
+ ### Serving a Modular Application
2608
+
2609
+ There are two common options for starting a modular app, actively
2610
+ starting with `run!`:
2611
+
2612
+ ```ruby
2613
+ # my_app.rb
2614
+ require 'sinatra/base'
2615
+
2616
+ class MyApp < Sinatra::Base
2617
+ # ... app code here ...
2618
+
2619
+ # start the server if ruby file executed directly
2620
+ run! if app_file == $0
2621
+ end
2622
+ ```
2623
+
2624
+ Start with:
2625
+
2626
+ ```shell
2627
+ ruby my_app.rb
2628
+ ```
2629
+
2630
+ Or with a `config.ru` file, which allows using any Rack handler:
2631
+
2632
+ ```ruby
2633
+ # config.ru (run with rackup)
2634
+ require './my_app'
2635
+ run MyApp
2636
+ ```
2637
+
2638
+ Run:
2639
+
2640
+ ```shell
2641
+ rackup -p 4567
2642
+ ```
2643
+
2644
+ ### Using a Classic Style Application with a config.ru
2645
+
2646
+ Write your app file:
2647
+
2648
+ ```ruby
2649
+ # app.rb
2650
+ require 'sinatra'
2651
+
2652
+ get '/' do
2653
+ 'Hello world!'
2654
+ end
2655
+ ```
2656
+
2657
+ And a corresponding `config.ru`:
2658
+
2659
+ ```ruby
2660
+ require './app'
2661
+ run Sinatra::Application
2662
+ ```
2663
+
2664
+ ### When to use a config.ru?
2665
+
2666
+ A `config.ru` file is recommended if:
2667
+
2668
+ * You want to deploy with a different Rack handler (Passenger, Unicorn,
2669
+ Heroku, ...).
2670
+ * You want to use more than one subclass of `Sinatra::Base`.
2671
+ * You want to use Sinatra only for middleware, and not as an endpoint.
2672
+
2673
+ **There is no need to switch to a `config.ru` simply because you
2674
+ switched to the modular style, and you don't have to use the modular
2675
+ style for running with a `config.ru`.**
2676
+
2677
+ ### Using Sinatra as Middleware
2678
+
2679
+ Not only is Sinatra able to use other Rack middleware, any Sinatra
2680
+ application can, in turn, be added in front of any Rack endpoint as
2681
+ middleware itself. This endpoint could be another Sinatra application,
2682
+ or any other Rack-based application (Rails/Hanami/Roda/...):
2683
+
2684
+ ```ruby
2685
+ require 'sinatra/base'
2686
+
2687
+ class LoginScreen < Sinatra::Base
2688
+ enable :sessions
2689
+
2690
+ get('/login') { haml :login }
2691
+
2692
+ post('/login') do
2693
+ if params['name'] == 'admin' && params['password'] == 'admin'
2694
+ session['user_name'] = params['name']
2695
+ else
2696
+ redirect '/login'
2697
+ end
2698
+ end
2699
+ end
2700
+
2701
+ class MyApp < Sinatra::Base
2702
+ # middleware will run before filters
2703
+ use LoginScreen
2704
+
2705
+ before do
2706
+ unless session['user_name']
2707
+ halt "Access denied, please <a href='/login'>login</a>."
2708
+ end
2709
+ end
2710
+
2711
+ get('/') { "Hello #{session['user_name']}." }
2712
+ end
2713
+ ```
2714
+
2715
+ ### Dynamic Application Creation
2716
+
2717
+ Sometimes you want to create new applications at runtime without having to
2718
+ assign them to a constant. You can do this with `Sinatra.new`:
2719
+
2720
+ ```ruby
2721
+ require 'sinatra/base'
2722
+ my_app = Sinatra.new { get('/') { "hi" } }
2723
+ my_app.run!
2724
+ ```
2725
+
2726
+ It takes the application to inherit from as an optional argument:
2727
+
2728
+ ```ruby
2729
+ # config.ru (run with rackup)
2730
+ require 'sinatra/base'
2731
+
2732
+ controller = Sinatra.new do
2733
+ enable :logging
2734
+ helpers MyHelpers
2735
+ end
2736
+
2737
+ map('/a') do
2738
+ run Sinatra.new(controller) { get('/') { 'a' } }
2739
+ end
2740
+
2741
+ map('/b') do
2742
+ run Sinatra.new(controller) { get('/') { 'b' } }
2743
+ end
2744
+ ```
2745
+
2746
+ This is especially useful for testing Sinatra extensions or using Sinatra in
2747
+ your own library.
2748
+
2749
+ This also makes using Sinatra as middleware extremely easy:
2750
+
2751
+ ```ruby
2752
+ require 'sinatra/base'
2753
+
2754
+ use Sinatra do
2755
+ get('/') { ... }
2756
+ end
2757
+
2758
+ run RailsProject::Application
2759
+ ```
2760
+
2761
+ ## Scopes and Binding
2762
+
2763
+ The scope you are currently in determines what methods and variables are
2764
+ available.
2765
+
2766
+ ### Application/Class Scope
2767
+
2768
+ Every Sinatra application corresponds to a subclass of `Sinatra::Base`.
2769
+ If you are using the top-level DSL (`require 'sinatra'`), then this
2770
+ class is `Sinatra::Application`, otherwise it is the subclass you
2771
+ created explicitly. At the class level, you have methods like `get` or
2772
+ `before`, but you cannot access the `request` or `session` objects, as
2773
+ there is only a single application class for all requests.
2774
+
2775
+ Options created via `set` are methods at class level:
2776
+
2777
+ ```ruby
2778
+ class MyApp < Sinatra::Base
2779
+ # Hey, I'm in the application scope!
2780
+ set :foo, 42
2781
+ foo # => 42
2782
+
2783
+ get '/foo' do
2784
+ # Hey, I'm no longer in the application scope!
2785
+ end
2786
+ end
2787
+ ```
2788
+
2789
+ You have the application scope binding inside:
2790
+
2791
+ * Your application class body
2792
+ * Methods defined by extensions
2793
+ * The block passed to `helpers`
2794
+ * Procs/blocks used as a value for `set`
2795
+ * The block passed to `Sinatra.new`
2796
+
2797
+ You can reach the scope object (the class) like this:
2798
+
2799
+ * Via the object passed to configure blocks (`configure { |c| ... }`)
2800
+ * `settings` from within the request scope
2801
+
2802
+ ### Request/Instance Scope
2803
+
2804
+ For every incoming request, a new instance of your application class is
2805
+ created, and all handler blocks run in that scope. From within this scope you
2806
+ can access the `request` and `session` objects or call rendering methods like
2807
+ `erb` or `haml`. You can access the application scope from within the request
2808
+ scope via the `settings` helper:
2809
+
2810
+ ```ruby
2811
+ class MyApp < Sinatra::Base
2812
+ # Hey, I'm in the application scope!
2813
+ get '/define_route/:name' do
2814
+ # Request scope for '/define_route/:name'
2815
+ @value = 42
2816
+
2817
+ settings.get("/#{params['name']}") do
2818
+ # Request scope for "/#{params['name']}"
2819
+ @value # => nil (not the same request)
2820
+ end
2821
+
2822
+ "Route defined!"
2823
+ end
2824
+ end
2825
+ ```
2826
+
2827
+ You have the request scope binding inside:
2828
+
2829
+ * get, head, post, put, delete, options, patch, link and unlink blocks
2830
+ * before and after filters
2831
+ * helper methods
2832
+ * templates/views
2833
+
2834
+ ### Delegation Scope
2835
+
2836
+ The delegation scope just forwards methods to the class scope. However, it
2837
+ does not behave exactly like the class scope, as you do not have the class
2838
+ binding. Only methods explicitly marked for delegation are available, and you
2839
+ do not share variables/state with the class scope (read: you have a different
2840
+ `self`). You can explicitly add method delegations by calling
2841
+ `Sinatra::Delegator.delegate :method_name`.
2842
+
2843
+ You have the delegate scope binding inside:
2844
+
2845
+ * The top-level binding, if you did `require "sinatra"`
2846
+ * An object extended with the `Sinatra::Delegator` mixin
2847
+
2848
+ Have a look at the code for yourself: here's the
2849
+ [Sinatra::Delegator mixin](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/base.rb#L1609-1633)
2850
+ being [extending the main object](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/main.rb#L28-30).
2851
+
2852
+ ## Command Line
2853
+
2854
+ Sinatra applications can be run directly:
2855
+
2856
+ ```shell
2857
+ ruby myapp.rb [-h] [-x] [-q] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER]
2858
+ ```
2859
+
2860
+ Options are:
2861
+
2862
+ ```
2863
+ -h # help
2864
+ -p # set the port (default is 4567)
2865
+ -o # set the host (default is 0.0.0.0)
2866
+ -e # set the environment (default is development)
2867
+ -s # specify rack server/handler (default is puma)
2868
+ -q # turn on quiet mode for server (default is off)
2869
+ -x # turn on the mutex lock (default is off)
2870
+ ```
2871
+
2872
+ ### Multi-threading
2873
+
2874
+ _Paraphrasing from
2875
+ [this StackOverflow answer](https://stackoverflow.com/a/6282999/5245129)
2876
+ by Konstantin_
2877
+
2878
+ Sinatra doesn't impose any concurrency model but leaves that to the
2879
+ underlying Rack handler (server) like Puma or WEBrick. Sinatra
2880
+ itself is thread-safe, so there won't be any problem if the Rack handler
2881
+ uses a threaded model of concurrency. This would mean that when starting
2882
+ the server, you'd have to specify the correct invocation method for the
2883
+ specific Rack handler. The following example is a demonstration of how
2884
+ to start a multi-threaded Rainbows server:
2885
+
2886
+ ```ruby
2887
+ # config.ru
2888
+
2889
+ require 'sinatra/base'
2890
+
2891
+ class App < Sinatra::Base
2892
+ get '/' do
2893
+ "Hello, World"
2894
+ end
2895
+ end
2896
+
2897
+ run App
2898
+ ```
2899
+
2900
+ ```ruby
2901
+ # rainbows.conf
2902
+
2903
+ # Rainbows configurator is based on Unicorn.
2904
+ Rainbows! do
2905
+ use :ThreadSpawn
2906
+ end
2907
+ ```
2908
+
2909
+ To start the server, the command would be:
2910
+
2911
+ ```shell
2912
+ rainbows -c rainbows.conf
2913
+ ```
2914
+
2915
+ ## Requirement
2916
+
2917
+ The following Ruby versions are officially supported:
2918
+ <dl>
2919
+ <dt>Ruby 2.6</dt>
2920
+ <dd>
2921
+ 2.6 is fully supported and recommended. There are currently no plans to
2922
+ drop official support for it.
2923
+ </dd>
2924
+
2925
+ <dt>Rubinius</dt>
2926
+ <dd>
2927
+ Rubinius is officially supported (Rubinius >= 2.x). It is recommended to
2928
+ <tt>gem install puma</tt>.
2929
+ </dd>
2930
+
2931
+ <dt>JRuby</dt>
2932
+ <dd>
2933
+ The latest stable release of JRuby is officially supported. It is not
2934
+ recommended to use C extensions with JRuby. It is recommended to
2935
+ <tt>gem install trinidad</tt>.
2936
+ </dd>
2937
+ </dl>
2938
+
2939
+ Versions of Ruby before 2.6 are no longer supported as of Sinatra 3.0.0.
2940
+
2941
+ We also keep an eye on upcoming Ruby versions. Expect upcoming
2942
+ 3.x releases to be fully supported.
2943
+
2944
+ Sinatra should work on any operating system supported by the chosen Ruby
2945
+ implementation.
2946
+
2947
+ Running Sinatra on a not officially supported Ruby flavor means that if things only break there we assume it's not our issue but theirs.
2948
+
2949
+ ## The Bleeding Edge
2950
+
2951
+ If you would like to use Sinatra's latest bleeding-edge code, feel free
2952
+ to run your application against the main branch, it should be rather
2953
+ stable.
2954
+
2955
+ We also push out prerelease gems from time to time, so you can do a
2956
+
2957
+ ```shell
2958
+ gem install sinatra --pre
2959
+ ```
2960
+
2961
+ to get some of the latest features.
2962
+
2963
+ ### With Bundler
2964
+
2965
+ If you want to run your application with the latest Sinatra, using
2966
+ [Bundler](https://bundler.io) is the recommended way.
2967
+
2968
+ First, install bundler, if you haven't:
2969
+
2970
+ ```shell
2971
+ gem install bundler
2972
+ ```
2973
+
2974
+ Then, in your project directory, create a `Gemfile`:
2975
+
2976
+ ```ruby
2977
+ source 'https://rubygems.org'
2978
+ gem 'sinatra', :github => 'sinatra/sinatra'
2979
+
2980
+ # other dependencies
2981
+ gem 'haml' # for instance, if you use haml
2982
+ ```
2983
+
2984
+ Note that you will have to list all your application's dependencies in
2985
+ the `Gemfile`. Sinatra's direct dependencies (Rack and Tilt) will,
2986
+ however, be automatically fetched and added by Bundler.
2987
+
2988
+ Now you can run your app like this:
2989
+
2990
+ ```shell
2991
+ bundle exec ruby myapp.rb
2992
+ ```
2993
+
2994
+ ## Versioning
2995
+
2996
+ Sinatra follows [Semantic Versioning](https://semver.org/), both SemVer and
2997
+ SemVerTag.
2998
+
2999
+ ## Further Reading
3000
+
3001
+ * [Project Website](https://sinatrarb.com/) - Additional documentation,
3002
+ news, and links to other resources.
3003
+ * [Contributing](https://sinatrarb.com/contributing) - Find a bug? Need
3004
+ help? Have a patch?
3005
+ * [Issue tracker](https://github.com/sinatra/sinatra/issues)
3006
+ * [Twitter](https://twitter.com/sinatra)
3007
+ * [Mailing List](https://groups.google.com/forum/#!forum/sinatrarb)
3008
+ * IRC: [#sinatra](irc://chat.freenode.net/#sinatra) on [Freenode](https://freenode.net)
3009
+ * [Sinatra & Friends](https://discord.gg/ncjsfsNHh7) on Discord
3010
+ * [Sinatra Book](https://github.com/sinatra/sinatra-book) - Cookbook Tutorial
3011
+ * [Sinatra Recipes](http://recipes.sinatrarb.com/) - Community contributed
3012
+ recipes
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/)
3016
+ * [CI Actions](https://github.com/sinatra/sinatra/actions)