merb-core 0.9.5 → 0.9.6

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.
Files changed (78) hide show
  1. data/CHANGELOG +925 -0
  2. data/CONTRIBUTORS +93 -0
  3. data/PUBLIC_CHANGELOG +85 -0
  4. data/Rakefile +18 -28
  5. data/bin/merb +34 -5
  6. data/lib/merb-core/autoload.rb +2 -3
  7. data/lib/merb-core/bootloader.rb +60 -66
  8. data/lib/merb-core/config.rb +7 -1
  9. data/lib/merb-core/controller/abstract_controller.rb +35 -21
  10. data/lib/merb-core/controller/merb_controller.rb +15 -42
  11. data/lib/merb-core/controller/mixins/authentication.rb +42 -6
  12. data/lib/merb-core/controller/mixins/conditional_get.rb +83 -0
  13. data/lib/merb-core/controller/mixins/render.rb +3 -3
  14. data/lib/merb-core/core_ext/kernel.rb +6 -19
  15. data/lib/merb-core/dispatch/cookies.rb +96 -80
  16. data/lib/merb-core/dispatch/default_exception/views/index.html.erb +2 -0
  17. data/lib/merb-core/dispatch/request.rb +18 -16
  18. data/lib/merb-core/dispatch/router/route.rb +6 -0
  19. data/lib/merb-core/dispatch/router.rb +4 -1
  20. data/lib/merb-core/dispatch/session/container.rb +64 -0
  21. data/lib/merb-core/dispatch/session/cookie.rb +91 -101
  22. data/lib/merb-core/dispatch/session/memcached.rb +38 -174
  23. data/lib/merb-core/dispatch/session/memory.rb +62 -208
  24. data/lib/merb-core/dispatch/session/store_container.rb +145 -0
  25. data/lib/merb-core/dispatch/session.rb +174 -48
  26. data/lib/merb-core/rack/middleware/conditional_get.rb +14 -8
  27. data/lib/merb-core/rack/middleware/csrf.rb +73 -0
  28. data/lib/merb-core/rack.rb +1 -0
  29. data/lib/merb-core/script.rb +112 -0
  30. data/lib/merb-core/server.rb +2 -0
  31. data/lib/merb-core/tasks/merb_rake_helper.rb +25 -0
  32. data/lib/merb-core/test/helpers/request_helper.rb +40 -3
  33. data/lib/merb-core/test/run_specs.rb +4 -3
  34. data/lib/merb-core/vendor/facets/inflect.rb +7 -10
  35. data/lib/merb-core/version.rb +1 -1
  36. data/lib/merb-core.rb +11 -40
  37. data/spec/private/core_ext/kernel_spec.rb +0 -11
  38. data/spec/private/dispatch/fixture/log/merb_test.log +893 -0
  39. data/spec/private/router/fixture/log/merb_test.log +12 -1728
  40. data/spec/private/router/route_spec.rb +4 -0
  41. data/spec/private/router/router_spec.rb +8 -0
  42. data/spec/private/vendor/facets/plural_spec.rb +1 -1
  43. data/spec/private/vendor/facets/singular_spec.rb +1 -1
  44. data/spec/public/abstract_controller/controllers/display.rb +8 -2
  45. data/spec/public/abstract_controller/controllers/filters.rb +18 -0
  46. data/spec/public/abstract_controller/display_spec.rb +6 -2
  47. data/spec/public/abstract_controller/filter_spec.rb +4 -0
  48. data/spec/public/controller/authentication_spec.rb +114 -43
  49. data/spec/public/controller/base_spec.rb +8 -0
  50. data/spec/public/controller/conditional_get_spec.rb +100 -0
  51. data/spec/public/controller/config/init.rb +1 -1
  52. data/spec/public/controller/controllers/authentication.rb +29 -0
  53. data/spec/public/controller/controllers/base.rb +13 -0
  54. data/spec/public/controller/controllers/conditional_get.rb +35 -0
  55. data/spec/public/controller/controllers/cookies.rb +10 -1
  56. data/spec/public/controller/cookies_spec.rb +38 -9
  57. data/spec/public/controller/spec_helper.rb +1 -0
  58. data/spec/public/controller/url_spec.rb +70 -1
  59. data/spec/public/directory_structure/directory/log/merb_test.log +461 -0
  60. data/spec/public/rack/conditinal_get_middleware_spec.rb +77 -89
  61. data/spec/public/rack/csrf_middleware_spec.rb +70 -0
  62. data/spec/public/reloading/directory/log/merb_test.log +52 -0
  63. data/spec/public/request/request_spec.rb +19 -1
  64. data/spec/public/router/fixation_spec.rb +26 -4
  65. data/spec/public/router/fixture/log/merb_test.log +234 -30332
  66. data/spec/public/session/controllers/sessions.rb +52 -0
  67. data/spec/public/session/cookie_session_spec.rb +73 -0
  68. data/spec/public/session/memcached_session_spec.rb +31 -0
  69. data/spec/public/session/memory_session_spec.rb +28 -0
  70. data/spec/public/session/multiple_sessions_spec.rb +74 -0
  71. data/spec/public/session/no_session_spec.rb +12 -0
  72. data/spec/public/session/session_spec.rb +91 -0
  73. data/spec/public/test/controllers/spec_helper_controller.rb +2 -1
  74. data/spec/public/test/request_helper_spec.rb +15 -0
  75. data/spec/spec_helper.rb +2 -2
  76. metadata +23 -5
  77. data/spec/private/dispatch/cookies_spec.rb +0 -219
  78. data/spec/private/dispatch/session_mixin_spec.rb +0 -47
