jellyfish 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30753a754648b5b6d9a72d9165c763b3e4db9383
4
+ data.tar.gz: dc78ee33ce6341c19ff571bb78ab2485ef5f2fbd
5
+ SHA512:
6
+ metadata.gz: aa1d7ff64073a23ffb0b8d4d218e5e2f3ec898c102ad2ee7786c2af062792be705b2941ca98f7fc3e59b095ec88945b3788b065eb22b48e00eae041be930843e
7
+ data.tar.gz: 1f33f9aa6f449b034e81c1fb33e30e91c91a580e1310230e487649606add2afeaddf13fa10ea9a9daac1dc878797a390d6211e7486315ff9ee19b34012acb225
data/.gitignore CHANGED
@@ -1,3 +1,2 @@
1
1
  pkg
2
2
  *.rbc
3
- sinatra
data/.travis.yml CHANGED
@@ -6,5 +6,6 @@ env:
6
6
 
7
7
  rvm:
8
8
  - 1.9.3
9
+ - 2.0.0
9
10
  - rbx-head
10
11
  - jruby-head
data/CHANGES.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # CHANGES
2
2
 
3
+ ## Jellyfish 0.8.0
4
+
5
+ ### Incompatible changes
6
+
7
+ * Now there's no longer Jellyfish#controller but Jellyfish.controller,
8
+ as there's no much point for making the controller per-instance.
9
+ You do this to override the controller method instead:
10
+
11
+ ``` ruby
12
+ class MyApp
13
+ include Jellyfish
14
+ def self.controller
15
+ MyController
16
+ end
17
+ class MyController < Jellyfish::Controller
18
+ def hi
19
+ 'hi'
20
+ end
21
+ end
22
+ get{ hi }
23
+ end
24
+ ```
25
+
26
+ * You can also change the controller by assigning it. The same as above:
27
+
28
+ ``` ruby
29
+ class MyApp
30
+ include Jellyfish
31
+ class MyController < Jellyfish::Controller
32
+ def hi
33
+ 'hi'
34
+ end
35
+ end
36
+ controller MyController
37
+ get{ hi }
38
+ end
39
+ ```
40
+
41
+ ### Enhancements for Jellyfish core
42
+
43
+ * Introduced Jellyfish.controller_include which makes it easy to pick
44
+ modules to be included in built-in controller.
45
+ * Introduced Controller#halt as a short hand for `throw :halt`
46
+ * Now default route is `//`. Using `get{ 'Hello, World!' }` is effectively
47
+ the same as `get(//){ 'Hello, World!' }`
48
+ * Now inheritance works.
49
+ * Now it raises TypeError if passing a route doesn't respond to :match.
50
+ * Now Jellyfish would find the most suitable error handler to handle
51
+ errors, i.e. It would find the error handler which would handle the
52
+ nearest exception class in the ancestors chain. Previously it would
53
+ only find the first one which matches, ignoring the rest. It would
54
+ also cache the result upon a lookup.
55
+
56
+ ### Enhancements for Jellyfish extension
57
+
58
+ * Added `Jellyfish::ChunkedBody` which is similar to `Sinatra::Stream`.
59
+
60
+ * Added `Jellyfish::MultiAction` which gives you some kind of ability to do
61
+ before or after filters. See README.md for usage.
62
+
63
+ * Added `Jellyfish::NormalizedParams` which gives you some kind of Sinatra
64
+ flavoured params.
65
+
66
+ * Added `Jellyfish::NormalizedPath` which would unescape incoming PATH_INFO
67
+ so you could match '/f%C3%B6%C3%B6' with '/föö'.
68
+
69
+ ### Enhancements for Jellyfish::Sinatra
70
+
71
+ * Now `Jellyfish::Sinatra` includes `Jellyfish::MultiAction`,
72
+ `Jellyfish::NormalizedParams`, and `Jellyfish::NormalizedPath`.
73
+
3
74
  ## Jellyfish 0.6.0 -- 2012-11-02
4
75
 
5
76
  ### Enhancements for Jellyfish core
data/README.md CHANGED
@@ -13,7 +13,7 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
13
13
  ## DESCRIPTION:
14
14
 
15
15
  Pico web framework for building API-centric web applications.
16
- For Rack applications or Rack middlewares. Under 200 lines of code.
16
+ For Rack applications or Rack middlewares. Around 200 lines of code.
17
17
 
