sinatra 1.3.0.e → 1.3.0.f

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

data/lib/sinatra/main.rb CHANGED
@@ -16,7 +16,7 @@ module Sinatra
16
16
  op.on('-x') { set :lock, true }
17
17
  op.on('-e env') { |val| set :environment, val.to_sym }
18
18
  op.on('-s server') { |val| set :server, val }
19
- op.on('-p port') { |val| set :port, val.to_i }
19
+ op.on('-p port') { |val| set :port, Integer(val) }
20
20
  op.on('-o addr') { |val| set :bind, val }
21
21
  }.parse!(ARGV.dup)
22
22
  end
@@ -252,7 +252,7 @@ TEMPLATE = <<-HTML # :nodoc:
252
252
 
253
253
  <div id="get">
254
254
  <h3 id="get-info">GET</h3>
255
- <% unless req.GET.empty? %>
255
+ <% if req.GET and not req.GET.empty? %>
256
256
  <table class="req">
257
257
  <tr>
258
258
  <th>Variable</th>
@@ -273,7 +273,7 @@ TEMPLATE = <<-HTML # :nodoc:
273
273
 
274
274
  <div id="post">
275
275
  <h3 id="post-info">POST</h3>
276
- <% unless req.POST.empty? %>
276
+ <% if req.POST and not req.POST.empty? %>
277
277
  <table class="req">
278
278
  <tr>
279
279
  <th>Variable</th>
@@ -1,3 +1,3 @@
1
1
  module Sinatra
2
- VERSION = '1.3.0.e'
2
+ VERSION = '1.3.0.f'
3
3
  end
data/sinatra.gemspec CHANGED
@@ -1,8 +1,9 @@
1
- load './lib/sinatra/version.rb'
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ require 'sinatra/version'
2
3
 
3
4
  Gem::Specification.new 'sinatra', Sinatra::VERSION do |s|
4
- s.description = "Classy web-development dressed in a DSL"
5
- s.summary = s.description
5
+ s.description = "Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort."
6
+ s.summary = "Classy web-development dressed in a DSL"
6
7
  s.authors = ["Blake Mizerany", "Ryan Tomayko", "Simon Rozet", "Konstantin Haase"]
7
8
  s.email = "sinatrarb@googlegroups.com"
8
9
  s.homepage = "http://www.sinatrarb.com/"
@@ -11,6 +12,7 @@ Gem::Specification.new 'sinatra', Sinatra::VERSION do |s|
11
12
  s.extra_rdoc_files = s.files.select { |p| p =~ /^README/ } << 'LICENSE'
12
13
  s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc]
13
14
 
14
- s.add_dependency 'rack', '~> 1.3'
15
- s.add_dependency 'tilt', '~> 1.3'
15
+ s.add_dependency 'rack', '~> 1.3'
16
+ s.add_dependency 'rack-protection', '~> 1.1'
17
+ s.add_dependency 'tilt', '~> 1.3'
16
18
  end
data/test/contest.rb CHANGED
@@ -1,38 +1,67 @@
1
+ # Copyright (c) 2009 Damian Janowski and Michel Martens for Citrusbyte
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
1
20
  require "test/unit"
2
21
 
3
- # Test::Unit loads a default test if the suite is empty, and the only
4
- # purpose of that test is to fail. As having empty contexts is a common
5
- # practice, we decided to overwrite TestSuite#empty? in order to
6
- # allow them. Having a failure when no tests have been defined seems
7
- # counter-intuitive.
22
+ # Test::Unit loads a default test if the suite is empty, whose purpose is to
23
+ # fail. Since having empty contexts is a common practice, we decided to
24
+ # overwrite TestSuite#empty? in order to allow them. Having a failure when no
25
+ # tests have been defined seems counter-intuitive.
8
26
  class Test::Unit::TestSuite
9
- unless method_defined?(:empty?)
10
- def empty?
11
- false
12
- end
27
+ def empty?
28
+ false
13
29
  end
14
30
  end
15
31
 