@@ -1,139 +1,127 @@
1
1
  require File.join(File.dirname(__FILE__), "..", "..", "spec_helper")
2
- require File.join(File.dirname(__FILE__), "shared_example_groups")
3
2
 
4
3
  require "sha1"
5
4
 
6
- NOW = Time.now
7
-
8
- class EtagController < Merb::Controller
9
- def non_matching_etag
10
- response = "Ruby world needs a Paste port. Or... CherryPy?"
5
+ class ConditionalGetTestController < Merb::Controller
6
+ def with_etag
7
+ response = "original message-body"
11
8
  headers['ETag'] = Digest::SHA1.hexdigest(response)
12
9
 
13
10
  response
14
11
  end
15
12
 
16
- def matching_etag
17
- response = "Everybody loves Rack"
18
- headers['ETag'] = Digest::SHA1.hexdigest(response)
19
-
20
- response
21
- end
22
-
23
- def no_etag
24
- # sanity check
25
- headers.delete('ETag')
26
-
27
- "Everyone loves Rack"
13
+ def with_last_modified
14
+ headers[Merb::Const::LAST_MODIFIED] = :documents_last_modified_time
15
+ "original message-body"
28
16
  end
29
- end
30
17
 
31
- class LastModifiedController < Merb::Controller
32
- def non_matching_last_modified
33
- response = "Who cares about efficiency? Just throw more hardware at the problem."
34
- headers[Merb::Const::LAST_MODIFIED] = :non_matching
35
-
36
- response
37
- end
38
-
39
- def matching_last_modified
40
- response = "Who cares about efficiency? Just throw more hardware at the problem."
41
- headers[Merb::Const::LAST_MODIFIED] = :matching
42
-
43
- response
44
- end
45
-
46
- def no_last_modified
18
+ def without
47
19
  # sanity check
48
- headers.delete('Last-Modified')
20
+ headers.delete('ETag')
21
+ headers.delete(Merb::Const::LAST_MODIFIED)
49
22
 
50
- "Everyone loves Rack"
23
+ "original message-body"
51
24
  end
52
25
  end
53
26
 
54
27
 