18
18
  ## DESIGN:
19
19
 
@@ -23,18 +23,21 @@ For Rack applications or Rack middlewares. Under 200 lines of code.
23
23
  * Embrace simplicity over convenience
24
24
  * Don't make things complicated only for _some_ convenience, but
25
25
  _great_ convenience, or simply stay simple for simplicity.
26
+ * More features are added as extensions
26
27
 
27
28
  ## FEATURES:
28
29
 
29
30
  * Minimal
30
31
  * Simple
31
- * No templates
32
+ * Modular
33
+ * No templates (You could use [tilt](https://github.com/rtomayko/tilt))
32
34
  * No ORM
33
35
  * No `dup` in `call`
34
36
  * Regular expression routes, e.g. `get %r{^/(?<id>\d+)$}`
35
37
  * String routes, e.g. `get '/'`
36
38
  * Custom routes, e.g. `get Matcher.new`
37
- * Build for either Rack applications or Rack middlewares
39
+ * Build for either Rack applications or Rack middleware
40
+ * Include extensions for more features (There's a Sinatra extension)
38
41
 
39
42
  ## WHY?
40
43
 
@@ -65,6 +68,13 @@ use Rack::ContentType, 'text/plain'
65
68
  run Tank.new
66
69
  ```
67
70
 
71
+ <!---
72
+ GET /
73
+ [200,
74
+ {'Content-Length' => '12', 'Content-Type' => 'text/plain'},
75
+ ["Jelly Kelly\n"]]
76
+ -->
77
+
68
78
  ### Regular expression routes
69
79
 
70
80
  ``` ruby
@@ -80,6 +90,13 @@ use Rack::ContentType, 'text/plain'
80
90
  run Tank.new
81
91
  ```
82
92
 
93
+ <!---
94
+ GET /123
95
+ [200,
96
+ {'Content-Length' => '11', 'Content-Type' => 'text/plain'},
97
+ ["Jelly #123\n"]]
98
+ -->
99
+
83
100
  ### Custom matcher routes
84
101
 
85
102
  ``` ruby
@@ -100,6 +117,13 @@ use Rack::ContentType, 'text/plain'
100
117
  run Tank.new
101
118
  ```
102
119
 
120
+ <!---
121
+ GET /hctam
122
+ [200,
123
+ {'Content-Length' => '5', 'Content-Type' => 'text/plain'},
124
+ ["true\n"]]
125
+ -->
126
+
103
127
  ### Different HTTP status and custom headers
104
128
 
105
129
  ``` ruby
@@ -119,6 +143,14 @@ use Rack::ContentType, 'text/plain'
119
143
  run Tank.new
120
144
  ```
121
145
 
146
+ <!---
147
+ POST /
148
+ [201,
149
+ {'Content-Length' => '18', 'Content-Type' => 'text/plain',
150
+ 'X-Jellyfish-Life' => '100', 'X-Jellyfish-Mana' => '200'},
151
+ ["Jellyfish 100/200\n"]]
152
+ -->
153
+
122
154
  ### Redirect helper
123
155
 
124
156
  ``` ruby
@@ -134,6 +166,17 @@ use Rack::ContentType, 'text/plain'
134
166
  run Tank.new
135
167
  ```
136
168
 
169
+ <!---
170
+ GET /lookup
171
+ body = File.read("#{File.dirname(
172
+ File.expand_path(__FILE__))}/../lib/jellyfish/public/302.html").
173
+ gsub('VAR_URL', ':///')
174
+ [302,
175
+ {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/html',
176
+ 'Location' => ':///'},
177
+ [body]]
178
+ -->
179
+
137
180
  ### Crash-proof
138
181
 
139
182
  ``` ruby
@@ -149,6 +192,15 @@ use Rack::ContentType, 'text/plain'
149
192
  run Tank.new
150
193
  ```
151
194
 
195
+ <!---
196
+ GET /crash
197
+ body = File.read("#{File.dirname(
198
+ File.expand_path(__FILE__))}/../lib/jellyfish/public/500.html")
199
+ [500,
200
+ {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/html'},
201
+ [body]]
202
+ -->
203
+
152
204
  ### Custom error handler
153
205
 
154
206
  ``` ruby
@@ -168,7 +220,74 @@ use Rack::ContentType, 'text/plain'
168
220
  run Tank.new
169
221
  ```
170
222
 
171
- ### Custom controller
223
+ <!---
224
+ GET /yell
225
+ body = case RUBY_ENGINE
226
+ when 'jruby'
227
+ "No one hears you: (eval):9:in `Tank'\n"
228
+ when 'rbx'
229
+ "No one hears you: kernel/delta/kernel.rb:81:in `yell (method_missing)'\n"
230
+ else
231
+ "No one hears you: (eval):9:in `block in <class:Tank>'\n"
232
+ end
233
+ [403,
234
+ {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/plain'},
235
+ [body]]
236
+ -->
237
+
238
+ ### Access Rack::Request and params
239
+
240
+ ``` ruby
241
+ require 'jellyfish'
242
+ class Tank
243
+ include Jellyfish
244
+ get '/report' do
245
+ "Your name is #{request.params['name']}\n"
246
+ end
247
+ end
248
+ use Rack::ContentLength
249
+ use Rack::ContentType, 'text/plain'
250
+ run Tank.new
251
+ ```
252
+
253
+ <!---
254
+ GET /report?name=godfat
255
+ [200,
256
+ {'Content-Length' => '20', 'Content-Type' => 'text/plain'},
257
+ ["Your name is godfat\n"]]
258
+ -->
259
+
260
+ ### Re-dispatch the request with modified env
261
+
262
+ ``` ruby
263
+ require 'jellyfish'
264
+ class Tank
265
+ include Jellyfish
266
+ get '/report' do
267
+ status, headers, body = jellyfish.call(env.merge('PATH_INFO' => '/info'))
268
+ self.status status
269
+ self.headers headers
270
+ self.body body
271
+ end
272
+ get('/info'){ "OK\n" }
273
+ end
274
+ use Rack::ContentLength
275
+ use Rack::ContentType, 'text/plain'
276
+ run Tank.new
277
+ ```
278
+
279
+ <!---
280
+ GET /report
281
+ [200,
282
+ {'Content-Length' => '3', 'Content-Type' => 'text/plain'},
283
+ ["OK\n"]]
284
+ -->
285
+
286
+ ### Include custom helper in built-in controller
287
+
288
+ Basically it's the same as defining a custom controller and then
289
+ include the helper. This is merely a short hand. See next section
290
+ for defining a custom controller.
172
291
 
173
292
  ``` ruby
174
293
  require 'jellyfish'
@@ -178,33 +297,92 @@ class Heater
178
297
  temperature
179
298
  end
180
299
 
181
- def controller; Controller; end
182
- class Controller < Jellyfish::Controller
300
+ module Helper
183
301
  def temperature
184
302
  "30\u{2103}\n"
185
303
  end
186
304
  end
305
+ controller_include Helper
187
306
  end
188
307
  use Rack::ContentLength
189
308
  use Rack::ContentType, 'text/plain'
190
309
  run Heater.new
191
310
  ```
192
311
 
193
- ### Sinatra flavored controller
312
+ <!---
313
+ GET /status
314
+ [200,
315
+ {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
316
+ ["30\u{2103}\n"]]
317
+ -->
318
+
319
+ ### Define custom controller manually
320
+
321
+ This is effectively the same as defining a helper module as above and
322
+ include it, but more flexible and extensible.
323
+
324
+ ``` ruby
325
+ require 'jellyfish'
326
+ class Heater
327
+ include Jellyfish
328
+ get '/status' do
329
+ temperature
330
+ end
331
+
332
+ class Controller < Jellyfish::Controller
333
+ def temperature
334
+ "30\u{2103}\n"
335
+ end
336
+ end
337
+ controller Controller
338
+ end
339
+ use Rack::ContentLength
340
+ use Rack::ContentType, 'text/plain'
341
+ run Heater.new
342
+ ```
194
343
 
195
- Currently support:
344
+ <!---
345
+ GET /status
346
+ [200,
347
+ {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
348
+ ["30\u{2103}\n"]]
349
+ -->
196
350
 
197
- * Indifferent params
198
- * Force params encoding to Encoding.default_external
351
+ ### Extension: MultiActions (Filters)
199
352
 
200
353
  ``` ruby
201
354
  require 'jellyfish'
202
355
  class Tank
203
356
  include Jellyfish
204
- class MyController < Jellyfish::Controller
205
- include Jellyfish::Sinatra
357
+ controller_include Jellyfish::MultiActions
358
+
359
+ get do # wildcard before filter
360
+ @state = 'jumps'
206
361
  end
207
- def controller; MyController; end
362
+ get do
363
+ "Jelly #{@state}.\n"
364
+ end
365
+ end
366
+ use Rack::ContentLength
367
+ use Rack::ContentType, 'text/plain'
368
+ run Tank.new
369
+ ```
370
+
371
+ <!---
372
+ GET /123
373
+ [200,
374
+ {'Content-Length' => '13', 'Content-Type' => 'text/plain'},
375
+ ["Jelly jumps.\n"]]
376
+ -->
377
+
378
+ ### Extension: NormalizedParams (with force_encoding)
379
+
380
+ ``` ruby
381
+ require 'jellyfish'
382
+ class Tank
383
+ include Jellyfish
384
+ controller_include Jellyfish::NormalizedParams
385
+
208
386
  get %r{^/(?<id>\d+)$} do
209
387
  "Jelly ##{params[:id]}\n"
210
388
  end
@@ -214,16 +392,78 @@ use Rack::ContentType, 'text/plain'
214
392
  run Tank.new
215
393
  ```
216
394
 
217
- ### Using NewRelic?
395
+ <!---
396
+ GET /123
397
+ [200,
398
+ {'Content-Length' => '11', 'Content-Type' => 'text/plain'},
399
+ ["Jelly #123\n"]]
400
+ -->
401
+
402
+ ### Extension: NormalizedPath (with unescaping)
218
403
 
219
404
  ``` ruby
220
405
  require 'jellyfish'
221
406
  class Tank
222
407
  include Jellyfish
223
- class MyController < Jellyfish::Controller
224
- include Jellyfish::NewRelic
408
+ controller_include Jellyfish::NormalizedPath
409
+
410
+ get "/\u{56e7}" do
411
+ "#{env['PATH_INFO']}=#{path_info}\n"
412
+ end
413
+ end
414
+ use Rack::ContentLength
415
+ use Rack::ContentType, 'text/plain'
416
+ run Tank.new
417
+ ```
418
+
419
+ <!---
420
+ GET /%E5%9B%A7
421
+ [200,
422
+ {'Content-Length' => '16', 'Content-Type' => 'text/plain'},
423
+ ["/%E5%9B%A7=/\u{56e7}\n"]]
424
+ -->
425
+
426
+ ### Extension: Sinatra flavoured controller
427
+
428
+ It's an extension collection contains:
429
+
430
+ * MultiActions
431
+ * NormalizedParams
432
+ * NormalizedPath
433
+
434
+ ``` ruby
435
+ require 'jellyfish'
436
+ class Tank
437
+ include Jellyfish
438
+ controller_include Jellyfish::Sinatra
439
+
440
+ get do # wildcard before filter
441
+ @state = 'jumps'
442
+ end
443
+ get %r{^/(?<id>\d+)$} do
444
+ "Jelly ##{params[:id]} #{@state}.\n"
225
445
  end
226
- def controller; MyController; end
446
+ end
447
+ use Rack::ContentLength
448
+ use Rack::ContentType, 'text/plain'
449
+ run Tank.new
450
+ ```
451
+
452
+ <!---
453
+ GET /123
454
+ [200,
455
+ {'Content-Length' => '18', 'Content-Type' => 'text/plain'},
456
+ ["Jelly #123 jumps.\n"]]
457
+ -->
458
+
459
+ ### Extension: NewRelic
460
+
461
+ ``` ruby
462
+ require 'jellyfish'
463
+ class Tank
464
+ include Jellyfish
465
+ controller_include Jellyfish::NewRelic
466
+
227
467
  get '/' do
228
468
  "OK\n"
229
469
  end
@@ -237,6 +477,48 @@ run Tank.new
237
477
  NewRelic::Agent.manual_start(:developer_mode => true)
238
478
  ```
239
479
 
480
+ <!---
481
+ GET /
482
+ [200,
483
+ {'Content-Length' => '3', 'Content-Type' => 'text/plain'},
484
+ ["OK\n"]]
485
+ -->
486
+
487
+ ### Extension: Using multiple extensions with custom controller
488
+
489
+ This is effectively the same as using Jellyfish::Sinatra extension.
490
+ Note that the controller should be assigned lastly in order to include
491
+ modules remembered in controller_include.
492
+
493
+ ``` ruby
494
+ require 'jellyfish'
495
+ class Tank
496
+ include Jellyfish
497
+ class MyController < Jellyfish::Controller
498
+ include Jellyfish::MultiActions
499
+ end
500
+ controller_include NormalizedParams, NormalizedPath
501
+ controller MyController
502
+
503
+ get do # wildcard before filter
504
+ @state = 'jumps'
505
+ end
506
+ get %r{^/(?<id>\d+)$} do
507
+ "Jelly ##{params[:id]} #{@state}.\n"
508
+ end
509
+ end
510
+ use Rack::ContentLength
511
+ use Rack::ContentType, 'text/plain'
512
+ run Tank.new
513
+ ```
514
+
515
+ <!---
516
+ GET /123
517
+ [200,
518
+ {'Content-Length' => '18', 'Content-Type' => 'text/plain'},
519
+ ["Jelly #123 jumps.\n"]]
520
+ -->
521
+
240
522
  ### Jellyfish as a middleware
241
523
 
242
524
  ``` ruby
@@ -261,6 +543,146 @@ use Heater
261
543
  run Tank.new
262
544
  ```
263
545
 
546
+ <!---
547
+ GET /
548
+ [200,
549
+ {'Content-Length' => '12', 'Content-Type' => 'text/plain'},
550
+ ["Jelly Kelly\n"]]
551
+ -->
552
+
553
+ ### Modify response as a middleware
554
+
555
+ ``` ruby
556
+ require 'jellyfish'
557
+ class Heater
558
+ include Jellyfish
559
+ get '/status' do
560
+ status, headers, body = jellyfish.app.call(env)
561
+ self.status status
562
+ self.headers headers
563
+ self.body body
564
+ headers_merge('X-Temperature' => "30\u{2103}")
565
+ end
566
+ end
567
+
568
+ class Tank
569
+ include Jellyfish
570
+ get '/status' do
571
+ "See header X-Temperature\n"
572
+ end
573
+ end
574
+
575
+ use Rack::ContentLength
576
+ use Rack::ContentType, 'text/plain'
577
+ use Heater
578
+ run Tank.new
579
+ ```
580
+
581
+ <!---
582
+ GET /status
583
+ [200,
584
+ {'Content-Length' => '25', 'Content-Type' => 'text/plain',
585
+ 'X-Temperature' => "30\u{2103}"},
586
+ ["See header X-Temperature\n"]]
587
+ -->
588
+
589
+ ### Default headers as a middleware
590
+
591
+ ``` ruby
592
+ require 'jellyfish'
593
+ class Heater
594
+ include Jellyfish
595
+ get '/status' do
596
+ status, headers, body = jellyfish.app.call(env)
597
+ self.status status
598
+ self.headers({'X-Temperature' => "30\u{2103}"}.merge(headers))
599
+ self.body body
600
+ end
601
+ end
602
+
603
+ class Tank
604
+ include Jellyfish
605
+ get '/status' do
606
+ headers_merge('X-Temperature' => "35\u{2103}")
607
+ "\n"
608
+ end
609
+ end
610
+
611
+ use Rack::ContentLength
612
+ use Rack::ContentType, 'text/plain'
613
+ use Heater
614
+ run Tank.new
615
+ ```
616
+
617
+ <!---
618
+ GET /status
619
+ [200,
620
+ {'Content-Length' => '1', 'Content-Type' => 'text/plain',
621
+ 'X-Temperature' => "35\u{2103}"},
622
+ ["\n"]]
623
+ -->
624
+
625
+ ### Simple before action as a middleware
626
+
627
+ ``` ruby
628
+ require 'jellyfish'
629
+ class Heater
630
+ include Jellyfish
631
+ get '/status' do
632
+ env['temperature'] = 30
633
+ forward
634
+ end
635
+ end
636
+
637
+ class Tank
638
+ include Jellyfish
639
+ get '/status' do
640
+ "#{env['temperature']}\u{2103}\n"
641
+ end
642
+ end
643
+
644
+ use Rack::ContentLength
645
+ use Rack::ContentType, 'text/plain'
646
+ use Heater
647
+ run Tank.new
648
+ ```
649
+
650
+ <!---
651
+ GET /status
652
+ [200,
653
+ {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
654
+ ["30\u{2103}\n"]]
655
+ -->
656
+
657
+ ### Halt in before action
658
+
659
+ ``` ruby
660
+ require 'jellyfish'
661
+ class Tank
662
+ include Jellyfish
663
+ controller_include Jellyfish::MultiActions
664
+
665
+ get do # wildcard before filter
666
+ body "Done!\n"
667
+ halt
668
+ end
669
+ get '/' do
670
+ "Never reach.\n"
671
+ end
672
+ end
673
+
674
+ use Rack::ContentLength
675
+ use Rack::ContentType, 'text/plain'
676
+ run Tank.new
677
+ ```
678
+
679
+ <!---
680
+ GET /status
681
+ [200,
682
+ {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
683
+ ["Done!\n"]]
684
+ -->
685
+
264
686
  ### One huge tank
265
687
 
266
688
  ``` ruby
@@ -289,6 +711,13 @@ end
289
711
  run HugeTank
290
712
  ```
291
713
 
714
+ <!---
715
+ GET /status
716
+ [200,
717
+ {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
718
+ ["30\u{2103}\n"]]
719
+ -->
720
+
292
721
  ### Raise exceptions
293
722
 
294
723
  ``` ruby
@@ -315,17 +744,48 @@ use Protector
315
744
  run Tank.new
316
745
  ```
317
746
 
318
- ### Chunked transfer encoding (streaming)
747
+ <!---
748
+ GET /
749
+ [200,
750
+ {'Content-Length' => '29', 'Content-Type' => 'text/plain'},
751
+ ["Protected: Oops, tank broken\n"]]
752
+ -->
753
+
754
+ ### Chunked transfer encoding (streaming) with Jellyfish::ChunkedBody
319
755
 
320
756
  You would need a proper server setup.
321
757
  Here's an example with Rainbows and fibers:
322
758
 
759
+ ``` ruby
760
+ class Tank
761
+ include Jellyfish
762
+ get '/chunked' do
763
+ ChunkedBody.new{ |out|
764
+ (0..4).each{ |i| out.call("#{i}\n") }
765
+ }
766
+ end
767
+ end
768
+ use Rack::Chunked
769
+ use Rack::ContentType, 'text/plain'
770
+ run Tank.new
771
+ ```
772
+
773
+ <!---
774
+ GET /chunked
775
+ [200,
776
+ {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'},
777
+ ["2\r\n0\n\r\n", "2\r\n1\n\r\n", "2\r\n2\n\r\n",
778
+ "2\r\n3\n\r\n", "2\r\n4\n\r\n", "0\r\n\r\n"]]
779
+ -->
780
+
781
+ ### Chunked transfer encoding (streaming) with custom body
782
+
323
783
  ``` ruby
324
784
  class Tank
325
785
  include Jellyfish
326
786
  class Body
327
787
  def each
328
- (0..4).each{ |i| yield "#{i}\n"; Rainbows.sleep(0.1) }
788
+ (0..4).each{ |i| yield "#{i}\n" }
329
789
  end
330
790
  end
331
791
  get '/chunked' do
@@ -337,6 +797,14 @@ use Rack::ContentType, 'text/plain'
337
797
  run Tank.new
338
798
  ```
339
799
 
800
+ <!---
801
+ GET /chunked
802
+ [200,
803
+ {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'},
804
+ ["2\r\n0\n\r\n", "2\r\n1\n\r\n", "2\r\n2\n\r\n",
805
+ "2\r\n3\n\r\n", "2\r\n4\n\r\n", "0\r\n\r\n"]]
806
+ -->
807
+
340
808
  ## CONTRIBUTORS:
341
809
 
342
810
  * Lin Jen-Shin (@godfat)
@@ -345,7 +813,7 @@ run Tank.new
345
813
 
346
814
  Apache License 2.0
347
815
 
348
- Copyright (c) 2012, Lin Jen-Shin (godfat)
816
+ Copyright (c) 2012-2013, Lin Jen-Shin (godfat)
349
817
 
350
818
  Licensed under the Apache License, Version 2.0 (the "License");
351
819
  you may not use this file except in compliance with the License.