16
- # We added setup, test and context as class methods, and the instance
17
- # method setup now iterates on the setup blocks. Note that all setup
18
- # blocks must be defined with the block syntax. Adding a setup instance
19
- # method defeats the purpose of this library.
32
+ # Contest adds +teardown+, +test+ and +context+ as class methods, and the
33
+ # instance methods +setup+ and +teardown+ now iterate on the corresponding
34
+ # blocks. Note that all setup and teardown blocks must be defined with the
35
+ # block syntax. Adding setup or teardown instance methods defeats the purpose
36
+ # of this library.
20
37
  class Test::Unit::TestCase
21
- def self.setup(&block)
22
- setup_blocks << block
38
+ def self.setup(&block) setup_blocks << block end
39
+ def self.teardown(&block) teardown_blocks << block end
40
+ def self.setup_blocks() @setup_blocks ||= [] end
41
+ def self.teardown_blocks() @teardown_blocks ||= [] end
42
+
43
+ def setup_blocks(base = self.class)
44
+ setup_blocks base.superclass if base.superclass.respond_to? :setup_blocks
45
+ base.setup_blocks.each do |block|
46
+ instance_eval(&block)
47
+ end
23
48
  end
24
49
 
25
- def setup
26
- self.class.setup_blocks.each do |block|
50
+ def teardown_blocks(base = self.class)
51
+ teardown_blocks base.superclass if base.superclass.respond_to? :teardown_blocks
52
+ base.teardown_blocks.each do |block|
27
53
  instance_eval(&block)
28
54
  end
29
55
  end
30
56
 
31
- def self.context(name, &block)
32
- subclass = Class.new(self.superclass)
33
- subclass.setup_blocks.unshift(*setup_blocks)
34
- subclass.class_eval(&block)
35
- const_set(context_name(name), subclass)
57
+ alias setup setup_blocks
58
+ alias teardown teardown_blocks
59
+
60
+ def self.context(*name, &block)
61
+ subclass = Class.new(self)
62
+ remove_tests(subclass)
63
+ subclass.class_eval(&block) if block_given?
64
+ const_set(context_name(name.join(" ")), subclass)
36
65
  end
37
66
 
38
67
  def self.test(name, &block)
@@ -46,12 +75,10 @@ class Test::Unit::TestCase
46
75
 
47
76
  private
48
77
 
49
- def self.setup_blocks
50
- @setup_blocks ||= []
51
- end
52
-
53
78
  def self.context_name(name)
54
- "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
79
+ # "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
80
+ name = "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}"
81
+ name.tr(" ", "_").to_sym
55
82
  end
56
83
 
57
84
  def self.test_name(name)
@@ -59,6 +86,13 @@ private
59
86
  end
60
87
 
61
88
  def self.sanitize_name(name)
62
- name.gsub(/\W+/, ' ').strip
89
+ # name.gsub(/\W+/, ' ').strip
90
+ name.gsub(/\W+/, ' ')
91
+ end
92
+
93
+ def self.remove_tests(subclass)
94
+ subclass.public_instance_methods.grep(/^test_/).each do |meth|
95
+ subclass.send(:undef_method, meth.to_sym)
96
+ end
63
97
  end
64
98
  end
data/test/filter_test.rb CHANGED
@@ -114,7 +114,7 @@ class BeforeFilterTest < Test::Unit::TestCase
114
114
  mock_app {
115
115
  before { ran_filter = true }
116
116
  set :static, true
117
- set :public, File.dirname(__FILE__)
117
+ set :public_folder, File.dirname(__FILE__)
118
118
  }
119
119
  get "/#{File.basename(__FILE__)}"
120
120
  assert ok?
@@ -237,7 +237,7 @@ class AfterFilterTest < Test::Unit::TestCase
237
237
  mock_app {
238
238
  after { ran_filter = true }
239
239
  set :static, true
240
- set :public, File.dirname(__FILE__)
240
+ set :public_folder, File.dirname(__FILE__)
241
241
  }
242
242
  get "/#{File.basename(__FILE__)}"
243
243
  assert ok?
data/test/helpers_test.rb CHANGED
@@ -6,22 +6,117 @@ class HelpersTest < Test::Unit::TestCase
6
6
  assert true
7
7
  end
8
8
 