55
28
  Merb::Router.prepare do |r|
56
- r.match("/etag/match").to(:controller => "etag_controller", :action => "matching_etag")
57
- r.match("/etag/nomatch").to(:controller => "etag_controller", :action => "non_matching_etag")
58
- r.match("/etag/stomach").to(:controller => "etag_controller", :action => "no_etag")
59
-
60
- r.match("/last_modified/match").to(:controller => "last_modified_controller", :action => "matching_last_modified")
61
- r.match("/last_modified/nomatch").to(:controller => "last_modified_controller", :action => "non_matching_last_modified")
62
- r.match("/last_modified/stomach").to(:controller => "last_modified_controller", :action => "no_last_modified")
29
+ r.match("/with_etag").to(
30
+ :controller => "conditional_get_test_controller", :action => "with_etag"
31
+ )
32
+ r.match("/with_last_modified").to(
33
+ :controller => "conditional_get_test_controller", :action => "with_last_modified"
34
+ )
35
+ r.match("/without").to(
36
+ :controller => "conditional_get_test_controller", :action => "without"
37
+ )
63
38
  end
64
39
 
40
+ describe Merb::Rack::ConditionalGet do
65
41
 
42
+ describe(
43
+ "when the client already has an up-to-date document",
44
+ :shared => true
45
+ ) do
46
+ it 'sets status to "304"' do
47
+ @status.should == 304
48
+ end
66
49
 
67
- describe Merb::Rack::ConditionalGet do
50
+ it 'returns no message-body' do
51
+ @body.should == ""
52
+ end
53
+ end
54
+
55
+ describe(
56
+ "when the client does NOT have an up-to-date document",
57
+ :shared => true
58
+ ) do
59
+ it 'does not modify status' do
60
+ @status.should == 200
61
+ end
68
62
 
63
+ it 'does not modify message-body' do
64
+ @body.should == "original message-body"
65
+ end
66
+ end
67
+
69
68
  before(:each) do
70
69
  @app = Merb::Rack::Application.new
71
70
  @middleware = Merb::Rack::ConditionalGet.new(@app)
72
71
  end
73
72
 
74
- describe "when response has no ETag header" do
75
- it 'does not modify status' do
76
- env = Rack::MockRequest.env_for('/etag/stomach')
77
- status, headers, body = @middleware.call(env)
78
-
79
- status.should == 200
73
+ describe "when response has no ETag header and no Last-Modified header" do
74
+ before(:each) do
75
+ env = Rack::MockRequest.env_for('/without')
76
+ @status, @headers, @body = @middleware.call(env)
80
77
  end
78
+
79
+ it_should_behave_like "when the client does NOT have an up-to-date document"
81
80
  end
82
81
 
83
82
  describe "when response has ETag header" do
84
83
  describe "and it == to HTTP_IF_NONE_MATCH of the request" do
85
- it 'sets status to "304"' do
86
- env = Rack::MockRequest.env_for('/etag/match')
84
+ before(:each) do
85
+ env = Rack::MockRequest.env_for('/with_etag')
87
86
  env['HTTP_IF_NONE_MATCH'] =
88
- Digest::SHA1.hexdigest("Everybody loves Rack")
89
-
90
- status, headers, body = @middleware.call(env)
91
- status.should == 304
87
+ Digest::SHA1.hexdigest("original message-body")
88
+ @status, @headers, @body = @middleware.call(env)
92
89
  end
90
+
91
+ it_should_behave_like "when the client already has an up-to-date document"
93
92
  end
94
93
 
95
94
  describe "and it IS NOT == to HTTP_IF_NONE_MATCH of the request" do
96
- it 'does not modify status' do
97
- env = Rack::MockRequest.env_for('/etag/nomatch')
95
+ before(:each) do
96
+ env = Rack::MockRequest.env_for('/with_etag')
98
97
  env['HTTP_IF_NONE_MATCH'] =
