sinatra 2.0.4 → 2.0.5

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
- SHA1:
3
- metadata.gz: 2eb0ce368ea68772182f3af721a991c23d85cc97
4
- data.tar.gz: d55ba8f5d95c39f7e8903ced236103b46b1a29ab
2
+ SHA256:
3
+ metadata.gz: 9f1a1b936783c248c4e1bd887b4e0f97a845d6f6322fbd9fdcfcd300a30fd161
4
+ data.tar.gz: 446c53ca1c4dbd2ac4ec56cc3373ef8424917edf5b66eb7dc4aae8b3994e9d06
5
5
  SHA512:
6
- metadata.gz: e9ccb8f9d0a4636c538af77f6f35920620873aa7b5330a74e0811213505ab8ac7ee3daa238b22d378a2ccf603130091acef6cae2cbb661ecd8038cefab2f6f03
7
- data.tar.gz: 77fcd98ec71a87f3ba5cf0105f8f0e3f1a8f2c079051d2b44677fe22be1cb7cc3a0b8b85fed4997e3a83f9baae1f268e802d3f34eb5a85544a1260c7290d88e8
6
+ metadata.gz: 51d4a3db499602ac7d80910b79c77d86cc7f22dfc410c9dee400a3e7ec50ba6884ad585f325095f1befbb9093dcbb9219030b63aefbea673b74832ee7c30a8d1
7
+ data.tar.gz: a535bfff1956e4c1ccfa31a7d8fbc1dd751695890116c5c9625d84aa066da1675381f4ada14d6a4c065374517d9b8cef3af472a739e72d693eef6896861935f5
@@ -1,3 +1,25 @@
1
+ ## 2.0.5 / 2018-12-22
2
+
3
+ * Avoid FrozenError when params contains frozen value [#1506](https://github.com/sinatra/sinatra/pull/1506) by Kunpei Sakai
4
+
5
+ * Add support for Erubi [#1494](https://github.com/sinatra/sinatra/pull/1494) by @tkmru
6
+
7
+ * `IndifferentHash` monkeypatch warning improvements [#1477](https://github.com/sinatra/sinatra/pull/1477) by Mike Pastore
8
+
9
+ * Improve development support and documentation and source code by Anusree Prakash, Jordan Owens, @ceclinux and @krororo.
10
+
11
+ ### sinatra-contrib
12
+
13
+ * Add `flush` option to `content_for` [#1225](https://github.com/sinatra/sinatra/pull/1225) by Shota Iguchi
14
+
15
+ * Drop activesupport dependency from sinatra-contrib [#1448](https://github.com/sinatra/sinatra/pull/1448)
16
+
17
+ * Update `yield_content` to append default to ERB template buffer [#1500](https://github.com/sinatra/sinatra/pull/1500) by Jordan Owens
18
+
19
+ ### rack-protection
20
+
21
+ * Don't track the Accept-Language header by default [#1504](https://github.com/sinatra/sinatra/pull/1504) by Artem Chistyakov
22
+
1
23
  ## 2.0.4 / 2018-09-15
2
24
 
3
25
  * Don't blow up when passing frozen string to `send_file` disposition [#1137](https://github.com/sinatra/sinatra/pull/1137) by Andrew Selder
data/Gemfile CHANGED
@@ -53,6 +53,7 @@ if RUBY_ENGINE == "ruby"
53
53
  gem 'stylus'
54
54
  gem 'rabl'
55
55
  gem 'builder'
56
+ gem 'erubi'
56
57
  gem 'erubis'
57
58
  gem 'haml', '>= 3.0'
58
59
  gem 'sass'
@@ -357,13 +357,13 @@ auch andere Werte akzeptiert.
357
357
  Es kann jedes gültige Objekt zurückgegeben werden, bei dem es sich entweder um
358
358
  einen Rack-Rückgabewert, einen Rack-Body oder einen HTTP-Status-Code handelt:
359
359
 
360
- * Ein Array mit drei Elementen: `[Status (Fixnum), Headers (Hash),
360
+ * Ein Array mit drei Elementen: `[Status (Integer), Headers (Hash),
361
361
  Response-Body (antwortet auf #each)]`.
362
- * Ein Array mit zwei Elementen: `[Status (Fixnum), Response-Body (antwortet
362
+ * Ein Array mit zwei Elementen: `[Status (Integer), Response-Body (antwortet
363
363
  auf #each)]`.
364
364
  * Ein Objekt, das auf `#each` antwortet und den an diese Methode übergebenen
365
365
  Block nur mit Strings als Übergabewerte aufruft.
366
- * Ein Fixnum, das den Status-Code festlegt.
366
+ * Ein Integer, das den Status-Code festlegt.
367
367
 
368
368
  Damit lässt sich relativ einfach Streaming implementieren:
369
369
 
@@ -353,13 +353,13 @@ Puedes retornar cualquier objeto que sea una respuesta Rack válida,
353
353
  un objeto que represente el cuerpo de una respuesta Rack o un código
354
354
  de estado HTTP:
355
355
 
356
- * Un arreglo con tres elementos: `[estado (Fixnum), cabeceras (Hash), cuerpo de
356
+ * Un arreglo con tres elementos: `[estado (Integer), cabeceras (Hash), cuerpo de
357
357
  la respuesta (responde a #each)]`
358
- * Un arreglo con dos elementos: `[estado (Fixnum), cuerpo de la respuesta
358
+ * Un arreglo con dos elementos: `[estado (Integer), cuerpo de la respuesta
359
359
  (responde a #each)]`
360
360
  * Un objeto que responde a `#each` y que le pasa únicamente strings al bloque
361
361
  dado
362
- * Un Fixnum representando el código de estado
362
+ * Un Integer representando el código de estado
363
363
 
364
364
  De esa manera, por ejemplo, podemos fácilmente implementar un ejemplo de streaming:
365
365
 
@@ -324,13 +324,13 @@ acceptées.
324
324
  Vous pouvez renvoyer n'importe quel objet qu'il s'agisse d'une réponse Rack
325
325
  valide, d'un corps de réponse Rack ou d'un code statut HTTP :
326
326
 
327
- * Un tableau de 3 éléments : `[code statut (Fixnum), en-têtes (Hash), corps
327
+ * Un tableau de 3 éléments : `[code statut (Integer), en-têtes (Hash), corps
328
328
  de la réponse (répondant à #each)]`
329
- * Un tableau de 2 élements : `[code statut (Fixnum), corps de la réponse
329
+ * Un tableau de 2 élements : `[code statut (Integer), corps de la réponse
330
330
  (répondant à #each)]`
331
331
  * Un objet qui répond à `#each` et qui ne transmet que des chaînes de
332
332
  caractères au bloc fourni
333
- * Un Fixnum représentant le code statut
333
+ * Un Integer représentant le code statut
334
334
 
335
335
  Ainsi, on peut facilement implémenter un exemple de streaming :
336
336
 
@@ -315,12 +315,12 @@ end
315
315
  Rackレスポンス、Rackボディオブジェクト、HTTPステータスコードのいずれかとして妥当なオブジェクトであればどのようなオブジェクトでも返すことができます。
316
316
 
317
317
  * 3つの要素を含む配列:
318
- `[ステータス(Fixnum), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]`
318
+ `[ステータス(Integer), ヘッダ(Hash), レスポンスボディ(#eachに応答する)]`
319
319
  * 2つの要素を含む配列:
320
- `[ステータス(Fixnum), レスポンスボディ(#eachに応答する)]`
320
+ `[ステータス(Integer), レスポンスボディ(#eachに応答する)]`
321
321
  * `#each`に応答するオブジェクト。通常はそのまま何も返さないが、
322
322
  与えられたブロックに文字列を渡す。
323
- * ステータスコードを表現する整数(Fixnum)
323
+ * ステータスコードを表現する整数(Integer)
324
324
 
325
325
  これにより、例えばストリーミングを簡単に実装することができます。
326
326
 
@@ -551,13 +551,14 @@ get('/') { markdown :index }
551
551
  <tr>
552
552
  <td>依存</td>
553
553
  <td>
554
- <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a>
554
+ <a href="https://github.com/jeremyevans/erubi" title="erubi">erubi</a>
555
+ または <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a>
555
556
  または erb (Rubyに同梱)
556
557
  </td>
557
558
  </tr>
558
559
  <tr>
559
560
  <td>ファイル拡張子</td>
560
- <td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubis</tt> (Erubisだけ)</td>
561
+ <td><tt>.erb</tt>, <tt>.rhtml</tt> または <tt>.erubi</tt> (Erubiだけ) または<tt>.erubis</tt> (Erubisだけ)</td>
561
562
  </tr>
562
563
  <tr>
563
564
  <td>例</td>
@@ -315,10 +315,10 @@ end
315
315
 
316
316
  유효한 Rack 응답, Rack 본문 객체 또는 HTTP 상태 코드가 되는 어떠한 객체라도 반환할 수 있습니다.
317
317
 
318
- * 세 요소를 가진 배열: `[상태 (Fixnum), 헤더 (Hash), 응답 본문 (#each에 반응)]`
319
- * 두 요소를 가진 배열: `[상태 (Fixnum), 응답 본문 (#each에 반응)]`
318
+ * 세 요소를 가진 배열: `[상태 (Integer), 헤더 (Hash), 응답 본문 (#each에 반응)]`
319
+ * 두 요소를 가진 배열: `[상태 (Integer), 응답 본문 (#each에 반응)]`
320
320
  * `#each`에 반응하고 주어진 블록으로 문자열만을 전달하는 객체
321
- * 상태 코드를 의미하는 Fixnum
321
+ * 상태 코드를 의미하는 Integer
322
322
 
323
323
  이것을 이용한 예를 들자면, 스트리밍(streaming) 예제를 쉽게 구현할 수 있습니다.
324
324
 
@@ -0,0 +1,3141 @@
1
+ # സിനാട്ര
2
+
3
+ [![gem വേർഷൻ ](https://badge.fury.io/rb/sinatra.svg)](http://badge.fury.io/rb/sinatra)
4
+ [![ബിൽഡ് സ്റ്റാറ്റസ്](https://secure.travis-ci.org/sinatra/sinatra.svg)](https://travis-ci.org/sinatra/sinatra)
5
+ [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=sinatra&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sinatra&package-manager=bundler&version-scheme=semver)
6
+
7
+ വെബ് അപ്പ്ലിക്കേഷൻസ് എളുപ്പത്തിൽ ഉണ്ടാക്കാനുള്ള ഒരു ലൈബ്രറി [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) ആണ്.:
8
+
9
+ ```റൂബി
10
+ # myapp.rb
11
+ require 'sinatra'
12
+
13
+ get '/' do
14
+ 'Hello world!'
15
+ end
16
+ ```
17
+
18
+ gem ഇൻസ്റ്റാൾ ചെയ്യുവാൻ:
19
+
20
+ ```shell
21
+ gem install sinatra
22
+ ```
23
+
24
+ റൺ ചെയ്യുവാൻ :
25
+
26
+ ```shell / ഷെൽ
27
+ ruby myapp.rb
28
+ ```
29
+
30
+ View at: [http://localhost:4567](http://localhost:4567)
31
+
32
+ സെർവർ വീണ്ടും സ്റ്റാർട്ട് ചെയ്യാതെ നിങ്ങളുടെ കോഡ് ചേഞ്ച് കാണാൻ സാധിക്കുകയില്ല
33
+ കോഡ് ചേഞ്ച് ചെയ്യുമ്പോൾ സെർവർ വീണ്ടും സ്റ്റാർട്ട് ചെയ്യാൻ മറക്കരുത്
34
+ [sinatra/reloader](http://www.sinatrarb.com/contrib/reloader).
35
+
36
+ എപ്പോഴും `gem install thin`,എന്ന് റൺ ചെയ്യുക , ഇത് ഏറ്റവും പുതിയ അപ്ലിക്കേഷൻ സെലക്ട് ചെയ്യാൻ നമ്മളെ സഹായിക്കും .
37
+
38
+ ## ഉള്ളടക്കം
39
+
40
+ * [സിനാട്ര](#sinatra)
41
+ * [ഉള്ളടക്കം](#table-of-contents)
42
+ * [റൂട്സ്](#routes)
43
+ * [കണ്ടിഷൻസ്](#conditions)
44
+ * [റിട്ടേൺ വാല്യൂസ്](#return-values)
45
+ * [കസ്റ്റമ് റൂട്ട് മടീച്ചേഴ്സ് ](#custom-route-matchers)
46
+ * [സ്റ്റാറ്റിക് files](#static-files)
47
+ * [വ്യൂസ് / ടെംപ്ലേറ്റ്സ്](#views--templates)
48
+ * [ലിറ്ററൽ ടെംപ്ലേറ്റ്സ് ](#literal-templates)
49
+ * [ലഭ്യമായ ടെംപ്ലേറ്റ്സ് ഭാഷകൾ ](#available-template-languages)
50
+ * [Haml ടെംപ്ലേറ്റ്സ്](#haml-templates)
51
+ * [Erb ടെംപ്ലേറ്റ്സ്](#erb-templates)
52
+ * [Builder ടെംപ്ലേറ്റ്സ്](#builder-templates)
53
+ * [nokogiri ടെംപ്ലേറ്റ്സ്](#nokogiri-templates)
54
+ * [Sass ടെംപ്ലേറ്റ്സ്](#sass-templates)
55
+ * [SCSS ടെംപ്ലേറ്റ്സ്](#scss-templates)
56
+ * [Less ടെംപ്ലേറ്റ്സ്](#less-templates)
57
+ * [Liquid ടെംപ്ലേറ്റ്സ്](#liquid-templates)
58
+ * [Markdown ടെംപ്ലേറ്റ്സ്](#markdown-templates)
59
+ * [Textile ടെംപ്ലേറ്റ്സ്](#textile-templates)
60
+ * [RDoc ടെംപ്ലേറ്റ്സ്](#rdoc-templates)
61
+ * [AsciiDoc ടെംപ്ലേറ്റ്സ്](#asciidoc-templates)
62
+ * [Radius ടെംപ്ലേറ്റ്സ്](#radius-templates)
63
+ * [Markaby ടെംപ്ലേറ്റ്സ്](#markaby-templates)
64
+ * [RABL ടെംപ്ലേറ്റ്സ്](#rabl-templates)
65
+ * [Slim ടെംപ്ലേറ്റ്സ്](#slim-templates)
66
+ * [Creole ടെംപ്ലേറ്റ്സ്](#creole-templates)
67
+ * [MediaWiki ടെംപ്ലേറ്റ്സ്](#mediawiki-templates)
68
+ * [CoffeeScript ടെംപ്ലേറ്റ്സ്](#coffeescript-templates)
69
+ * [Stylus ടെംപ്ലേറ്റ്സ്](#stylus-templates)
70
+ * [Yajl ടെംപ്ലേറ്റ്സ്](#yajl-templates)
71
+ * [WLang ടെംപ്ലേറ്റ്സ്](#wlang-templates)
72
+ * [വാരിയബിൾസിനെ എടുക്കാൻ സഹായിക്കുന്ന ടെംപ്ലേറ്റ്സ്](#accessing-variables-in-templates)
73
+ * [Templates with `yield` and nested layouts](#templates-with-yield-and-nested-layouts)
74
+ * [Inline ടെംപ്ലേറ്റ്സ്](#inline-templates)
75
+ * [പേരുള്ള ടെംപ്ലേറ്റ്സ്](#named-templates)
76
+ * [Associating File Extensions](#associating-file-extensions)
77
+ * [നിങ്ങളുടെ സ്വന്തം ടെമ്പ്ലേറ്റ് എങ്ങിനെ ഉണ്ടാക്കാൻ സഹായിക്കുന്നു ](#adding-your-own-template-engine)
78
+ * [Using Custom Logic for Template Lookup](#using-custom-logic-for-template-lookup)
79
+ * [Filters](#filters)
80
+ * [Helpers](#helpers)
81
+ * [സെഷൻസ് ഉപയോഗിക്കുന്നു ](#using-sessions)
82
+ * [രഹസ്യമായി സെഷൻസ് സംരക്ഷിക്കുക ](#session-secret-security)
83
+ * [Session Config](#session-config)
84
+ * [സെഷൻ middlewate തിരഞ്ഞെടുക്കുക](#choosing-your-own-session-middleware)
85
+ * [ഹാൾട് ചെയ്യുക ](#halting)
86
+ * [Passing](#passing)
87
+ * [മറ്റൊരു റൂട്ട് ട്രിഗർ ചെയ്യുക ](#triggering-another-route)
88
+ * [Setting Body, Status Code and Headers](#setting-body-status-code-and-headers)
89
+ * [Streaming Responses](#streaming-responses)
90
+ * [Logging](#logging)
91
+ * [Mime Types](#mime-types)
92
+ * [ URLs Generating](#generating-urls)
93
+ * [Browser റീഡിറക്ട് ചെയ്യുക ](#browser-redirect)
94
+ * [Cache Control](#cache-control)
95
+ * [Sending Files](#sending-files)
96
+ * [Accessing the Request Object](#accessing-the-request-object)
97
+ * [അറ്റാച്മെന്റ്സ് ](#attachments)
98
+ * [ദിവസവും സമയവും ഡീൽ ചെയ്യക ](#dealing-with-date-and-time)
99
+ * [Template Files നോക്കുന്നു ](#looking-up-template-files)
100
+ * [Configuration](#configuration)
101
+ * [Configuring attack protection](#configuring-attack-protection)
102
+ * [Available Settings](#available-settings)
103
+ * [Environments](#environments)
104
+ * [ കൈകാര്യം ചെയ്യുക ](#error-handling)
105
+ * [കണ്ടെത്താൻ ആയില്ല ](#not-found)
106
+ * [തെറ്റ്](#error)
107
+ * [Rack Middleware](#rack-middleware)
108
+ * [ടെസ്റ്റ് ചെയ്യുക ](#testing)
109
+ * [Sinatra::Base - Middleware, Libraries, and Modular Apps](#sinatrabase---middleware-libraries-and-modular-apps)
110
+ * [Modular vs. Classic Style](#modular-vs-classic-style)
111
+ * [Serving a Modular Application](#serving-a-modular-application)
112
+ * [Using a Classic Style Application with a config.ru](#using-a-classic-style-application-with-a-configru)
113
+ * [When to use a config.ru?](#when-to-use-a-configru)
114
+ * [Using Sinatra as Middleware](#using-sinatra-as-middleware)
115
+ * [Dynamic Application Creation](#dynamic-application-creation)
116
+ * [Scopes and Binding](#scopes-and-binding)
117
+ * [Application/Class Scope](#applicationclass-scope)
118
+ * [Request/Instance Scope](#requestinstance-scope)
119
+ * [Delegation Scope](#delegation-scope)
120
+ * [Command Line](#command-line)
121
+ * [Multi-threading](#multi-threading)
122
+ * [ആവശ്യങ്ങൾ ](#requirement)
123
+ * [The Bleeding Edge](#the-bleeding-edge)
124
+ * [With Bundler](#with-bundler)
125
+ * [വേർഷൻ ചെയ്യുക ](#versioning)
126
+ * [Further Reading](#further-reading)
127
+
128
+ ## Routes
129
+
130
+ In Sinatra, a route is an HTTP method paired with a URL-matching pattern.
131
+ Each route is associated with a block:
132
+
133
+ ```റൂബി
134
+ get '/' do
135
+ .. show something ..
136
+ end
137
+
138
+ post '/' do
139
+ .. create something ..
140
+ end
141
+
142
+ put '/' do
143
+ .. replace something ..
144
+ end
145
+
146
+ patch '/' do
147
+ .. modify something ..
148
+ end
149
+
150
+ delete '/' do
151
+ .. annihilate something ..
152
+ end
153
+
154
+ options '/' do
155
+ .. appease something ..
156
+ end
157
+
158
+ link '/' do
159
+ .. affiliate something ..
160
+ end
161
+
162
+ unlink '/' do
163
+ .. separate something ..
164
+ end
165
+ ```
166
+
167
+ റൂട്സ് മാച്ച് ചെയ്യാനാ രീതിയില് ആണ് അത് നിർവചിക്കുന്നത് . ഏത് റിക്വസ്റ്റ് ആണോ റൂട്ട് ആയി ചേരുന്നത് ആ റൂട്ട് ആണ് വിളിക്കപെടുക .
168
+
169
+ ട്രെയ്ലറിങ് സ്ലാഷ്‌സ് ഉള്ള റൂട്സ് അത് ഇല്ലാത്തതിൽ നിന്ന് വ്യത്യാസം ഉള്ളത് ആണ് :
170
+
171
+ ```ruby
172
+ get '/foo' do
173
+ # Does not match "GET /foo/"
174
+ end
175
+ ```
176
+
177
+ Route patterns may include named parameters, accessible via the
178
+ `params` hash:
179
+
180
+ ```ruby
181
+ get '/hello/:name' do
182
+ # matches "GET /hello/foo" and "GET /hello/bar"
183
+ # params['name'] is 'foo' or 'bar'
184
+ "Hello #{params['name']}!"
185
+ end
186
+ ```
187
+
188
+ ```ruby
189
+ get '/hello/:name' do |n|
190
+ # matches "GET /hello/foo" and "GET /hello/bar"
191
+ # params['name'] is 'foo' or 'bar'
192
+ # n stores params['name']
193
+ "Hello #{n}!"
194
+ end
195
+ ```
196
+ റൂട്ട് പാട്ടേഴ്സിൽ പേരുള്ള splat ഉണ്ടാകാറുണ്ട് അതിനെ 'params['splat']' array ഉപയോഗിച്ച ഉപയോഗപ്പെടുത്താവുന്നത് ആണ്
197
+
198
+
199
+
200
+ ```ruby
201
+ get '/say/*/to/*' do
202
+ # matches /say/hello/to/world
203
+ params['splat'] # => ["hello", "world"]
204
+ end
205
+
206
+ get '/download/*.*' do
207
+ # matches /download/path/to/file.xml
208
+ params['splat'] # => ["path/to/file", "xml"]
209
+ end
210
+ ```
211
+
212
+ Or with block parameters:
213
+
214
+ ```ruby
215
+ get '/download/*.*' do |path, ext|
216
+ [path, ext] # => ["path/to/file", "xml"]
217
+ end
218
+ ```
219
+
220
+ റെഗുലർ expressions :
221
+
222
+ ```ruby
223
+ get /\/hello\/([\w]+)/ do
224
+ "Hello, #{params['captures'].first}!"
225
+ end
226
+ ```
227
+
228
+ ബ്ലോക്ക് പരാമീറ്റർസ് ഉള്ള റൂട്ട് മാച്ചിങ് :
229
+
230
+ ```ruby
231
+ get %r{/hello/([\w]+)} do |c|
232
+ # Matches "GET /meta/hello/world", "GET /hello/world/1234" etc.
233
+ "Hello, #{c}!"
234
+ end
235
+ ```
236
+
237
+
238
+
239
+ ```ruby
240
+ get '/posts/:format?' do
241
+ # matches "GET /posts/" and any extension "GET /posts/json", "GET /posts/xml" etc
242
+ end
243
+ ```
244
+ റൂട്ട് പാറ്റെൺസ് ഇത് query പരാമീറ്റർസ് ഉണ്ടാകാം :
245
+
246
+
247
+ ```ruby
248
+ get '/posts' do
249
+ # matches "GET /posts?title=foo&author=bar"
250
+ title = params['title']
251
+ author = params['author']
252
+ # uses title and author variables; query is optional to the /posts route
253
+ end
254
+ ```
255
+ അതുപോലെ നിങ്ങൾ പാത ട്രവേഴ്സല് അറ്റാച്ച് പ്രൊട്ടക്ഷൻ (#configuring-attack-protection) ഡിസബിലെ ചെയ്തട്ടില്ലെങ്കിൽ റെക്‌സ് പാത മോഡിഫിയ ചെയ്യണത്തിനു മുൻപ് അത് മാച്ച് ചെയ്യപ്പെടും
256
+
257
+
258
+ You may customize the [Mustermann](https://github.com/sinatra/mustermann#readme)
259
+ options used for a given route by passing in a `:mustermann_opts` hash:
260
+
261
+ ```ruby
262
+ get '\A/posts\z', :mustermann_opts => { :type => :regexp, :check_anchors => false } do
263
+ # matches /posts exactly, with explicit anchoring
264
+ "If you match an anchored pattern clap your hands!"
265
+ end
266
+ ```
267
+ ഇത് [condition](#conditions), പോലെ തോന്നുമെങ്കിലും ഇ ഒപ്റേൻസ് global `:mustermann_opts` ആയി മെർജ് ചെയ്യപ്പെട്ടിരിക്കുന്നു
268
+
269
+ ## കണ്ടിഷൻസ്
270
+
271
+ യൂസർ അഗെന്റ്റ് പോലുള്ള മാച്ചിങ് റൂട്സ് ഇത് അടങ്ങി ഇരിക്കുന്നു
272
+ ```ruby
273
+ get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
274
+ "You're using Songbird version #{params['agent'][0]}"
275
+ end
276
+
277
+ get '/foo' do
278
+ # Matches non-songbird browsers
279
+ end
280
+ ```
281
+
282
+ ഇതുപോലുള്ള വേറെ കണ്ടിഷൻസ് ആണ് host_name , provides
283
+ ```ruby
284
+ get '/', :host_name => /^admin\./ do
285
+ "Admin Area, Access denied!"
286
+ end
287
+
288
+ get '/', :provides => 'html' do
289
+ haml :index
290
+ end
291
+
292
+ get '/', :provides => ['rss', 'atom', 'xml'] do
293
+ builder :feed
294
+ end
295
+ ```
296
+ `provides ` ആക്‌സെപ്റ് ഹെൽഡർസ് നെ അന്വഷിക്കുന്നു
297
+
298
+ നിങ്ങളുടെ കണ്ടിഷൻസ് ഇനി എളുപ്പത്തിൽ ഉണ്ടാക്കാൻ സഹായിക്കുന്നു
299
+ ```ruby
300
+ set(:probability) { |value| condition { rand <= value } }
301
+
302
+ get '/win_a_car', :probability => 0.1 do
303
+ "You won!"
304
+ end
305
+
306
+ get '/win_a_car' do
307
+ "Sorry, you lost."
308
+ end
309
+ ```
310
+
311
+ splat ഉപയോഗിച്ച പലതരത്തിൽ ഉള്ള കണ്ടിഷൻസ് ഉണ്ടാക്കാൻ സാധിക്കുന്നു :
312
+
313
+ ```ruby
314
+ set(:auth) do |*roles| # <- notice the splat here
315
+ condition do
316
+ unless logged_in? && roles.any? {|role| current_user.in_role? role }
317
+ redirect "/login/", 303
318
+ end
319
+ end
320
+ end
321
+
322
+ get "/my/account/", :auth => [:user, :admin] do
323
+ "Your Account Details"
324
+ end
325
+
326
+ get "/only/admin/", :auth => :admin do
327
+ "Only admins are allowed here!"
328
+ end
329
+ ```
330
+
331
+ ## Return Values
332
+
333
+
334
+
335
+
336
+ റൂട്ട് ബ്ലോക്കിന്റെ റിട്ടേൺ വാല്യൂ HTTP client യിലേക്ക് കടത്തിവിടുന്ന രേസ്പോൻസ് ബോഡിയെ തീരുമാനിക്കുന്നു. സാധാരണയായി ഇത് ഒരു സ്ട്രിംഗ് ആണ്. പക്ഷെ മറ്റു വാല്യൂകളെയും ഇത് സ്വീകരിക്കും
337
+
338
+ * മൂന്ന് എലെമെന്റ്സ് ഉള്ള അറേ : `[status (Integer), headers (Hash), response
339
+ body (responds to #each)]`
340
+ * രണ്ട് എലെമെന്റ്സ് ഉള്ള അറേ : `[status (Integer), response body (responds to
341
+ #each)]`
342
+ * An object that responds to `#each` and passes nothing but strings to
343
+ the given block
344
+ * Integer സ്റ്റാറ്റസ് കോഡിനെ കാണിക്കുന്നു
345
+
346
+ ഇത് നമക്ക് സ്ട്രീമിംഗ് ഉദാഹരണങ്ങൾ ഉണ്ടാക്കാം
347
+ ```ruby
348
+ class Stream
349
+ def each
350
+ 100.times { |i| yield "#{i}\n" }
351
+ end
352
+ end
353
+
354
+ get('/') { Stream.new }
355
+ ```
356
+
357
+ `stream` helper' ഉപയോഗിച്ച([described below](#streaming-responses))റൂട്ട് ഇലെ ബോയ്ലർ പ്ലേറ്റ്സ് ഇനി കുറക്കാം
358
+
359
+ ## Custom Route Matchers
360
+
361
+ മുകളിൽ കാണിച്ചിരിക്കുന്ന പോലെ , സിനാട്ര ഉപയോഗിച്ച String patterns, regular expressions കൈകാര്യം ചെയ്യാം മാത്രമല്ല നിങ്ങളുടെ സ്വന്തം matchers ഉം ഉണ്ടാക്കാം
362
+ ```ruby
363
+ class AllButPattern
364
+ Match = Struct.new(:captures)
365
+
366
+ def initialize(except)
367
+ @except = except
368
+ @captures = Match.new([])
369
+ end
370
+
371
+ def match(str)
372
+ @captures unless @except === str
373
+ end
374
+ end
375
+
376
+ def all_but(pattern)
377
+ AllButPattern.new(pattern)
378
+ end
379
+
380
+ get all_but("/index") do
381
+ # ...
382
+ end
383
+ ```
384
+
385
+ ഇതിനെ ഇങ്ങനെയും കാണിക്കാം
386
+
387
+ ```ruby
388
+ get // do
389
+ pass if request.path_info == "/index"
390
+ # ...
391
+ end
392
+ ```
393
+
394
+ Or, using negative look ahead:
395
+
396
+ ```ruby
397
+ get %r{(?!/index)} do
398
+ # ...
399
+ end
400
+ ```
401
+
402
+ ## Static Files
403
+
404
+ സ്റ്റാറ്റിക് ഫിലെസ് `./public` എന്ന ഡയറക്ടറി ഇത് ആണ് ഉണ്ടാകുക
405
+ നിങ്ങൾക്ക് `:public_folder` വഴി വേറെ പാത ഉണ്ടാക്കാം
406
+
407
+
408
+ ```ruby
409
+ set :public_folder, File.dirname(__FILE__) + '/static'
410
+ ```
411
+
412
+ URL ഇളിൽ ഡയറക്ടറി പാത ഉണ്ടാകില്ല . A file
413
+ `./public/css/style.css` is made available as
414
+ `http://example.com/css/style.css`.
415
+
416
+ Use the `:static_cache_control` setting (see [below](#cache-control)) to add
417
+ `Cache-Control` header info.
418
+
419
+ ## Views / Templates
420
+
421
+ എല്ലാ ടെമ്പ്ലേറ്റ് ഭാഷയും അതിന്റെ സ്വതം റെൻഡറിങ് മെതോഡിൽ ആണ് പുറത്തു കാണപ്പെടുക. ഇത് ഒരു സ്ട്രിംഗ് ഇനി റിട്ടേൺ ചെയ്യും
422
+
423
+ ```ruby
424
+ get '/' do
425
+ erb :index
426
+ end
427
+ ```
428
+
429
+ This renders `views/index.erb`.
430
+
431
+ ടെമ്പ്ലേറ്റ് ഇന്റെ പേരിനു പകരം നിങ്ങൾക്ക് ടെപ്ലേറ്റ് ഇന്റെ കോൺടെന്റ് കടത്തി വിടാം
432
+
433
+ ```ruby
434
+ get '/' do
435
+ code = "<%= Time.now %>"
436
+ erb code
437
+ end
438
+ ```
439
+
440
+ ടെമ്പ്ലേറ്റ് മറ്റൊരു അർജുമെന്റിനെ കടത്തി വിടുന്നു
441
+ ```ruby
442
+ get '/' do
443
+ erb :index, :layout => :post
444
+ end
445
+ ```
446
+
447
+ This will render `views/index.erb` embedded in the
448
+ `views/post.erb` (default is `views/layout.erb`, if it exists).
449
+
450
+ സിനാട്ര ക്ക് മനസ്സിലാകാത്ത ടെമ്പ്ലേറ്റ് ഇനി ടെമ്പ്ലേറ്റ് എന്ജിനിലേക്ക് കടത്തി വിടും :
451
+
452
+ ```ruby
453
+ get '/' do
454
+ haml :index, :format => :html5
455
+ end
456
+ ```
457
+
458
+ നിങ്ങൾക്ക് ഓപ്ഷണൽ ആയി ലാംഗ്വേജ് ജനറലിൽ സെറ്റ് ചെയ്യാൻ കഴിയും :
459
+
460
+ ```ruby
461
+ set :haml, :format => :html5
462
+
463
+ get '/' do
464
+ haml :index
465
+ end
466
+ ```
467
+
468
+ ഉപയോഗിച്ച റെൻഡർ മെതോഡിൽ ഒപ്റേൻസ് പാസ് ചെയ്യാൻ പാട്ടും `set`.
469
+
470
+ Available Options:
471
+
472
+ <dl>
473
+ <dt>locals</dt>
474
+ <dd>
475
+ List of locals passed to the document. Handy with partials.
476
+ Example: <tt>erb "<%= foo %>", :locals => {:foo => "bar"}</tt>
477
+ </dd>
478
+
479
+ <dt>default_encoding</dt>
480
+ <dd>
481
+ String encoding to use if uncertain. Defaults to
482
+ <tt>settings.default_encoding</tt>.
483
+ </dd>
484
+
485
+ <dt>views</dt>
486
+ <dd>
487
+ Views folder to load templates from. Defaults to <tt>settings.views</tt>.
488
+ </dd>
489
+
490
+ <dt>layout</dt>
491
+ <dd>
492
+ Whether to use a layout (<tt>true</tt> or <tt>false</tt>). If it's a
493
+ Symbol, specifies what template to use. Example:
494
+ <tt>erb :index, :layout => !request.xhr?</tt>
495
+ </dd>
496
+
497
+ <dt>content_type</dt>
498
+ <dd>
499
+ Content-Type the template produces. Default depends on template language.
500
+ </dd>
501
+
502
+ <dt>scope</dt>
503
+ <dd>
504
+ Scope to render template under. Defaults to the application
505
+ instance. If you change this, instance variables and helper methods
506
+ will not be available.
507
+ </dd>
508
+
509
+ <dt>layout_engine</dt>
510
+ <dd>
511
+ Template engine to use for rendering the layout. Useful for
512
+ languages that do not support layouts otherwise. Defaults to the
513
+ engine used for the template. Example: <tt>set :rdoc, :layout_engine
514
+ => :erb</tt>
515
+ </dd>
516
+
517
+ <dt>layout_options</dt>
518
+ <dd>
519
+ Special options only used for rendering the layout. Example:
520
+ <tt>set :rdoc, :layout_options => { :views => 'views/layouts' }</tt>
521
+ </dd>
522
+ </dl>
523
+
524
+ Templates are assumed to be located directly under the `./views`
525
+ directory. To use a different views directory:
526
+
527
+ ```ruby
528
+ set :views, settings.root + '/templates'
529
+ ```
530
+
531
+
532
+ One important thing to remember is that you always have to reference
533
+ templates with symbols, even if they're in a subdirectory (in this case,
534
+ use: `:'subdir/template'` or `'subdir/template'.to_sym`). You must use a
535
+ symbol because otherwise rendering methods will render any strings
536
+ passed to them directly.
537
+
538
+ ### Literal Templates
539
+
540
+ ```ruby
541
+ get '/' do
542
+ haml '%div.title Hello World'
543
+ end
544
+ ```
545
+
546
+ Renders the template string. You can optionally specify `:path` and
547
+ `:line` for a clearer backtrace if there is a filesystem path or line
548
+ associated with that string:
549
+
550
+ ```ruby
551
+ get '/' do
552
+ haml '%div.title Hello World', :path => 'examples/file.haml', :line => 3
553
+ end
554
+ ```
555
+
556
+ ### Available Template Languages
557
+
558
+ Some languages have multiple implementations. To specify what implementation
559
+ to use (and to be thread-safe), you should simply require it first:
560
+
561
+ ```ruby
562
+ require 'rdiscount' # or require 'bluecloth'
563
+ get('/') { markdown :index }
564
+ ```
565
+
566
+ #### Haml Templates
567
+
568
+ <table>
569
+ <tr>
570
+ <td>Dependency</td>
571
+ <td><a href="http://haml.info/" title="haml">haml</a></td>
572
+ </tr>
573
+ <tr>
574
+ <td>File Extension</td>
575
+ <td><tt>.haml</tt></td>
576
+ </tr>
577
+ <tr>
578
+ <td>Example</td>
579
+ <td><tt>haml :index, :format => :html5</tt></td>
580
+ </tr>
581
+ </table>
582
+
583
+ #### Erb Templates
584
+
585
+ <table>
586
+ <tr>
587
+ <td>Dependency</td>
588
+ <td>
589
+ <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a>
590
+ or erb (included in Ruby)
591
+ </td>
592
+ </tr>
593
+ <tr>
594
+ <td>File Extensions</td>
595
+ <td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubis</tt> (Erubis only)</td>
596
+ </tr>
597
+ <tr>
598
+ <td>Example</td>
599
+ <td><tt>erb :index</tt></td>
600
+ </tr>
601
+ </table>
602
+
603
+ #### Builder Templates
604
+
605
+ <table>
606
+ <tr>
607
+ <td>Dependency</td>
608
+ <td>
609
+ <a href="https://github.com/jimweirich/builder" title="builder">builder</a>
610
+ </td>
611
+ </tr>
612
+ <tr>
613
+ <td>File Extension</td>
614
+ <td><tt>.builder</tt></td>
615
+ </tr>
616
+ <tr>
617
+ <td>Example</td>
618
+ <td><tt>builder { |xml| xml.em "hi" }</tt></td>
619
+ </tr>
620
+ </table>
621
+
622
+ It also takes a block for inline templates (see [example](#inline-templates)).
623
+
624
+ #### Nokogiri Templates
625
+
626
+ <table>
627
+ <tr>
628
+ <td>Dependency</td>
629
+ <td><a href="http://www.nokogiri.org/" title="nokogiri">nokogiri</a></td>
630
+ </tr>
631
+ <tr>
632
+ <td>File Extension</td>
633
+ <td><tt>.nokogiri</tt></td>
634
+ </tr>
635
+ <tr>
636
+ <td>Example</td>
637
+ <td><tt>nokogiri { |xml| xml.em "hi" }</tt></td>
638
+ </tr>
639
+ </table>
640
+
641
+ It also takes a block for inline templates (see [example](#inline-templates)).
642
+
643
+ #### Sass Templates
644
+
645
+ <table>
646
+ <tr>
647
+ <td>Dependency</td>
648
+ <td><a href="https://sass-lang.com/" title="sass">sass</a></td>
649
+ </tr>
650
+ <tr>
651
+ <td>File Extension</td>
652
+ <td><tt>.sass</tt></td>
653
+ </tr>
654
+ <tr>
655
+ <td>Example</td>
656
+ <td><tt>sass :stylesheet, :style => :expanded</tt></td>
657
+ </tr>
658
+ </table>
659
+
660
+ #### SCSS Templates
661
+
662
+ <table>
663
+ <tr>
664
+ <td>Dependency</td>
665
+ <td><a href="https://sass-lang.com/" title="sass">sass</a></td>
666
+ </tr>
667
+ <tr>
668
+ <td>File Extension</td>
669
+ <td><tt>.scss</tt></td>
670
+ </tr>
671
+ <tr>
672
+ <td>Example</td>
673
+ <td><tt>scss :stylesheet, :style => :expanded</tt></td>
674
+ </tr>
675
+ </table>
676
+
677
+ #### Less Templates
678
+
679
+ <table>
680
+ <tr>
681
+ <td>Dependency</td>
682
+ <td><a href="http://lesscss.org/" title="less">less</a></td>
683
+ </tr>
684
+ <tr>
685
+ <td>File Extension</td>
686
+ <td><tt>.less</tt></td>
687
+ </tr>
688
+ <tr>
689
+ <td>Example</td>
690
+ <td><tt>less :stylesheet</tt></td>
691
+ </tr>
692
+ </table>
693
+
694
+ #### Liquid Templates
695
+
696
+ <table>
697
+ <tr>
698
+ <td>Dependency</td>
699
+ <td><a href="https://shopify.github.io/liquid/" title="liquid">liquid</a></td>
700
+ </tr>
701
+ <tr>
702
+ <td>File Extension</td>
703
+ <td><tt>.liquid</tt></td>
704
+ </tr>
705
+ <tr>
706
+ <td>Example</td>
707
+ <td><tt>liquid :index, :locals => { :key => 'value' }</tt></td>
708
+ </tr>
709
+ </table>
710
+
711
+ Since you cannot call Ruby methods (except for `yield`) from a Liquid
712
+ template, you almost always want to pass locals to it.
713
+
714
+ #### Markdown Templates
715
+
716
+ <table>
717
+ <tr>
718
+ <td>Dependency</td>
719
+ <td>
720
+ Anyone of:
721
+ <a href="https://github.com/davidfstr/rdiscount" title="RDiscount">RDiscount</a>,
722
+ <a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>,
723
+ <a href="https://github.com/ged/bluecloth" title="BlueCloth">BlueCloth</a>,
724
+ <a href="https://kramdown.gettalong.org/" title="kramdown">kramdown</a>,
725
+ <a href="https://github.com/bhollis/maruku" title="maruku">maruku</a>
726
+ </td>
727
+ </tr>
728
+ <tr>
729
+ <td>File Extensions</td>
730
+ <td><tt>.markdown</tt>, <tt>.mkd</tt> and <tt>.md</tt></td>
731
+ </tr>
732
+ <tr>
733
+ <td>Example</td>
734
+ <td><tt>markdown :index, :layout_engine => :erb</tt></td>
735
+ </tr>
736
+ </table>
737
+
738
+ It is not possible to call methods from Markdown, nor to pass locals to it.
739
+ You therefore will usually use it in combination with another rendering
740
+ engine:
741
+
742
+ ```ruby
743
+ erb :overview, :locals => { :text => markdown(:introduction) }
744
+ ```
745
+
746
+ Note that you may also call the `markdown` method from within other
747
+ templates:
748
+
749
+ ```ruby
750
+ %h1 Hello From Haml!
751
+ %p= markdown(:greetings)
752
+ ```
753
+
754
+ Since you cannot call Ruby from Markdown, you cannot use layouts written in
755
+ Markdown. However, it is possible to use another rendering engine for the
756
+ template than for the layout by passing the `:layout_engine` option.
757
+
758
+ #### Textile Templates
759
+
760
+ <table>
761
+ <tr>
762
+ <td>Dependency</td>
763
+ <td><a href="http://redcloth.org/" title="RedCloth">RedCloth</a></td>
764
+ </tr>
765
+ <tr>
766
+ <td>File Extension</td>
767
+ <td><tt>.textile</tt></td>
768
+ </tr>
769
+ <tr>
770
+ <td>Example</td>
771
+ <td><tt>textile :index, :layout_engine => :erb</tt></td>
772
+ </tr>
773
+ </table>
774
+
775
+ It is not possible to call methods from Textile, nor to pass locals to
776
+ it. You therefore will usually use it in combination with another
777
+ rendering engine:
778
+
779
+ ```ruby
780
+ erb :overview, :locals => { :text => textile(:introduction) }
781
+ ```
782
+
783
+ Note that you may also call the `textile` method from within other templates:
784
+
785
+ ```ruby
786
+ %h1 Hello From Haml!
787
+ %p= textile(:greetings)
788
+ ```
789
+
790
+ Since you cannot call Ruby from Textile, you cannot use layouts written in
791
+ Textile. However, it is possible to use another rendering engine for the
792
+ template than for the layout by passing the `:layout_engine` option.
793
+
794
+ #### RDoc Templates
795
+
796
+ <table>
797
+ <tr>
798
+ <td>Dependency</td>
799
+ <td><a href="http://rdoc.sourceforge.net/" title="RDoc">RDoc</a></td>
800
+ </tr>
801
+ <tr>
802
+ <td>File Extension</td>
803
+ <td><tt>.rdoc</tt></td>
804
+ </tr>
805
+ <tr>
806
+ <td>Example</td>
807
+ <td><tt>rdoc :README, :layout_engine => :erb</tt></td>
808
+ </tr>
809
+ </table>
810
+
811
+ It is not possible to call methods from RDoc, nor to pass locals to it. You
812
+ therefore will usually use it in combination with another rendering engine:
813
+
814
+ ```ruby
815
+ erb :overview, :locals => { :text => rdoc(:introduction) }
816
+ ```
817
+
818
+ Note that you may also call the `rdoc` method from within other templates:
819
+
820
+ ```ruby
821
+ %h1 Hello From Haml!
822
+ %p= rdoc(:greetings)
823
+ ```
824
+
825
+ Since you cannot call Ruby from RDoc, you cannot use layouts written in
826
+ RDoc. However, it is possible to use another rendering engine for the
827
+ template than for the layout by passing the `:layout_engine` option.
828
+
829
+ #### AsciiDoc Templates
830
+
831
+ <table>
832
+ <tr>
833
+ <td>Dependency</td>
834
+ <td><a href="http://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td>
835
+ </tr>
836
+ <tr>
837
+ <td>File Extension</td>
838
+ <td><tt>.asciidoc</tt>, <tt>.adoc</tt> and <tt>.ad</tt></td>
839
+ </tr>
840
+ <tr>
841
+ <td>Example</td>
842
+ <td><tt>asciidoc :README, :layout_engine => :erb</tt></td>
843
+ </tr>
844
+ </table>
845
+
846
+ Since you cannot call Ruby methods directly from an AsciiDoc template, you
847
+ almost always want to pass locals to it.
848
+
849
+ #### Radius Templates
850
+
851
+ <table>
852
+ <tr>
853
+ <td>Dependency</td>
854
+ <td><a href="https://github.com/jlong/radius" title="Radius">Radius</a></td>
855
+ </tr>
856
+ <tr>
857
+ <td>File Extension</td>
858
+ <td><tt>.radius</tt></td>
859
+ </tr>
860
+ <tr>
861
+ <td>Example</td>
862
+ <td><tt>radius :index, :locals => { :key => 'value' }</tt></td>
863
+ </tr>
864
+ </table>
865
+
866
+ Since you cannot call Ruby methods directly from a Radius template, you
867
+ almost always want to pass locals to it.
868
+
869
+ #### Markaby Templates
870
+
871
+ <table>
872
+ <tr>
873
+ <td>Dependency</td>
874
+ <td><a href="https://markaby.github.io/" title="Markaby">Markaby</a></td>
875
+ </tr>
876
+ <tr>
877
+ <td>File Extension</td>
878
+ <td><tt>.mab</tt></td>
879
+ </tr>
880
+ <tr>
881
+ <td>Example</td>
882
+ <td><tt>markaby { h1 "Welcome!" }</tt></td>
883
+ </tr>
884
+ </table>
885
+
886
+ It also takes a block for inline templates (see [example](#inline-templates)).
887
+
888
+ #### RABL Templates
889
+
890
+ <table>
891
+ <tr>
892
+ <td>Dependency</td>
893
+ <td><a href="https://github.com/nesquena/rabl" title="Rabl">Rabl</a></td>
894
+ </tr>
895
+ <tr>
896
+ <td>File Extension</td>
897
+ <td><tt>.rabl</tt></td>
898
+ </tr>
899
+ <tr>
900
+ <td>Example</td>
901
+ <td><tt>rabl :index</tt></td>
902
+ </tr>
903
+ </table>
904
+
905
+ #### Slim Templates
906
+
907
+ <table>
908
+ <tr>
909
+ <td>Dependency</td>
910
+ <td><a href="http://slim-lang.com/" title="Slim Lang">Slim Lang</a></td>
911
+ </tr>
912
+ <tr>
913
+ <td>File Extension</td>
914
+ <td><tt>.slim</tt></td>
915
+ </tr>
916
+ <tr>
917
+ <td>Example</td>
918
+ <td><tt>slim :index</tt></td>
919
+ </tr>
920
+ </table>
921
+
922
+ #### Creole Templates
923
+
924
+ <table>
925
+ <tr>
926
+ <td>Dependency</td>
927
+ <td><a href="https://github.com/minad/creole" title="Creole">Creole</a></td>
928
+ </tr>
929
+ <tr>
930
+ <td>File Extension</td>
931
+ <td><tt>.creole</tt></td>
932
+ </tr>
933
+ <tr>
934
+ <td>Example</td>
935
+ <td><tt>creole :wiki, :layout_engine => :erb</tt></td>
936
+ </tr>
937
+ </table>
938
+
939
+ It is not possible to call methods from Creole, nor to pass locals to it. You
940
+ therefore will usually use it in combination with another rendering engine:
941
+
942
+ ```ruby
943
+ erb :overview, :locals => { :text => creole(:introduction) }
944
+ ```
945
+
946
+ Note that you may also call the `creole` method from within other templates:
947
+
948
+ ```ruby
949
+ %h1 Hello From Haml!
950
+ %p= creole(:greetings)
951
+ ```
952
+
953
+ Since you cannot call Ruby from Creole, you cannot use layouts written in
954
+ Creole. However, it is possible to use another rendering engine for the
955
+ template than for the layout by passing the `:layout_engine` option.
956
+
957
+ #### MediaWiki Templates
958
+
959
+ <table>
960
+ <tr>
961
+ <td>Dependency</td>
962
+ <td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td>
963
+ </tr>
964
+ <tr>
965
+ <td>File Extension</td>
966
+ <td><tt>.mediawiki</tt> and <tt>.mw</tt></td>
967
+ </tr>
968
+ <tr>
969
+ <td>Example</td>
970
+ <td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td>
971
+ </tr>
972
+ </table>
973
+
974
+ It is not possible to call methods from MediaWiki markup, nor to pass
975
+ locals to it. You therefore will usually use it in combination with
976
+ another rendering engine:
977
+
978
+ ```ruby
979
+ erb :overview, :locals => { :text => mediawiki(:introduction) }
980
+ ```
981
+
982
+ Note that you may also call the `mediawiki` method from within other
983
+ templates:
984
+
985
+ ```ruby
986
+ %h1 Hello From Haml!
987
+ %p= mediawiki(:greetings)
988
+ ```
989
+
990
+ Since you cannot call Ruby from MediaWiki, you cannot use layouts written in
991
+ MediaWiki. However, it is possible to use another rendering engine for the
992
+ template than for the layout by passing the `:layout_engine` option.
993
+
994
+ #### CoffeeScript Templates
995
+
996
+ <table>
997
+ <tr>
998
+ <td>Dependency</td>
999
+ <td>
1000
+ <a href="https://github.com/josh/ruby-coffee-script" title="Ruby CoffeeScript">
1001
+ CoffeeScript
1002
+ </a> and a
1003
+ <a href="https://github.com/sstephenson/execjs" title="ExecJS">
1004
+ way to execute javascript
1005
+ </a>
1006
+ </td>
1007
+ </tr>
1008
+ <tr>
1009
+ <td>File Extension</td>
1010
+ <td><tt>.coffee</tt></td>
1011
+ </tr>
1012
+ <tr>
1013
+ <td>Example</td>
1014
+ <td><tt>coffee :index</tt></td>
1015
+ </tr>
1016
+ </table>
1017
+
1018
+ #### Stylus Templates
1019
+
1020
+ <table>
1021
+ <tr>
1022
+ <td>Dependency</td>
1023
+ <td>
1024
+ <a href="https://github.com/forgecrafted/ruby-stylus" title="Ruby Stylus">
1025
+ Stylus
1026
+ </a> and a
1027
+ <a href="https://github.com/sstephenson/execjs" title="ExecJS">
1028
+ way to execute javascript
1029
+ </a>
1030
+ </td>
1031
+ </tr>
1032
+ <tr>
1033
+ <td>File Extension</td>
1034
+ <td><tt>.styl</tt></td>
1035
+ </tr>
1036
+ <tr>
1037
+ <td>Example</td>
1038
+ <td><tt>stylus :index</tt></td>
1039
+ </tr>
1040
+ </table>
1041
+
1042
+ Before being able to use Stylus templates, you need to load `stylus` and
1043
+ `stylus/tilt` first:
1044
+
1045
+ ```ruby
1046
+ require 'sinatra'
1047
+ require 'stylus'
1048
+ require 'stylus/tilt'
1049
+
1050
+ get '/' do
1051
+ stylus :example
1052
+ end
1053
+ ```
1054
+
1055
+ #### Yajl Templates
1056
+
1057
+ <table>
1058
+ <tr>
1059
+ <td>Dependency</td>
1060
+ <td><a href="https://github.com/brianmario/yajl-ruby" title="yajl-ruby">yajl-ruby</a></td>
1061
+ </tr>
1062
+ <tr>
1063
+ <td>File Extension</td>
1064
+ <td><tt>.yajl</tt></td>
1065
+ </tr>
1066
+ <tr>
1067
+ <td>Example</td>
1068
+ <td>
1069
+ <tt>
1070
+ yajl :index,
1071
+ :locals => { :key => 'qux' },
1072
+ :callback => 'present',
1073
+ :variable => 'resource'
1074
+ </tt>
1075
+ </td>
1076
+ </tr>
1077
+ </table>
1078
+
1079
+
1080
+ The template source is evaluated as a Ruby string, and the
1081
+ resulting json variable is converted using `#to_json`:
1082
+
1083
+ ```ruby
1084
+ json = { :foo => 'bar' }
1085
+ json[:baz] = key
1086
+ ```
1087
+
1088
+ The `:callback` and `:variable` options can be used to decorate the rendered
1089
+ object:
1090
+
1091
+ ```javascript
1092
+ var resource = {"foo":"bar","baz":"qux"};
1093
+ present(resource);
1094
+ ```
1095
+
1096
+ #### WLang Templates
1097
+
1098
+ <table>
1099
+ <tr>
1100
+ <td>Dependency</td>
1101
+ <td><a href="https://github.com/blambeau/wlang" title="WLang">WLang</a></td>
1102
+ </tr>
1103
+ <tr>
1104
+ <td>File Extension</td>
1105
+ <td><tt>.wlang</tt></td>
1106
+ </tr>
1107
+ <tr>
1108
+ <td>Example</td>
1109
+ <td><tt>wlang :index, :locals => { :key => 'value' }</tt></td>
1110
+ </tr>
1111
+ </table>
1112
+
1113
+ Since calling ruby methods is not idiomatic in WLang, you almost always
1114
+ want to pass locals to it. Layouts written in WLang and `yield` are
1115
+ supported, though.
1116
+
1117
+ ### Accessing Variables in Templates
1118
+
1119
+ Templates are evaluated within the same context as route handlers. Instance
1120
+ variables set in route handlers are directly accessible by templates:
1121
+
1122
+ ```ruby
1123
+ get '/:id' do
1124
+ @foo = Foo.find(params['id'])
1125
+ haml '%h1= @foo.name'
1126
+ end
1127
+ ```
1128
+
1129
+ Or, specify an explicit Hash of local variables:
1130
+
1131
+ ```ruby
1132
+ get '/:id' do
1133
+ foo = Foo.find(params['id'])
1134
+ haml '%h1= bar.name', :locals => { :bar => foo }
1135
+ end
1136
+ ```
1137
+
1138
+ This is typically used when rendering templates as partials from within
1139
+ other templates.
1140
+
1141
+ ### Templates with `yield` and nested layouts
1142
+
1143
+ A layout is usually just a template that calls `yield`.
1144
+ Such a template can be used either through the `:template` option as
1145
+ described above, or it can be rendered with a block as follows:
1146
+
1147
+ ```ruby
1148
+ erb :post, :layout => false do
1149
+ erb :index
1150
+ end
1151
+ ```
1152
+
1153
+ This code is mostly equivalent to `erb :index, :layout => :post`.
1154
+
1155
+ Passing blocks to rendering methods is most useful for creating nested
1156
+ layouts:
1157
+
1158
+ ```ruby
1159
+ erb :main_layout, :layout => false do
1160
+ erb :admin_layout do
1161
+ erb :user
1162
+ end
1163
+ end
1164
+ ```
1165
+
1166
+ This can also be done in fewer lines of code with:
1167
+
1168
+ ```ruby
1169
+ erb :admin_layout, :layout => :main_layout do
1170
+ erb :user
1171
+ end
1172
+ ```
1173
+
1174
+ Currently, the following rendering methods accept a block: `erb`, `haml`,
1175
+ `liquid`, `slim `, `wlang`. Also the general `render` method accepts a block.
1176
+
1177
+ ### Inline Templates
1178
+
1179
+ Templates may be defined at the end of the source file:
1180
+
1181
+ ```ruby
1182
+ require 'sinatra'
1183
+
1184
+ get '/' do
1185
+ haml :index
1186
+ end
1187
+
1188
+ __END__
1189
+
1190
+ @@ layout
1191
+ %html
1192
+ = yield
1193
+
1194
+ @@ index
1195
+ %div.title Hello world.
1196
+ ```
1197
+
1198
+ NOTE: Inline templates defined in the source file that requires sinatra are
1199
+ automatically loaded. Call `enable :inline_templates` explicitly if you
1200
+ have inline templates in other source files.
1201
+
1202
+ ### Named Templates
1203
+
1204
+ Templates may also be defined using the top-level `template` method:
1205
+
1206
+ ```ruby
1207
+ template :layout do
1208
+ "%html\n =yield\n"
1209
+ end
1210
+
1211
+ template :index do
1212
+ '%div.title Hello World!'
1213
+ end
1214
+
1215
+ get '/' do
1216
+ haml :index
1217
+ end
1218
+ ```
1219
+
1220
+ If a template named "layout" exists, it will be used each time a template
1221
+ is rendered. You can individually disable layouts by passing
1222
+ `:layout => false` or disable them by default via
1223
+ `set :haml, :layout => false`:
1224
+
1225
+ ```ruby
1226
+ get '/' do
1227
+ haml :index, :layout => !request.xhr?
1228
+ end
1229
+ ```
1230
+
1231
+ ### Associating File Extensions
1232
+
1233
+ To associate a file extension with a template engine, use
1234
+ `Tilt.register`. For instance, if you like to use the file extension
1235
+ `tt` for Textile templates, you can do the following:
1236
+
1237
+ ```ruby
1238
+ Tilt.register :tt, Tilt[:textile]
1239
+ ```
1240
+
1241
+ ### Adding Your Own Template Engine
1242
+
1243
+ First, register your engine with Tilt, then create a rendering method:
1244
+
1245
+ ```ruby
1246
+ Tilt.register :myat, MyAwesomeTemplateEngine
1247
+
1248
+ helpers do
1249
+ def myat(*args) render(:myat, *args) end
1250
+ end
1251
+
1252
+ get '/' do
1253
+ myat :index
1254
+ end
1255
+ ```
1256
+
1257
+ Renders `./views/index.myat`. Learn more about
1258
+ [Tilt](https://github.com/rtomayko/tilt#readme).
1259
+
1260
+ ### Using Custom Logic for Template Lookup
1261
+
1262
+ To implement your own template lookup mechanism you can write your
1263
+ own `#find_template` method:
1264
+
1265
+ ```ruby
1266
+ configure do
1267
+ set :views [ './views/a', './views/b' ]
1268
+ end
1269
+
1270
+ def find_template(views, name, engine, &block)
1271
+ Array(views).each do |v|
1272
+ super(v, name, engine, &block)
1273
+ end
1274
+ end
1275
+ ```
1276
+
1277
+ ## Filters
1278
+
1279
+ Before filters are evaluated before each request within the same context
1280
+ as the routes will be and can modify the request and response. Instance
1281
+ variables set in filters are accessible by routes and templates:
1282
+
1283
+ ```ruby
1284
+ before do
1285
+ @note = 'Hi!'
1286
+ request.path_info = '/foo/bar/baz'
1287
+ end
1288
+
1289
+ get '/foo/*' do
1290
+ @note #=> 'Hi!'
1291
+ params['splat'] #=> 'bar/baz'
1292
+ end
1293
+ ```
1294
+
1295
+ After filters are evaluated after each request within the same context
1296
+ as the routes will be and can also modify the request and response.
1297
+ Instance variables set in before filters and routes are accessible by
1298
+ after filters:
1299
+
1300
+ ```ruby
1301
+ after do
1302
+ puts response.status
1303
+ end
1304
+ ```
1305
+
1306
+ Note: Unless you use the `body` method rather than just returning a
1307
+ String from the routes, the body will not yet be available in the after
1308
+ filter, since it is generated later on.
1309
+
1310
+ Filters optionally take a pattern, causing them to be evaluated only if the
1311
+ request path matches that pattern:
1312
+
1313
+ ```ruby
1314
+ before '/protected/*' do
1315
+ authenticate!
1316
+ end
1317
+
1318
+ after '/create/:slug' do |slug|
1319
+ session[:last_slug] = slug
1320
+ end
1321
+ ```
1322
+
1323
+ Like routes, filters also take conditions:
1324
+
1325
+ ```ruby
1326
+ before :agent => /Songbird/ do
1327
+ # ...
1328
+ end
1329
+
1330
+ after '/blog/*', :host_name => 'example.com' do
1331
+ # ...
1332
+ end
1333
+ ```
1334
+
1335
+ ## Helpers
1336
+
1337
+ Use the top-level `helpers` method to define helper methods for use in
1338
+ route handlers and templates:
1339
+
1340
+ ```ruby
1341
+ helpers do
1342
+ def bar(name)
1343
+ "#{name}bar"
1344
+ end
1345
+ end
1346
+
1347
+ get '/:name' do
1348
+ bar(params['name'])
1349
+ end
1350
+ ```
1351
+
1352
+ Alternatively, helper methods can be separately defined in a module:
1353
+
1354
+ ```ruby
1355
+ module FooUtils
1356
+ def foo(name) "#{name}foo" end
1357
+ end
1358
+
1359
+ module BarUtils
1360
+ def bar(name) "#{name}bar" end
1361
+ end
1362
+
1363
+ helpers FooUtils, BarUtils
1364
+ ```
1365
+
1366
+ The effect is the same as including the modules in the application class.
1367
+
1368
+ ### Using Sessions
1369
+
1370
+ A session is used to keep state during requests. If activated, you have one
1371
+ session hash per user session:
1372
+
1373
+ ```ruby
1374
+ enable :sessions
1375
+
1376
+ get '/' do
1377
+ "value = " << session[:value].inspect
1378
+ end
1379
+
1380
+ get '/:value' do
1381
+ session['value'] = params['value']
1382
+ end
1383
+ ```
1384
+
1385
+ #### Session Secret Security
1386
+
1387
+ To improve security, the session data in the cookie is signed with a session
1388
+ secret using `HMAC-SHA1`. This session secret should optimally be a
1389
+ cryptographically secure random value of an appropriate length which for
1390
+ `HMAC-SHA1` is greater than or equal to 64 bytes (512 bits, 128 hex
1391
+ characters). You would be advised not to use a secret that is less than 32
1392
+ bytes of randomness (256 bits, 64 hex characters). It is therefore **very
1393
+ important** that you don't just make the secret up, but instead use a secure
1394
+ random number generator to create it. Humans are extremely bad at generating
1395
+ random values.
1396
+
1397
+ By default, a 32 byte secure random session secret is generated for you by
1398
+ Sinatra, but it will change with every restart of your application. If you
1399
+ have multiple instances of your application, and you let Sinatra generate the
1400
+ key, each instance would then have a different session key which is probably
1401
+ not what you want.
1402
+
1403
+ For better security and usability it's
1404
+ [recommended](https://12factor.net/config) that you generate a secure random
1405
+ secret and store it in an environment variable on each host running your
1406
+ application so that all of your application instances will share the same
1407
+ secret. You should periodically rotate this session secret to a new value.
1408
+ Here are some examples of how you might create a 64 byte secret and set it:
1409
+
1410
+ **Session Secret Generation**
1411
+
1412
+ ```text
1413
+ $ ruby -e "require 'securerandom'; puts SecureRandom.hex(64)"
1414
+ 99ae8af...snip...ec0f262ac
1415
+ ```
1416
+
1417
+ **Session Secret Generation (Bonus Points)**
1418
+
1419
+ Use the [sysrandom gem](https://github.com/cryptosphere/sysrandom#readme) to
1420
+ prefer use of system RNG facilities to generate random values instead of
1421
+ userspace `OpenSSL` which MRI Ruby currently defaults to:
1422
+
1423
+ ```text
1424
+ $ gem install sysrandom
1425
+ Building native extensions. This could take a while...
1426
+ Successfully installed sysrandom-1.x
1427
+ 1 gem installed
1428
+
1429
+ $ ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
1430
+ 99ae8af...snip...ec0f262ac
1431
+ ```
1432
+
1433
+ **Session Secret Environment Variable**
1434
+
1435
+ Set a `SESSION_SECRET` environment variable for Sinatra to the value you
1436
+ generated. Make this value persistent across reboots of your host. Since the
1437
+ method for doing this will vary across systems this is for illustrative
1438
+ purposes only:
1439
+
1440
+ ```bash
1441
+ # echo "export SESSION_SECRET=99ae8af...snip...ec0f262ac" >> ~/.bashrc
1442
+ ```
1443
+
1444
+ **Session Secret App Config**
1445
+
1446
+ Setup your app config to fail-safe to a secure random secret
1447
+ if the `SESSION_SECRET` environment variable is not available.
1448
+
1449
+ For bonus points use the [sysrandom
1450
+ gem](https://github.com/cryptosphere/sysrandom#readme) here as well:
1451
+
1452
+ ```ruby
1453
+ require 'securerandom'
1454
+ # -or- require 'sysrandom/securerandom'
1455
+ set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }
1456
+ ```
1457
+
1458
+ #### Session Config
1459
+
1460
+ If you want to configure it further, you may also store a hash with options
1461
+ in the `sessions` setting:
1462
+
1463
+ ```ruby
1464
+ set :sessions, :domain => 'foo.com'
1465
+ ```
1466
+
1467
+ To share your session across other apps on subdomains of foo.com, prefix the
1468
+ domain with a *.* like this instead:
1469
+
1470
+ ```ruby
1471
+ set :sessions, :domain => '.foo.com'
1472
+ ```
1473
+
1474
+ #### Choosing Your Own Session Middleware
1475
+
1476
+ Note that `enable :sessions` actually stores all data in a cookie. This
1477
+ might not always be what you want (storing lots of data will increase your
1478
+ traffic, for instance). You can use any Rack session middleware in order to
1479
+ do so, one of the following methods can be used:
1480
+
1481
+ ```ruby
1482
+ enable :sessions
1483
+ set :session_store, Rack::Session::Pool
1484
+ ```
1485
+
1486
+ Or to set up sessions with a hash of options:
1487
+
1488
+ ```ruby
1489
+ set :sessions, :expire_after => 2592000
1490
+ set :session_store, Rack::Session::Pool
1491
+ ```
1492
+
1493
+ Another option is to **not** call `enable :sessions`, but instead pull in
1494
+ your middleware of choice as you would any other middleware.
1495
+
1496
+ It is important to note that when using this method, session based
1497
+ protection **will not be enabled by default**.
1498
+
1499
+ The Rack middleware to do that will also need to be added:
1500
+
1501
+ ```ruby
1502
+ use Rack::Session::Pool, :expire_after => 2592000
1503
+ use Rack::Protection::RemoteToken
1504
+ use Rack::Protection::SessionHijacking
1505
+ ```
1506
+
1507
+ See '[Configuring attack protection](#configuring-attack-protection)' for more information.
1508
+
1509
+ ### Halting
1510
+
1511
+ To immediately stop a request within a filter or route use:
1512
+
1513
+ ```ruby
1514
+ halt
1515
+ ```
1516
+
1517
+ You can also specify the status when halting:
1518
+
1519
+ ```ruby
1520
+ halt 410
1521
+ ```
1522
+
1523
+ Or the body:
1524
+
1525
+ ```ruby
1526
+ halt 'this will be the body'
1527
+ ```
1528
+
1529
+ Or both:
1530
+
1531
+ ```ruby
1532
+ halt 401, 'go away!'
1533
+ ```
1534
+
1535
+ With headers:
1536
+
1537
+ ```ruby
1538
+ halt 402, {'Content-Type' => 'text/plain'}, 'revenge'
1539
+ ```
1540
+
1541
+ It is of course possible to combine a template with `halt`:
1542
+
1543
+ ```ruby
1544
+ halt erb(:error)
1545
+ ```
1546
+
1547
+ ### Passing
1548
+
1549
+ A route can punt processing to the next matching route using `pass`:
1550
+
1551
+ ```ruby
1552
+ get '/guess/:who' do
1553
+ pass unless params['who'] == 'Frank'
1554
+ 'You got me!'
1555
+ end
1556
+
1557
+ get '/guess/*' do
1558
+ 'You missed!'
1559
+ end
1560
+ ```
1561
+
1562
+ The route block is immediately exited and control continues with the next
1563
+ matching route. If no matching route is found, a 404 is returned.
1564
+
1565
+ ### Triggering Another Route
1566
+
1567
+ Sometimes `pass` is not what you want, instead you would like to get the
1568
+ result of calling another route. Simply use `call` to achieve this:
1569
+
1570
+ ```ruby
1571
+ get '/foo' do
1572
+ status, headers, body = call env.merge("PATH_INFO" => '/bar')
1573
+ [status, headers, body.map(&:upcase)]
1574
+ end
1575
+
1576
+ get '/bar' do
1577
+ "bar"
1578
+ end
1579
+ ```
1580
+
1581
+ Note that in the example above, you would ease testing and increase
1582
+ performance by simply moving `"bar"` into a helper used by both `/foo` and
1583
+ `/bar`.
1584
+
1585
+ If you want the request to be sent to the same application instance rather
1586
+ than a duplicate, use `call!` instead of `call`.
1587
+
1588
+ Check out the Rack specification if you want to learn more about `call`.
1589
+
1590
+ ### Setting Body, Status Code and Headers
1591
+
1592
+ It is possible and recommended to set the status code and response body with
1593
+ the return value of the route block. However, in some scenarios you might
1594
+ want to set the body at an arbitrary point in the execution flow. You can do
1595
+ so with the `body` helper method. If you do so, you can use that method from
1596
+ there on to access the body:
1597
+
1598
+ ```ruby
1599
+ get '/foo' do
1600
+ body "bar"
1601
+ end
1602
+
1603
+ after do
1604
+ puts body
1605
+ end
1606
+ ```
1607
+
1608
+ It is also possible to pass a block to `body`, which will be executed by the
1609
+ Rack handler (this can be used to implement streaming, [see "Return Values"](#return-values)).
1610
+
1611
+ Similar to the body, you can also set the status code and headers:
1612
+
1613
+ ```ruby
1614
+ get '/foo' do
1615
+ status 418
1616
+ headers \
1617
+ "Allow" => "BREW, POST, GET, PROPFIND, WHEN",
1618
+ "Refresh" => "Refresh: 20; https://ietf.org/rfc/rfc2324.txt"
1619
+ body "I'm a tea pot!"
1620
+ end
1621
+ ```
1622
+
1623
+ Like `body`, `headers` and `status` with no arguments can be used to access
1624
+ their current values.
1625
+
1626
+ ### Streaming Responses
1627
+
1628
+ Sometimes you want to start sending out data while still generating parts of
1629
+ the response body. In extreme examples, you want to keep sending data until
1630
+ the client closes the connection. You can use the `stream` helper to avoid
1631
+ creating your own wrapper:
1632
+
1633
+ ```ruby
1634
+ get '/' do
1635
+ stream do |out|
1636
+ out << "It's gonna be legen -\n"
1637
+ sleep 0.5
1638
+ out << " (wait for it) \n"
1639
+ sleep 1
1640
+ out << "- dary!\n"
1641
+ end
1642
+ end
1643
+ ```
1644
+
1645
+ This allows you to implement streaming APIs,
1646
+ [Server Sent Events](https://w3c.github.io/eventsource/), and can be used as
1647
+ the basis for [WebSockets](https://en.wikipedia.org/wiki/WebSocket). It can
1648
+ also be used to increase throughput if some but not all content depends on a
1649
+ slow resource.
1650
+
1651
+ Note that the streaming behavior, especially the number of concurrent
1652
+ requests, highly depends on the web server used to serve the application.
1653
+ Some servers might not even support streaming at all. If the server does not
1654
+ support streaming, the body will be sent all at once after the block passed
1655
+ to `stream` finishes executing. Streaming does not work at all with Shotgun.
1656
+
1657
+ If the optional parameter is set to `keep_open`, it will not call `close` on
1658
+ the stream object, allowing you to close it at any later point in the
1659
+ execution flow. This only works on evented servers, like Thin and Rainbows.
1660
+ Other servers will still close the stream:
1661
+
1662
+ ```ruby
1663
+ # long polling
1664
+
1665
+ set :server, :thin
1666
+ connections = []
1667
+
1668
+ get '/subscribe' do
1669
+ # register a client's interest in server events
1670
+ stream(:keep_open) do |out|
1671
+ connections << out
1672
+ # purge dead connections
1673
+ connections.reject!(&:closed?)
1674
+ end
1675
+ end
1676
+
1677
+ post '/:message' do
1678
+ connections.each do |out|
1679
+ # notify client that a new message has arrived
1680
+ out << params['message'] << "\n"
1681
+
1682
+ # indicate client to connect again
1683
+ out.close
1684
+ end
1685
+
1686
+ # acknowledge
1687
+ "message received"
1688
+ end
1689
+ ```
1690
+
1691
+ It's also possible for the client to close the connection when trying to
1692
+ write to the socket. Because of this, it's recommended to check
1693
+ `out.closed?` before trying to write.
1694
+
1695
+ ### Logging
1696
+
1697
+ In the request scope, the `logger` helper exposes a `Logger` instance:
1698
+
1699
+ ```ruby
1700
+ get '/' do
1701
+ logger.info "loading data"
1702
+ # ...
1703
+ end
1704
+ ```
1705
+
1706
+ This logger will automatically take your Rack handler's logging settings into
1707
+ account. If logging is disabled, this method will return a dummy object, so
1708
+ you do not have to worry about it in your routes and filters.
1709
+
1710
+ Note that logging is only enabled for `Sinatra::Application` by default, so
1711
+ if you inherit from `Sinatra::Base`, you probably want to enable it yourself:
1712
+
1713
+ ```ruby
1714
+ class MyApp < Sinatra::Base
1715
+ configure :production, :development do
1716
+ enable :logging
1717
+ end
1718
+ end
1719
+ ```
1720
+
1721
+ To avoid any logging middleware to be set up, set the `logging` setting to
1722
+ `nil`. However, keep in mind that `logger` will in that case return `nil`. A
1723
+ common use case is when you want to set your own logger. Sinatra will use
1724
+ whatever it will find in `env['rack.logger']`.
1725
+
1726
+ ### Mime Types
1727
+
1728
+ When using `send_file` or static files you may have mime types Sinatra
1729
+ doesn't understand. Use `mime_type` to register them by file extension:
1730
+
1731
+ ```ruby
1732
+ configure do
1733
+ mime_type :foo, 'text/foo'
1734
+ end
1735
+ ```
1736
+
1737
+ You can also use it with the `content_type` helper:
1738
+
1739
+ ```ruby
1740
+ get '/' do
1741
+ content_type :foo
1742
+ "foo foo foo"
1743
+ end
1744
+ ```
1745
+
1746
+ ### Generating URLs
1747
+
1748
+ For generating URLs you should use the `url` helper method, for instance, in
1749
+ Haml:
1750
+
1751
+ ```ruby
1752
+ %a{:href => url('/foo')} foo
1753
+ ```
1754
+
1755
+ It takes reverse proxies and Rack routers into account, if present.
1756
+
1757
+ This method is also aliased to `to` (see [below](#browser-redirect) for an example).
1758
+
1759
+ ### Browser Redirect
1760
+
1761
+ You can trigger a browser redirect with the `redirect` helper method:
1762
+
1763
+ ```ruby
1764
+ get '/foo' do
1765
+ redirect to('/bar')
1766
+ end
1767
+ ```
1768
+
1769
+ Any additional parameters are handled like arguments passed to `halt`:
1770
+
1771
+ ```ruby
1772
+ redirect to('/bar'), 303
1773
+ redirect 'http://www.google.com/', 'wrong place, buddy'
1774
+ ```
1775
+
1776
+ You can also easily redirect back to the page the user came from with
1777
+ `redirect back`:
1778
+
1779
+ ```ruby
1780
+ get '/foo' do
1781
+ "<a href='/bar'>do something</a>"
1782
+ end
1783
+
1784
+ get '/bar' do
1785
+ do_something
1786
+ redirect back
1787
+ end
1788
+ ```
1789
+
1790
+ To pass arguments with a redirect, either add them to the query:
1791
+
1792
+ ```ruby
1793
+ redirect to('/bar?sum=42')
1794
+ ```
1795
+
1796
+ Or use a session:
1797
+
1798
+ ```ruby
1799
+ enable :sessions
1800
+
1801
+ get '/foo' do
1802
+ session[:secret] = 'foo'
1803
+ redirect to('/bar')
1804
+ end
1805
+
1806
+ get '/bar' do
1807
+ session[:secret]
1808
+ end
1809
+ ```
1810
+
1811
+ ### Cache Control
1812
+
1813
+ Setting your headers correctly is the foundation for proper HTTP caching.
1814
+
1815
+ You can easily set the Cache-Control header like this:
1816
+
1817
+ ```ruby
1818
+ get '/' do
1819
+ cache_control :public
1820
+ "cache it!"
1821
+ end
1822
+ ```
1823
+
1824
+ Pro tip: Set up caching in a before filter:
1825
+
1826
+ ```ruby
1827
+ before do
1828
+ cache_control :public, :must_revalidate, :max_age => 60
1829
+ end
1830
+ ```
1831
+
1832
+ If you are using the `expires` helper to set the corresponding header,
1833
+ `Cache-Control` will be set automatically for you:
1834
+
1835
+ ```ruby
1836
+ before do
1837
+ expires 500, :public, :must_revalidate
1838
+ end
1839
+ ```
1840
+
1841
+ To properly use caches, you should consider using `etag` or `last_modified`.
1842
+ It is recommended to call those helpers *before* doing any heavy lifting, as
1843
+ they will immediately flush a response if the client already has the current
1844
+ version in its cache:
1845
+
1846
+ ```ruby
1847
+ get "/article/:id" do
1848
+ @article = Article.find params['id']
1849
+ last_modified @article.updated_at
1850
+ etag @article.sha1
1851
+ erb :article
1852
+ end
1853
+ ```
1854
+
1855
+ It is also possible to use a
1856
+ [weak ETag](https://en.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation):
1857
+
1858
+ ```ruby
1859
+ etag @article.sha1, :weak
1860
+ ```
1861
+
1862
+ These helpers will not do any caching for you, but rather feed the necessary
1863
+ information to your cache. If you are looking for a quick
1864
+ reverse-proxy caching solution, try
1865
+ [rack-cache](https://github.com/rtomayko/rack-cache#readme):
1866
+
1867
+ ```ruby
1868
+ require "rack/cache"
1869
+ require "sinatra"
1870
+
1871
+ use Rack::Cache
1872
+
1873
+ get '/' do
1874
+ cache_control :public, :max_age => 36000
1875
+ sleep 5
1876
+ "hello"
1877
+ end
1878
+ ```
1879
+
1880
+ Use the `:static_cache_control` setting (see [below](#cache-control)) to add
1881
+ `Cache-Control` header info to static files.
1882
+
1883
+ According to RFC 2616, your application should behave differently if the
1884
+ If-Match or If-None-Match header is set to `*`, depending on whether the
1885
+ resource requested is already in existence. Sinatra assumes resources for
1886
+ safe (like get) and idempotent (like put) requests are already in existence,
1887
+ whereas other resources (for instance post requests) are treated as new
1888
+ resources. You can change this behavior by passing in a `:new_resource`
1889
+ option:
1890
+
1891
+ ```ruby
1892
+ get '/create' do
1893
+ etag '', :new_resource => true
1894
+ Article.create
1895
+ erb :new_article
1896
+ end
1897
+ ```
1898
+
1899
+ If you still want to use a weak ETag, pass in a `:kind` option:
1900
+
1901
+ ```ruby
1902
+ etag '', :new_resource => true, :kind => :weak
1903
+ ```
1904
+
1905
+ ### Sending Files
1906
+
1907
+ To return the contents of a file as the response, you can use the `send_file`
1908
+ helper method:
1909
+
1910
+ ```ruby
1911
+ get '/' do
1912
+ send_file 'foo.png'
1913
+ end
1914
+ ```
1915
+
1916
+ It also takes options:
1917
+
1918
+ ```ruby
1919
+ send_file 'foo.png', :type => :jpg
1920
+ ```
1921
+
1922
+ The options are:
1923
+
1924
+ <dl>
1925
+ <dt>filename</dt>
1926
+ <dd>File name to be used in the response,
1927
+ defaults to the real file name.</dd>
1928
+ <dt>last_modified</dt>
1929
+ <dd>Value for Last-Modified header, defaults to the file's mtime.</dd>
1930
+
1931
+ <dt>type</dt>
1932
+ <dd>Value for Content-Type header, guessed from the file extension if
1933
+ missing.</dd>
1934
+
1935
+ <dt>disposition</dt>
1936
+ <dd>
1937
+ Value for Content-Disposition header, possible values: <tt>nil</tt>
1938
+ (default), <tt>:attachment</tt> and <tt>:inline</tt>
1939
+ </dd>
1940
+
1941
+ <dt>length</dt>
1942
+ <dd>Value for Content-Length header, defaults to file size.</dd>
1943
+
1944
+ <dt>status</dt>
1945
+ <dd>
1946
+ Status code to be sent. Useful when sending a static file as an error
1947
+ page. If supported by the Rack handler, other means than streaming
1948
+ from the Ruby process will be used. If you use this helper method,
1949
+ Sinatra will automatically handle range requests.
1950
+ </dd>
1951
+ </dl>
1952
+
1953
+ ### Accessing the Request Object
1954
+
1955
+ The incoming request object can be accessed from request level (filter,
1956
+ routes, error handlers) through the `request` method:
1957
+
1958
+ ```ruby
1959
+ # app running on http://example.com/example
1960
+ get '/foo' do
1961
+ t = %w[text/css text/html application/javascript]
1962
+ request.accept # ['text/html', '*/*']
1963
+ request.accept? 'text/xml' # true
1964
+ request.preferred_type(t) # 'text/html'
1965
+ request.body # request body sent by the client (see below)
1966
+ request.scheme # "http"
1967
+ request.script_name # "/example"
1968
+ request.path_info # "/foo"
1969
+ request.port # 80
1970
+ request.request_method # "GET"
1971
+ request.query_string # ""
1972
+ request.content_length # length of request.body
1973
+ request.media_type # media type of request.body
1974
+ request.host # "example.com"
1975
+ request.get? # true (similar methods for other verbs)
1976
+ request.form_data? # false
1977
+ request["some_param"] # value of some_param parameter. [] is a shortcut to the params hash.
1978
+ request.referrer # the referrer of the client or '/'
1979
+ request.user_agent # user agent (used by :agent condition)
1980
+ request.cookies # hash of browser cookies
1981
+ request.xhr? # is this an ajax request?
1982
+ request.url # "http://example.com/example/foo"
1983
+ request.path # "/example/foo"
1984
+ request.ip # client IP address
1985
+ request.secure? # false (would be true over ssl)
1986
+ request.forwarded? # true (if running behind a reverse proxy)
1987
+ request.env # raw env hash handed in by Rack
1988
+ end
1989
+ ```
1990
+
1991
+ Some options, like `script_name` or `path_info`, can also be written:
1992
+
1993
+ ```ruby
1994
+ before { request.path_info = "/" }
1995
+
1996
+ get "/" do
1997
+ "all requests end up here"
1998
+ end
1999
+ ```
2000
+
2001
+ The `request.body` is an IO or StringIO object:
2002
+
2003
+ ```ruby
2004
+ post "/api" do
2005
+ request.body.rewind # in case someone already read it
2006
+ data = JSON.parse request.body.read
2007
+ "Hello #{data['name']}!"
2008
+ end
2009
+ ```
2010
+
2011
+ ### Attachments
2012
+
2013
+ You can use the `attachment` helper to tell the browser the response should
2014
+ be stored on disk rather than displayed in the browser:
2015
+
2016
+ ```ruby
2017
+ get '/' do
2018
+ attachment
2019
+ "store it!"
2020
+ end
2021
+ ```
2022
+
2023
+ You can also pass it a file name:
2024
+
2025
+ ```ruby
2026
+ get '/' do
2027
+ attachment "info.txt"
2028
+ "store it!"
2029
+ end
2030
+ ```
2031
+
2032
+ ### Dealing with Date and Time
2033
+
2034
+ Sinatra offers a `time_for` helper method that generates a Time object from
2035
+ the given value. It is also able to convert `DateTime`, `Date` and similar
2036
+ classes:
2037
+
2038
+ ```ruby
2039
+ get '/' do
2040
+ pass if Time.now > time_for('Dec 23, 2016')
2041
+ "still time"
2042
+ end
2043
+ ```
2044
+
2045
+ This method is used internally by `expires`, `last_modified` and akin. You
2046
+ can therefore easily extend the behavior of those methods by overriding
2047
+ `time_for` in your application:
2048
+
2049
+ ```ruby
2050
+ helpers do
2051
+ def time_for(value)
2052
+ case value
2053
+ when :yesterday then Time.now - 24*60*60
2054
+ when :tomorrow then Time.now + 24*60*60
2055
+ else super
2056
+ end
2057
+ end
2058
+ end
2059
+
2060
+ get '/' do
2061
+ last_modified :yesterday
2062
+ expires :tomorrow
2063
+ "hello"
2064
+ end
2065
+ ```
2066
+
2067
+ ### Looking Up Template Files
2068
+
2069
+ The `find_template` helper is used to find template files for rendering:
2070
+
2071
+ ```ruby
2072
+ find_template settings.views, 'foo', Tilt[:haml] do |file|
2073
+ puts "could be #{file}"
2074
+ end
2075
+ ```
2076
+
2077
+ This is not really useful. But it is useful that you can actually override
2078
+ this method to hook in your own lookup mechanism. For instance, if you want
2079
+ to be able to use more than one view directory:
2080
+
2081
+ ```ruby
2082
+ set :views, ['views', 'templates']
2083
+
2084
+ helpers do
2085
+ def find_template(views, name, engine, &block)
2086
+ Array(views).each { |v| super(v, name, engine, &block) }
2087
+ end
2088
+ end
2089
+ ```
2090
+
2091
+ Another example would be using different directories for different engines:
2092
+
2093
+ ```ruby
2094
+ set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views'
2095
+
2096
+ helpers do
2097
+ def find_template(views, name, engine, &block)
2098
+ _, folder = views.detect { |k,v| engine == Tilt[k] }
2099
+ folder ||= views[:default]
2100
+ super(folder, name, engine, &block)
2101
+ end
2102
+ end
2103
+ ```
2104
+
2105
+ You can also easily wrap this up in an extension and share with others!
2106
+
2107
+ Note that `find_template` does not check if the file really exists but
2108
+ rather calls the given block for all possible paths. This is not a
2109
+ performance issue, since `render` will use `break` as soon as a file is
2110
+ found. Also, template locations (and content) will be cached if you are not
2111
+ running in development mode. You should keep that in mind if you write a
2112
+ really crazy method.
2113
+
2114
+ ## Configuration
2115
+
2116
+ Run once, at startup, in any environment:
2117
+
2118
+ ```ruby
2119
+ configure do
2120
+ # setting one option
2121
+ set :option, 'value'
2122
+
2123
+ # setting multiple options
2124
+ set :a => 1, :b => 2
2125
+
2126
+ # same as `set :option, true`
2127
+ enable :option
2128
+
2129
+ # same as `set :option, false`
2130
+ disable :option
2131
+
2132
+ # you can also have dynamic settings with blocks
2133
+ set(:css_dir) { File.join(views, 'css') }
2134
+ end
2135
+ ```
2136
+
2137
+ Run only when the environment (`APP_ENV` environment variable) is set to
2138
+ `:production`:
2139
+
2140
+ ```ruby
2141
+ configure :production do
2142
+ ...
2143
+ end
2144
+ ```
2145
+
2146
+ Run when the environment is set to either `:production` or `:test`:
2147
+
2148
+ ```ruby
2149
+ configure :production, :test do
2150
+ ...
2151
+ end
2152
+ ```
2153
+
2154
+ You can access those options via `settings`:
2155
+
2156
+ ```ruby
2157
+ configure do
2158
+ set :foo, 'bar'
2159
+ end
2160
+
2161
+ get '/' do
2162
+ settings.foo? # => true
2163
+ settings.foo # => 'bar'
2164
+ ...
2165
+ end
2166
+ ```
2167
+
2168
+ ### Configuring attack protection
2169
+
2170
+ Sinatra is using
2171
+ [Rack::Protection](https://github.com/sinatra/sinatra/tree/master/rack-protection#readme) to
2172
+ defend your application against common, opportunistic attacks. You can
2173
+ easily disable this behavior (which will open up your application to tons
2174
+ of common vulnerabilities):
2175
+
2176
+ ```ruby
2177
+ disable :protection
2178
+ ```
2179
+
2180
+ To skip a single defense layer, set `protection` to an options hash:
2181
+
2182
+ ```ruby
2183
+ set :protection, :except => :path_traversal
2184
+ ```
2185
+ You can also hand in an array in order to disable a list of protections:
2186
+
2187
+ ```ruby
2188
+ set :protection, :except => [:path_traversal, :session_hijacking]
2189
+ ```
2190
+
2191
+ By default, Sinatra will only set up session based protection if `:sessions`
2192
+ have been enabled. See '[Using Sessions](#using-sessions)'. Sometimes you may want to set up
2193
+ sessions "outside" of the Sinatra app, such as in the config.ru or with a
2194
+ separate `Rack::Builder` instance. In that case you can still set up session
2195
+ based protection by passing the `:session` option:
2196
+
2197
+ ```ruby
2198
+ set :protection, :session => true
2199
+ ```
2200
+
2201
+ ### Available Settings
2202
+
2203
+ <dl>
2204
+ <dt>absolute_redirects</dt>
2205
+ <dd>
2206
+ If disabled, Sinatra will allow relative redirects, however, Sinatra
2207
+ will no longer conform with RFC 2616 (HTTP 1.1), which only allows
2208
+ absolute redirects.
2209
+ </dd>
2210
+ <dd>
2211
+ Enable if your app is running behind a reverse proxy that has not been
2212
+ set up properly. Note that the <tt>url</tt> helper will still produce
2213
+ absolute URLs, unless you pass in <tt>false</tt> as the second
2214
+ parameter.
2215
+ </dd>
2216
+ <dd>Disabled by default.</dd>
2217
+
2218
+ <dt>add_charset</dt>
2219
+ <dd>
2220
+ Mime types the <tt>content_type</tt> helper will automatically add the
2221
+ charset info to. You should add to it rather than overriding this
2222
+ option: <tt>settings.add_charset << "application/foobar"</tt>
2223
+ </dd>
2224
+
2225
+ <dt>app_file</dt>
2226
+ <dd>
2227
+ Path to the main application file, used to detect project root, views
2228
+ and public folder and inline templates.
2229
+ </dd>
2230
+
2231
+ <dt>bind</dt>
2232
+ <dd>
2233
+ IP address to bind to (default: <tt>0.0.0.0</tt> <em>or</em>
2234
+ <tt>localhost</tt> if your `environment` is set to development). Only
2235
+ used for built-in server.
2236
+ </dd>
2237
+
2238
+ <dt>default_encoding</dt>
2239
+ <dd>Encoding to assume if unknown (defaults to <tt>"utf-8"</tt>).</dd>
2240
+
2241
+ <dt>dump_errors</dt>
2242
+ <dd>Display errors in the log.</dd>
2243
+
2244
+ <dt>environment</dt>
2245
+ <dd>
2246
+ Current environment. Defaults to <tt>ENV['APP_ENV']</tt>, or
2247
+ <tt>"development"</tt> if not available.
2248
+ </dd>
2249
+
2250
+ <dt>logging</dt>
2251
+ <dd>Use the logger.</dd>
2252
+
2253
+ <dt>lock</dt>
2254
+ <dd>
2255
+ Places a lock around every request, only running processing on request
2256
+ per Ruby process concurrently.
2257
+ </dd>
2258
+ <dd>Enabled if your app is not thread-safe. Disabled by default.</dd>
2259
+
2260
+ <dt>method_override</dt>
2261
+ <dd>
2262
+ Use <tt>_method</tt> magic to allow put/delete forms in browsers that
2263
+ don't support it.
2264
+ </dd>
2265
+
2266
+ <dt>mustermann_opts</dt>
2267
+ <dd>
2268
+ A default hash of options to pass to Mustermann.new when compiling routing
2269
+ paths.
2270
+ </dd>
2271
+
2272
+ <dt>port</dt>
2273
+ <dd>Port to listen on. Only used for built-in server.</dd>
2274
+
2275
+ <dt>prefixed_redirects</dt>
2276
+ <dd>
2277
+ Whether or not to inser