9
- describe 'status' do
10
- setup do
11
- mock_app {
12
- get '/' do
13
- status 207
14
- nil
15
- end
16
- }
9
+ def status_app(code, &block)
10
+ code += 2 if [204, 205, 304].include? code
11
+ block ||= proc { }
12
+ mock_app do
13
+ get '/' do
14
+ status code
15
+ instance_eval(&block).inspect
16
+ end
17
17
  end
18
+ get '/'
19
+ end
18
20
 
21
+ describe 'status' do
19
22
  it 'sets the response status code' do
20
- get '/'
23
+ status_app 207
21
24
  assert_equal 207, response.status
22
25
  end
23
26
  end
24
27
 
28
+ describe 'not_found?' do
29
+ it 'is true for status == 404' do
30
+ status_app(404) { not_found? }
31
+ assert_body 'true'
32
+ end
33
+
34
+ it 'is false for status > 404' do
35
+ status_app(405) { not_found? }
36
+ assert_body 'false'
37
+ end
38
+
39
+ it 'is false for status < 404' do
40
+ status_app(403) { not_found? }
41
+ assert_body 'false'
42
+ end
43
+ end
44
+
45
+ describe 'informational?' do
46
+ it 'is true for 1xx status' do
47
+ status_app(100 + rand(100)) { informational? }
48
+ assert_body 'true'
49
+ end
50
+
51
+ it 'is false for status > 199' do
52
+ status_app(200 + rand(400)) { informational? }
53
+ assert_body 'false'
54
+ end
55
+ end
56
+
57
+ describe 'success?' do
58
+ it 'is true for 2xx status' do
59
+ status_app(200 + rand(100)) { success? }
60
+ assert_body 'true'
61
+ end
62
+
63
+ it 'is false for status < 200' do
64
+ status_app(100 + rand(100)) { success? }
65
+ assert_body 'false'
66
+ end
67
+
68
+ it 'is false for status > 299' do
69
+ status_app(300 + rand(300)) { success? }
70
+ assert_body 'false'
71
+ end
72
+ end
73
+
74
+ describe 'redirect?' do
75
+ it 'is true for 3xx status' do
76
+ status_app(300 + rand(100)) { redirect? }
77
+ assert_body 'true'
78
+ end
79
+
80
+ it 'is false for status < 300' do
81
+ status_app(200 + rand(100)) { redirect? }
82
+ assert_body 'false'
83
+ end
84
+
85
+ it 'is false for status > 399' do
86
+ status_app(400 + rand(200)) { redirect? }
87
+ assert_body 'false'
88
+ end
89
+ end
90
+
91
+ describe 'client_error?' do
92
+ it 'is true for 4xx status' do
93
+ status_app(400 + rand(100)) { client_error? }
94
+ assert_body 'true'
95
+ end
96
+
97
+ it 'is false for status < 400' do
98
+ status_app(200 + rand(200)) { client_error? }
99
+ assert_body 'false'
100
+ end
101
+
102
+ it 'is false for status > 499' do
103
+ status_app(500 + rand(100)) { client_error? }
104
+ assert_body 'false'
105
+ end
106
+ end
107
+
108
+ describe 'server_error?' do
109
+ it 'is true for 5xx status' do
110
+ status_app(500 + rand(100)) { server_error? }
111
+ assert_body 'true'
112
+ end
113
+
114
+ it 'is false for status < 500' do
115
+ status_app(200 + rand(300)) { server_error? }
116
+ assert_body 'false'
117
+ end
118
+ end
119
+
25
120
  describe 'body' do
26
121
  it 'takes a block for defered body generation' do