99
- Digest::SHA1.hexdigest("Everybody loves Rack")
100
-
101
- status, headers, body = @middleware.call(env)
102
- status.should == 200
98
+ Digest::SHA1.hexdigest("a different message-body")
99
+ @status, @headers, @body = @middleware.call(env)
103
100
  end
104
- end
105
- end
106
-
107
- describe "when response has no Last-Modified header" do
108
- it 'does not modify status' do
109
- env = Rack::MockRequest.env_for('/last_modified/stomach')
110
- status, headers, body = @middleware.call(env)
111
-
112
- status.should == 200
101
+
102
+ it_should_behave_like "when the client does NOT have an up-to-date document"
113
103
  end
114
104
  end
115
105
 
116
106
  describe "when response has Last-Modified header" do
117
- describe "when response has Last-Modified header" do
118
- describe "and it == to HTTP_IF_NOT_MODIFIED_SINCE of the request" do
119
- it 'sets status to "304"' do
120
- env = Rack::MockRequest.env_for('/last_modified/match')
121
- env[Merb::Const::HTTP_IF_MODIFIED_SINCE] = :matching
122
-
123
- status, headers, body = @middleware.call(env)
124
- status.should == 304
125
- end
107
+ describe "and it == to HTTP_IF_NOT_MODIFIED_SINCE of the request" do
108
+ before(:each) do
109
+ env = Rack::MockRequest.env_for('/with_last_modified')
110
+ env[Merb::Const::HTTP_IF_MODIFIED_SINCE] = :documents_last_modified_time
111
+ @status, @headers, @body = @middleware.call(env)
126
112
  end
113
+
114
+ it_should_behave_like "when the client already has an up-to-date document"
115
+ end
127
116
 
128
- describe "and it IS NOT == to HTTP_IF_NOT_MODIFIED_SINCE of the request" do
129
- it 'does not modify status' do
130
- env = Rack::MockRequest.env_for('/last_modified/nomatch')
131
- env[Merb::Const::HTTP_IF_MODIFIED_SINCE] = :matching
132
-
133
- status, headers, body = @middleware.call(env)
134
- status.should == 200
135
- end
117
+ describe "and it IS NOT == to HTTP_IF_NOT_MODIFIED_SINCE of the request" do
118
+ before(:each) do
119
+ env = Rack::MockRequest.env_for('/with_last_modified')
120
+ env[Merb::Const::HTTP_IF_MODIFIED_SINCE] = :some_other_time
121
+ @status, @headers, @body = @middleware.call(env)
136
122
  end
123
+
124
+ it_should_behave_like "when the client does NOT have an up-to-date document"
137
125
  end
138
126
  end
139
127
  end
