sinatra 1.4.3 → 1.4.4

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.

Binary file
Binary file
@@ -1,3 +1,3 @@
1
1
  module Sinatra
2
- VERSION = '1.4.3'
2
+ VERSION = '1.4.4'
3
3
  end
@@ -156,7 +156,6 @@ class BaseTest < Test::Unit::TestCase
156
156
 
157
157
  class TestMiddlewareContentLength < Sinatra::Base
158
158
  get '/forward' do
159
- res = forward
160
159
  'From after explicit forward!'
161
160
  end
162
161
  end
@@ -45,10 +45,10 @@ class CompileTest < Test::Unit::TestCase
45
45
 
46
46
  converts "/", %r{\A/\z}
47
47
  parses "/", "/", {}
48
-
48
+
49
49
  converts "/foo", %r{\A/foo\z}
50
50
  parses "/foo", "/foo", {}
51
-
51
+
52
52
  converts "/:foo", %r{\A/([^/?#]+)\z}
53
53
  parses "/:foo", "/foo", "foo" => "foo"
54
54
  parses "/:foo", "/foo.bar", "foo" => "foo.bar"
@@ -58,68 +58,68 @@ class CompileTest < Test::Unit::TestCase
58
58
  fails "/:foo", "/foo/bar"
59
59
  fails "/:foo", "/"
60
60
  fails "/:foo", "/foo/"
61
-
61
+
62
62
  converts "/föö", %r{\A/f%[Cc]3%[Bb]6%[Cc]3%[Bb]6\z}
63
63
  parses "/föö", "/f%C3%B6%C3%B6", {}
64
-
64
+
65
65
  converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
66
66
  parses "/:foo/:bar", "/foo/bar", "foo" => "foo", "bar" => "bar"
67
-
67
+
68
68
  converts "/hello/:person", %r{\A/hello/([^/?#]+)\z}
69
69
  parses "/hello/:person", "/hello/Frank", "person" => "Frank"
70
-
70
+
71
71
  converts "/?:foo?/?:bar?", %r{\A/?([^/?#]+)?/?([^/?#]+)?\z}
72
72
  parses "/?:foo?/?:bar?", "/hello/world", "foo" => "hello", "bar" => "world"
73
73
  parses "/?:foo?/?:bar?", "/hello", "foo" => "hello", "bar" => nil
74
74
  parses "/?:foo?/?:bar?", "/", "foo" => nil, "bar" => nil
75
75
  parses "/?:foo?/?:bar?", "", "foo" => nil, "bar" => nil
76
-
76
+
77
77
  converts "/*", %r{\A/(.*?)\z}
78
78
  parses "/*", "/", "splat" => ""
79
79
  parses "/*", "/foo", "splat" => "foo"
80
80
  parses "/*", "/foo/bar", "splat" => "foo/bar"
81
-
81
+
82
82
  converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
83
83
  parses "/:foo/*", "/foo/bar/baz", "foo" => "foo", "splat" => "bar/baz"
84
-
84
+
85
85
  converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
86
86
  parses "/:foo/:bar", "/user@example.com/name", "foo" => "user@example.com", "bar" => "name"
87
-
87
+
88
88
  converts "/test$/", %r{\A/test(?:\$|%24)/\z}
89
89
  parses "/test$/", "/test$/", {}
90
-
90
+
91
91
  converts "/te+st/", %r{\A/te(?:\+|%2[Bb])st/\z}
92
92
  parses "/te+st/", "/te+st/", {}
93
93
  fails "/te+st/", "/test/"
94
94
  fails "/te+st/", "/teeest/"
95
-
95
+
96
96
  converts "/test(bar)/", %r{\A/test(?:\(|%28)bar(?:\)|%29)/\z}
97
97
  parses "/test(bar)/", "/test(bar)/", {}
98
-
98
+
99
99
  converts "/path with spaces", %r{\A/path(?:%20|(?:\+|%2[Bb]))with(?:%20|(?:\+|%2[Bb]))spaces\z}
100
100
  parses "/path with spaces", "/path%20with%20spaces", {}
101
101
  parses "/path with spaces", "/path%2Bwith%2Bspaces", {}
102
102
  parses "/path with spaces", "/path+with+spaces", {}
103
-
103
+
104
104
  converts "/foo&bar", %r{\A/foo(?:&|%26)bar\z}
105
105
  parses "/foo&bar", "/foo&bar", {}
106
-
106
+
107
107
  converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
108
108
  parses "/:foo/*", "/hello%20world/how%20are%20you", "foo" => "hello%20world", "splat" => "how%20are%20you"
109
-
109
+
110
110
  converts "/*/foo/*/*", %r{\A/(.*?)/foo/(.*?)/(.*?)\z}
111
111
  parses "/*/foo/*/*", "/bar/foo/bling/baz/boom", "splat" => ["bar", "bling", "baz/boom"]
112
112
  fails "/*/foo/*/*", "/bar/foo/baz"
113
-
113
+
114
114
  converts "/test.bar", %r{\A/test(?:\.|%2[Ee])bar\z}
115
115
  parses "/test.bar", "/test.bar", {}
116
116
  fails "/test.bar", "/test0bar"
117
-
117
+
118
118
  converts "/:file.:ext", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)\z}
119
119
  parses "/:file.:ext", "/pony.jpg", "file" => "pony", "ext" => "jpg"
120
120
  parses "/:file.:ext", "/pony%2Ejpg", "file" => "pony", "ext" => "jpg"
121
121
  fails "/:file.:ext", "/.jpg"
122
-
122
+
123
123
  converts "/:name.?:format?", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])?((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)?\z}
124
124
  parses "/:name.?:format?", "/foo", "name" => "foo", "format" => nil
125
125
  parses "/:name.?:format?", "/foo.bar", "name" => "foo", "format" => "bar"
@@ -129,41 +129,41 @@ class CompileTest < Test::Unit::TestCase
129
129
  parses "/:name?.:format?", "/.bar", "name" => nil, "format" => "bar"
130
130
  fails "/:name.:format", "/.bar"
131
131
  fails "/:name.?:format?", "/.bar"
132
-
132
+
133
133
  converts "/:user@?:host?", %r{\A/((?:[^@/?#%]|(?:%[^4].|%[4][^0]))+)(?:@|%40)?((?:[^@/?#%]|(?:%[^4].|%[4][^0]))+)?\z}
134
134
  parses "/:user@?:host?", "/foo@bar", "user" => "foo", "host" => "bar"
135
135
  parses "/:user@?:host?", "/foo.foo@bar", "user" => "foo.foo", "host" => "bar"
136
136
  parses "/:user@?:host?", "/foo@bar.bar", "user" => "foo", "host" => "bar.bar"
137
-
137
+
138
138
  # From https://gist.github.com/2154980#gistcomment-169469.
139
139
  #
140
140
  # converts "/:name(.:format)?", %r{\A/([^\.%2E/?#]+)(?:\(|%28)(?:\.|%2E)([^\.%2E/?#]+)(?:\)|%29)?\z}
141
141
  # parses "/:name(.:format)?", "/foo", "name" => "foo", "format" => nil
142
142
  # parses "/:name(.:format)?", "/foo.bar", "name" => "foo", "format" => "bar"
143
143
  fails "/:name(.:format)?", "/foo."
144
-
144
+
145
145
  parses "/:id/test.bar", "/3/test.bar", {"id" => "3"}
146
146
  parses "/:id/test.bar", "/2/test.bar", {"id" => "2"}
147
147
  parses "/:id/test.bar", "/2E/test.bar", {"id" => "2E"}
148
148
  parses "/:id/test.bar", "/2e/test.bar", {"id" => "2e"}
149
149
  parses "/:id/test.bar", "/%2E/test.bar", {"id" => "%2E"}
150
-
150
+
151
151
  parses '/10/:id', '/10/test', "id" => "test"
152
152
  parses '/10/:id', '/10/te.st', "id" => "te.st"
153
-
153
+
154
154
  parses '/10.1/:id', '/10.1/test', "id" => "test"
155
155
  parses '/10.1/:id', '/10.1/te.st', "id" => "te.st"
156
156
  parses '/:foo/:id', '/10.1/te.st', "foo" => "10.1", "id" => "te.st"
157
157
  parses '/:foo/:id', '/10.1.2/te.st', "foo" => "10.1.2", "id" => "te.st"
158
158
  parses '/:foo.:bar/:id', '/10.1/te.st', "foo" => "10", "bar" => "1", "id" => "te.st"
159
159
  fails '/:foo.:bar/:id', '/10.1.2/te.st' # We don't do crazy.
160
-
160
+
161
161
  parses '/:a/:b.?:c?', '/a/b', "a" => "a", "b" => "b", "c" => nil
162
162
  parses '/:a/:b.?:c?', '/a/b.c', "a" => "a", "b" => "b", "c" => "c"
163
163
  parses '/:a/:b.?:c?', '/a.b/c', "a" => "a.b", "b" => "c", "c" => nil
164
164
  parses '/:a/:b.?:c?', '/a.b/c.d', "a" => "a.b", "b" => "c", "c" => "d"
165
165
  fails '/:a/:b.?:c?', '/a.b/c.d/e'
166
-
166
+
167
167
  parses "/:file.:ext", "/pony%2ejpg", "file" => "pony", "ext" => "jpg"
168
168
  parses "/:file.:ext", "/pony%E6%AD%A3%2Ejpg", "file" => "pony%E6%AD%A3", "ext" => "jpg"
169
169
  parses "/:file.:ext", "/pony%e6%ad%a3%2ejpg", "file" => "pony%e6%ad%a3", "ext" => "jpg"
@@ -171,12 +171,12 @@ class CompileTest < Test::Unit::TestCase
171
171
  parses "/:file.:ext", "/pony正%2ejpg", "file" => "pony正", "ext" => "jpg"
172
172
  parses "/:file.:ext", "/pony正..jpg", "file" => "pony正", "ext" => ".jpg"
173
173
  fails "/:file.:ext", "/pony正.%2ejpg"
174
-
174
+
175
175
  converts "/:name.:format", %r{\A/((?:[^\./?#%]|(?:%[^2].|%[2][^Ee]))+)(?:\.|%2[Ee])((?:[^/?#%]|(?:%[^2].|%[2][^Ee]))+)\z}
176
176
  parses "/:name.:format", "/file.tar.gz", "name" => "file", "format" => "tar.gz"
177
177
  parses "/:name.:format1.:format2", "/file.tar.gz", "name" => "file", "format1" => "tar", "format2" => "gz"
178
178
  parses "/:name.:format1.:format2", "/file.temp.tar.gz", "name" => "file", "format1" => "temp", "format2" => "tar.gz"
179
-
179
+
180
180
  # From issue #688.
181
181
  #
182
182
  parses "/articles/10.1103/:doi", "/articles/10.1103/PhysRevLett.110.026401", "doi" => "PhysRevLett.110.026401"
@@ -445,7 +445,7 @@ class AfterFilterTest < Test::Unit::TestCase
445
445
  assert ran
446
446
  end
447
447
 
448
- it 'only triggeres provides condition if conforms with current Content-Type' do
448
+ it 'only triggers provides condition if conforms with current Content-Type' do
449
449
  mock_app do
450
450
  before(:provides => :txt) { @type = 'txt' }
451
451
  before(:provides => :html) { @type = 'html' }
@@ -905,6 +905,17 @@ class HelpersTest < Test::Unit::TestCase
905
905
  get '/'
906
906
  assert_equal 'image/gif', response['Content-Type']
907
907
  end
908
+
909
+ it 'can have :status option as a string' do
910
+ path = @file
911
+ mock_app do
912
+ post '/' do
913
+ send_file path, :status => '422'
914
+ end
915
+ end
916
+ post '/'
917
+ assert_equal response.status, 422
918
+ end
908
919
  end
909
920
 
910
921
  describe 'cache_control' do
@@ -44,6 +44,23 @@ get '/send' do
44
44
  "ok"
45
45
  end
46
46
 
47
+ get '/send_file' do
48
+ file = File.expand_path '../../views/a/in_a.str', __FILE__
49
+ send_file file
50
+ end
51
+
52
+ get '/streaming' do
53
+ headers['Content-Length'] = '46'
54
+ stream do |out|
55
+ out << "It's gonna be legen -\n"
56
+ sleep 0.5
57
+ out << " (wait for it) \n"
58
+ puts headers
59
+ sleep 1
60
+ out << "- dary!\n"
61
+ end
62
+ end
63
+
47
64
  class Subclass < Sinatra::Base
48
65
  set :out, nil
49
66
  get '/subclass/async' do
@@ -73,6 +73,15 @@ module IntegrationHelper
73
73
  end
74
74
  end
75
75
 
76
+ def get_response(url)
77
+ Net::HTTP.start '127.0.0.1', port do |http|
78
+ request = Net::HTTP::Get.new url
79
+ http.request request do |response|
80
+ response
81
+ end
82
+ end
83
+ end
84
+
76
85
  def get(url)
77
86
  Timeout.timeout(1) { open("http://127.0.0.1:#{port}#{url}").read }
78
87
  end
@@ -221,7 +230,7 @@ module IntegrationHelper
221
230
 
222
231
  base_port = 5000 + Process.pid % 100
223
232
  Sinatra::Base.server.each_with_index do |server, index|
224
- Server.run(server, 5000+index)
233
+ Server.run(server, base_port+index)
225
234
  end
226
235
  end
227
236
  end
@@ -91,4 +91,14 @@ class IntegrationTest < Test::Unit::TestCase
91
91
  server.get '/app_file'
92
92
  assert_equal [], server.warnings
93
93
  end
94
- end
94
+
95
+ it 'sets the Content-Length response header when sending files' do
96
+ response = server.get_response '/send_file'
97
+ assert response['Content-Length']
98
+ end
99
+
100
+ it "doesn't ignore Content-Length header when streaming" do
101
+ response = server.get_response '/streaming'
102
+ assert_equal '46', response['Content-Length']
103
+ end
104
+ end
@@ -16,13 +16,13 @@ class RdocTest < Test::Unit::TestCase
16
16
  it 'renders inline rdoc strings' do
17
17
  rdoc_app { rdoc '= Hiya' }
18
18
  assert ok?
19
- assert_body /<h1[^>]*>Hiya(<span><a href=\"#label-Hiya\">&para;<\/a> <a href=\"#documentation\">&uarr;<\/a><\/span>)?<\/h1>/
19
+ assert_body(/<h1[^>]*>Hiya(<span><a href=\"#label-Hiya\">&para;<\/a> <a href=\"#documentation\">&uarr;<\/a><\/span>)?<\/h1>/)
20
20
  end
21
21
 
22
22
  it 'renders .rdoc files in views path' do
23
23
  rdoc_app { rdoc :hello }
24
24
  assert ok?
25
- assert_body /<h1[^>]*>Hello From RDoc(<span><a href=\"#label-Hello\+From\+RDoc\">&para;<\/a> <a href=\"#documentation\">&uarr;<\/a><\/span>)?<\/h1>/
25
+ assert_body(/<h1[^>]*>Hello From RDoc(<span><a href=\"#label-Hello\+From\+RDoc\">&para;<\/a> <a href=\"#documentation\">&uarr;<\/a><\/span>)?<\/h1>/)
26
26
  end
27
27
 
28
28
  it "raises error if template not found" do
@@ -63,6 +63,11 @@ class RequestTest < Test::Unit::TestCase
63
63
  end
64
64
  end
65
65
 
66
+ it "accepts types when wildcards are requested" do
67
+ request = Sinatra::Request.new('HTTP_ACCEPT' => 'image/*')
68
+ assert request.accept?('image/jpeg')
69
+ end
70
+
66
71
  it "properly decodes MIME type parameters" do
67
72
  request = Sinatra::Request.new(
68
73
  'HTTP_ACCEPT' => 'image/jpeg;unquoted=0.25;quoted="0.25";chartest="\";,\x"'
@@ -70,4 +75,18 @@ class RequestTest < Test::Unit::TestCase
70
75
  expected = { 'unquoted' => '0.25', 'quoted' => '0.25', 'chartest' => '";,x' }
71
76
  assert_equal(expected, request.preferred_type.params)
72
77
  end
78
+
79
+ it 'accepts */* when HTTP_ACCEPT is not present in the request' do
80
+ request = Sinatra::Request.new Hash.new
81
+ assert_equal 1, request.accept.size
82
+ assert request.accept?('text/html')
83
+ assert_equal '*/*', request.preferred_type.to_s
84
+ end
85
+
86
+ it 'accepts */* when HTTP_ACCEPT is blank in the request' do
87
+ request = Sinatra::Request.new 'HTTP_ACCEPT' => ''
88
+ assert_equal 1, request.accept.size
89
+ assert request.accept?('text/html')
90
+ assert_equal '*/*', request.preferred_type.to_s
91
+ end
73
92
  end
@@ -37,7 +37,7 @@ class ResponseTest < Test::Unit::TestCase
37
37
 
38
38
  it 'Calculates the Content-Length using the bytesize of the body' do
39
39
  @response.body = ['Hello', 'World!', '✈']
40
- status, headers, body = @response.finish
40
+ _, headers, body = @response.finish
41
41
  assert_equal '14', headers['Content-Length']
42
42
  assert_same_body @response.body, body
43
43
  end
@@ -669,6 +669,24 @@ class RoutingTest < Test::Unit::TestCase
669
669
  assert "this", body
670
670
  end
671
671
 
672
+ it "uses optional block passed to pass as route block if no other route is found and superclass has non-matching routes" do
673
+ base = Class.new(Sinatra::Base)
674
+ base.get('/foo') { 'foo in baseclass' }
675
+
676
+ mock_app(base) {
677
+ get "/" do
678
+ pass do
679
+ "this"
680
+ end
681
+ "not this"
682
+ end
683
+ }
684
+
685
+ get "/"
686
+ assert_equal 200, status
687
+ assert "this", body
688
+ end
689
+
672
690
  it "passes when matching condition returns false" do
673
691
  mock_app {
674
692
  condition { params[:foo] == 'bar' }
@@ -48,7 +48,7 @@ class SlimTest < Test::Unit::TestCase
48
48
  HTML4_DOCTYPE = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
49
49
 
50
50
  it "passes slim options to the slim engine" do
51
- mock_app { get('/') { slim("x foo='bar'", :attr_wrapper => "'") }}
51
+ mock_app { get('/') { slim("x foo='bar'", :attr_quote => "'") }}
52
52
  get '/'
53
53
  assert ok?
54
54
  assert_body "<x foo='bar'></x>"
@@ -56,7 +56,7 @@ class SlimTest < Test::Unit::TestCase
56
56
 
57
57
  it "passes default slim options to the slim engine" do
58
58
  mock_app do
59
- set :slim, :attr_wrapper => "'"
59
+ set :slim, :attr_quote => "'"
60
60
  get('/') { slim("x foo='bar'") }
61
61
  end
62
62
  get '/'
@@ -66,9 +66,9 @@ class SlimTest < Test::Unit::TestCase
66
66
 
67
67
  it "merges the default slim options with the overrides and passes them to the slim engine" do
68
68
  mock_app do
69
- set :slim, :attr_wrapper => "'"
69
+ set :slim, :attr_quote => "'"
70
70
  get('/') { slim("x foo='bar'") }
71
- get('/other') { slim("x foo='bar'", :attr_wrapper => '"') }
71
+ get('/other') { slim("x foo='bar'", :attr_quote => '"') }
72
72
  end
73
73
  get '/'
74
74
  assert ok?
@@ -79,6 +79,21 @@ class TemplatesTest < Test::Unit::TestCase
79
79
  assert_equal "Hello World!", body
80
80
  end
81
81
 
82
+ it 'allows overriding false default layout with explicit true' do
83
+ mock_app do
84
+ template(:layout) { 'Layout!!! <%= yield %>' }
85
+ set :erb, :layout => false
86
+
87
+ get('/') do
88
+ erb('Hello World!', { :layout => true })
89
+ end
90
+ end
91
+
92
+ get '/'
93
+ assert ok?
94
+ assert_equal "Layout!!! Hello World!", body
95
+ end
96
+
82
97
  it 'renders String templates directly' do
83
98
  render_app { render(:test, 'Hello World') }
84
99
  assert ok?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-06-07 00:00:00.000000000 Z
14
+ date: 2013-10-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rack
@@ -105,7 +105,7 @@ files:
105
105
  - lib/sinatra/images/404.png
106
106
  - lib/sinatra/images/500.png
107
107
  - lib/sinatra/main.rb
108
- - lib/sinatra/showexceptions.rb
108
+ - lib/sinatra/show_exceptions.rb
109
109
  - lib/sinatra/version.rb
110
110
  - sinatra.gemspec
111
111
  - test/base_test.rb
@@ -228,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
228
  version: '0'
229
229
  requirements: []
230
230
  rubyforge_project:
231
- rubygems_version: 2.0.2
231
+ rubygems_version: 2.0.7
232
232
  signing_key:
233
233
  specification_version: 4
234
234
  summary: Classy web-development dressed in a DSL