27
122
  mock_app {
@@ -112,6 +207,22 @@ class HelpersTest < Test::Unit::TestCase
112
207
  assert_equal 'http://example.org:444/foo', response['Location']
113
208
  end
114
209
 
210
+ it 'uses 303 for post requests if request is HTTP 1.1' do
211
+ mock_app { post('/') { redirect '/'} }
212
+ post '/', {}, 'HTTP_VERSION' => 'HTTP/1.1'
213
+ assert_equal 303, status
214
+ assert_equal '', body
215
+ assert_equal 'http://example.org/', response['Location']
216
+ end
217
+
218
+ it 'uses 302 for post requests if request is HTTP 1.0' do
219
+ mock_app { post('/') { redirect '/'} }
220
+ post '/', {}, 'HTTP_VERSION' => 'HTTP/1.0'
221
+ assert_equal 302, status
222
+ assert_equal '', body
223
+ assert_equal 'http://example.org/', response['Location']
224
+ end
225
+
115
226
  it 'works behind a reverse proxy' do
116
227
  mock_app do
117
228
  get '/' do
@@ -269,7 +380,7 @@ class HelpersTest < Test::Unit::TestCase
269
380
  enable :sessions
270
381
 
271
382
  get '/' do
272
- assert session.empty?
383
+ assert session[:foo].nil?
273
384
  session[:foo] = 'bar'
274
385
  redirect '/hi'
275
386
  end
@@ -481,6 +592,45 @@ class HelpersTest < Test::Unit::TestCase
481
592
  end
482
593
  end
483
594
 
595
+ describe 'attachment' do
596
+ def attachment_app(filename=nil)
597
+ mock_app {
598
+ get '/attachment' do
599
+ attachment filename
600
+ response.write("<sinatra></sinatra>")
601
+ end
602
+ }
603
+ end
604
+
605
+ it 'sets the Content-Type response header' do
606
+ attachment_app('test.xml')
607
+ get '/attachment'
608
+ assert_equal 'application/xml;charset=utf-8', response['Content-Type']
609
+ assert_equal '<sinatra></sinatra>', body
610
+ end
611
+
612
+ it 'sets the Content-Type response header without extname' do
613
+ attachment_app('test')
614
+ get '/attachment'
615
+ assert_equal 'text/html;charset=utf-8', response['Content-Type']
616
+ assert_equal '<sinatra></sinatra>', body
617
+ end
618
+
619
+ it 'sets the Content-Type response header without extname' do
620
+ mock_app do
621
+ get '/attachment' do
622
+ content_type :atom
623
+ attachment 'test.xml'
624
+ response.write("<sinatra></sinatra>")
625
+ end
626
+ end
627
+ get '/attachment'
628
+ assert_equal 'application/atom+xml', response['Content-Type']
629
+ assert_equal '<sinatra></sinatra>', body
630
+ end
631
+
632
+ end
633
+
484
634
  describe 'send_file' do
485
635
  setup do
486
636
  @file = File.dirname(__FILE__) + '/file.txt'
@@ -663,7 +813,7 @@ class HelpersTest < Test::Unit::TestCase
663
813
  end
664
814
 
665
815
  get '/boom' do
666
- expires '1000'
816
+ expires '9999'
667
817
  end
668
818
  end
669
819
  end
@@ -719,7 +869,7 @@ class HelpersTest < Test::Unit::TestCase
719
869
  end
720
870
  end
721
871
  wrapper = Object.new.extend Sinatra::Helpers
722
- @last_modified_time = wrapper.send :time_for, last_modified_time
872
+ @last_modified_time = wrapper.time_for last_modified_time
723
873
  end
724
874
 
725
875
  # fixes strange missing test error when running complete test suite.
@@ -817,6 +967,11 @@ class HelpersTest < Test::Unit::TestCase
817
967
  etag 'FOO'
818
968
  'Boo!'
819
969
  end
970
+
971
+ post '/' do
972
+ etag 'FOO'
973
+ 'Matches!'
974
+ end
820
975
  }
821
976
  end
822
977
 
@@ -831,6 +986,24 @@ class HelpersTest < Test::Unit::TestCase
831
986
  assert_equal 'Boo!', body
832
987
  end
833
988
 
989
+ it 'returns a body when posting with no If-None-Match header' do
990
+ post '/'
991
+ assert_equal 200, status
992
+ assert_equal 'Matches!', body
993
+ end
994
+
995
+ it 'returns a body when conditional post matches' do
996
+ post '/', {}, { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
997
+ assert_equal 200, status
998
+ assert_equal 'Matches!', body
999
+ end
1000
+
1001
+ it 'halts with 412 when conditional post misses' do
1002
+ post '/', {}, { 'HTTP_IF_NONE_MATCH' => '"BAR"' }
1003
+ assert_equal 412, status
1004
+ assert_equal '', body
1005
+ end
1006
+
834
1007
  it 'halts when a conditional GET matches' do
835
1008
  get '/', {}, { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
836
1009
  assert_equal 304, status