@@ -0,0 +1,70 @@
1
+ require File.join(File.dirname(__FILE__), "..", "..", "spec_helper")
2
+ require File.join(File.dirname(__FILE__), "shared_example_groups")
3
+
4
+
5
+ Merb::Router.prepare do |r|
6
+ r.resources :users
7
+ end
8
+
9
+ class Users < Merb::Controller
10
+ def new
11
+ body = "<div><form action='/users' method='POST'></form></div>"
12
+ body
13
+ end
14
+
15
+ def index
16
+ body = "<div>This is my index action</div>"
17
+ body
18
+ end
19
+
20
+ def edit
21
+ body = "<div><form action='/users' method='POST'></form><form action='/sessions' method='POST'></form></div>"
22
+ end
23
+
24
+ def create
25
+
26
+ end
27
+ end
28
+
29
+
30
+ describe Merb::Rack::Csrf do
31
+ before(:each) do
32
+ @app = Merb::Rack::Application.new
33
+ @middleware = Merb::Rack::Csrf.new(@app)
34
+ @env = Rack::MockRequest.env_for('/users/new')
35
+
36
+ Merb::Config[:session_secret_key] = "ABC"
37
+ end
38
+
39
+ it "should be successful" do
40
+ env = Rack::MockRequest.env_for('/users', :method => 'POST', 'csrf_authentication_token' => "b072aa15485e028dc8973d48089efe0e")
41
+ status, header, body = @middleware.call(env)
42
+ status.should == 200
43
+ end
44
+
45
+ it "should return a Merb::ExceptionsController::Forbidden (403)" do
46
+ env = Rack::MockRequest.env_for('/users', :method => 'POST', 'csrf_authentication_token' => "INCORRECT_AUTH_TOKEN")
47
+ status, header, body = @middleware.call(env)
48
+ status.should == 403
49
+ end
50
+
51
+ it "should insert a hidden field in to any form with a POST method" do
52
+ env = Rack::MockRequest.env_for('/users/new')
53
+ status, header, body = @middleware.call(env)
54
+ body.should have_tag(:form, :action => '/users')
55
+ body.should have_tag(:input, :type => 'hidden', :id => 'csrf_authentication_token')
56
+ end
57
+
58
+ it "should not do anything if there is no form found in the response" do
59
+ env = Rack::MockRequest.env_for('/users')
60
+ status, header, body = @middleware.call(env)
61
+ body.should not_match_tag('form')
62
+ end
63
+
64
+ it "should insert hidden fields in to both forms" do
65
+ env = Rack::MockRequest.env_for('/users/1/edit')
66
+ status, header, body = @middleware.call(env)
67
+ body.should have_tag(:form, :action => '/users')
68
+ body.should have_tag(:form, :action => '/sessions')
69
+ end
70
+ end
@@ -288161,3 +288161,55 @@ Restarting Worker Thread
288161
288161
  ~ Not Using Sessions
288162
288162
  ~ Not Using Sessions
288163
288163
  ~ Not Using Sessions
288164
+ ~ Not Using Sessions
288165
+ ~ Not Using Sessions
288166
+ ~ Not Using Sessions
288167
+ ~ Not Using Sessions
288168
+ ~ Not Using Sessions
288169
+ ~ Not Using Sessions
288170
+ ~ Not Using Sessions
288171
+ ~ Not Using Sessions
288172
+ ~ Not Using Sessions
288173
+ ~ Not Using Sessions
288174
+ ~ Not Using Sessions
288175
+ ~ Not Using Sessions
288176
+ ~ Not Using Sessions
288177
+ ~ Not Using Sessions
288178
+ ~ Not Using Sessions
288179
+ ~ Not Using Sessions
288180
+ ~ Not Using Sessions
288181
+ ~ Not Using Sessions
288182
+ ~ Not Using Sessions
288183
+ ~ Not Using Sessions
288184
+ ~ Not Using Sessions
288185
+ ~ Not Using Sessions
288186
+ ~ Not Using Sessions
288187
+ ~ Not Using Sessions
288188
+ ~ Not Using Sessions
288189
+ ~ Not Using Sessions
288190
+ ~ Not Using Sessions
288191
+ ~ Not Using Sessions
288192
+ ~ Not Using Sessions
288193
+ ~ Starting Merb server listening at 0.0.0.0:4000
288194
+ ~ Not Using Sessions
288195
+ ~ Starting Merb server listening at 0.0.0.0:4000
288196
+ ~ Not Using Sessions
288197
+ ~ Starting Merb server listening at 0.0.0.0:4000
288198
+ ~ Not Using Sessions
288199
+ ~ Starting Merb server listening at 0.0.0.0:4000
288200
+ ~ Not Using Sessions
288201
+ ~ Starting Merb server listening at 0.0.0.0:4000
288202
+ ~ Not Using Sessions
288203
+ ~ Starting Merb server listening at 0.0.0.0:4000
288204
+ ~ Not Using Sessions
288205
+ ~ Starting Merb server listening at 0.0.0.0:4000
288206
+ ~ Not Using Sessions
288207
+ ~ Starting Merb server listening at 0.0.0.0:4000
288208
+ ~ Not Using Sessions
288209
+ ~ Starting Merb server listening at 0.0.0.0:4000
288210
+ ~ Starting Merb server listening at 0.0.0.0:4000
288211
+ ~ Starting Merb server listening at 0.0.0.0:4000
288212
+ ~ Starting Merb server listening at 0.0.0.0:4000
288213
+ ~ Starting Merb server listening at 0.0.0.0:4000
288214
+ ~ Starting Merb server listening at 0.0.0.0:4000
288215
+ ~ Starting Merb server listening at 0.0.0.0:4000
@@ -56,6 +56,7 @@ describe Merb::Request, " query and body params" do
56
56
  before(:all) { Merb::BootLoader::Dependencies.enable_json_gem }
57
57
 
58
58
  {"foo=bar&baz=bat" => {"foo" => "bar", "baz" => "bat"},
59
+ "foo=bar&foo=baz" => {"foo" => "baz"},
59
60
  "foo[]=bar&foo[]=baz" => {"foo" => ["bar", "baz"]},
60
61
  "foo[][bar]=1&foo[][bar]=2" => {"foo" => [{"bar" => "1"},{"bar" => "2"}]},
61
62
  "foo[bar][][baz]=1&foo[bar][][baz]=2" => {"foo" => {"bar" => [{"baz" => "1"},{"baz" => "2"}]}},
@@ -220,4 +221,21 @@ describe Merb::Request, " misc" do
220
221
 
221
222
  end
222
223
 
223
- end
224
+ end
225
+
226
+
227
+
228
+ describe Merb::Request, "#if_none_match" do
229
+ it 'returns value of If-None-Match request header' do
230
+ fake_request(Merb::Const::HTTP_IF_NONE_MATCH => "dc1562a133").if_none_match.should == "dc1562a133"
231
+ end
232
+ end
233
+
234
+
235
+
236
+ describe Merb::Request, "#if_modified_since" do
237
+ it 'returns value of If-Modified-Since request header' do
238
+ t = '05 Sep 2008 22:00:27 GMT'
239
+ fake_request(Merb::Const::HTTP_IF_MODIFIED_SINCE => t).if_modified_since.should == Time.rfc2822(t)
240
+ end
241
+ end
@@ -1,19 +1,41 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper")
2
2
 
3
+ module Merb::Test::Fixtures
4
+ module Controllers
5
+ class FixatableRoutes < Merb::Controller
6
+
7
+ def fixoid
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+
3
14
  describe "A route marked as fixatable" do
4
15
  predicate_matchers[:allow_fixation] = :allow_fixation?
5
16
 
6
- it "allows fixation" do
17
+ before do
7
18
  Merb::Router.prepare do |r|
8
- r.match("/hello/:action/:id").to(:controller => "foo", :action => "fixoid").fixatable
19
+ r.match("/hello/:action/:id").to(
20
+ :controller => "merb/test/fixtures/controllers/fixatable_routes",
21
+ :action => "fixoid").fixatable
9
22
  end
23
+ end
10
24
 
25
+ it "allows fixation" do
11
26
  matched_route_for("/hello/goodbye/tagging").should allow_fixation
12
27
  end
28
+
29
+ it "should store a cookie with the session_id" do
30
+ session_id = Merb::SessionMixin.rand_uuid
31
+ request = fake_request(:request_uri => "/hello/goodbye/tagging",
32
+ :query_string => "_session_id=#{session_id}")
33
+ controller = ::Merb::Dispatcher.handle(request)
34
+ controller.params["_session_id"].should == session_id
35
+ controller.request.session_cookie_value.should == session_id
36
+ end
13
37
  end
14
38
 
15
-
16
-
17
39
  describe "A route NOT marked as fixatable" do
18
40
  predicate_matchers[:allow_fixation] = :allow_fixation?
19
41