merb-core 1.1.0 → 1.1.1
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.
- data/CHANGELOG +38 -8
- data/Rakefile +1 -59
- data/lib/merb-core.rb +3 -2
- data/lib/merb-core/bootloader.rb +17 -1
- data/lib/merb-core/config.rb +1 -1
- data/lib/merb-core/dispatch/dispatcher.rb +53 -64
- data/lib/merb-core/dispatch/request.rb +1 -1
- data/lib/merb-core/dispatch/session.rb +20 -10
- data/lib/merb-core/gem_ext/erubis.rb +1 -0
- data/lib/merb-core/rack.rb +1 -0
- data/lib/merb-core/rack/adapter/abstract.rb +12 -5
- data/lib/merb-core/rack/handler/mongrel.rb +2 -2
- data/lib/merb-core/rack/middleware.rb +43 -11
- data/lib/merb-core/rack/middleware/content_length.rb +8 -14
- data/lib/merb-core/rack/middleware/head.rb +14 -0
- data/lib/merb-core/test/helpers.rb +1 -0
- data/lib/merb-core/test/helpers/webrat_helper.rb +18 -0
- data/lib/merb-core/version.rb +1 -1
- data/spec/private/dispatch/bootloader_spec.rb +1 -0
- data/spec/public/controller/controllers/redirect.rb +1 -1
- data/spec/public/controller/redirect_spec.rb +6 -3
- data/spec/public/rack/rack_middleware_spec.rb +15 -0
- data/spec/public/rack/shared_example_groups.rb +3 -3
- data/spec/public/request/request_spec.rb +0 -2
- data/spec/public/webrat/test_app/config/init.rb +2 -1
- data/spec/public/webrat/test_app/config/rack.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +249 -239
data/CHANGELOG
CHANGED
@@ -1,4 +1,18 @@
|
|
1
|
-
== 1.1.0 ""
|
1
|
+
== 1.1.0 "Black Hole" 2010-03-22
|
2
|
+
|
3
|
+
* Ruby 1.9 support. The big one. Merb now runs on ruby 1.9.1. This mandated some
|
4
|
+
small changes to the internals as well as some changes to the specs. However,
|
5
|
+
it shouldn't require any changes in your app level code, or at least the merb
|
6
|
+
specific parts of your app level code.
|
7
|
+
|
8
|
+
* Unicorns! Merb is now better behaved as a rack app and works with a config.ru
|
9
|
+
file[2]. This change should make working with whatever is the latest and
|
10
|
+
greatest ruby webserver a lot easier.
|
11
|
+
|
12
|
+
* Bugfixes. So many bug fixes. As part of the release process we've done our
|
13
|
+
best to clear out many of the bugs which have been gathering dust over the
|
14
|
+
past year. Some do still remain, but those generally require a more complex
|
15
|
+
solution which needs some thought.
|
2
16
|
|
3
17
|
* !!!BC!!! Dependency handling using Bundler
|
4
18
|
In this version we dropped old way of loading dependencies using the Kernel
|
@@ -6,36 +20,52 @@
|
|
6
20
|
us to move the whole dependency handling and gem management outside the
|
7
21
|
Merb. Therefore we can simplify some internals and remove some of the Kernel
|
8
22
|
monkeypatching:
|
9
|
-
|
23
|
+
|
10
24
|
The old Kernel.dependency and Kernel.dependencies will only 'require
|
11
25
|
gem_name' or 'require require_as' when you call this methods. These methods
|
12
26
|
will also emit the DEPRECATED warnings when you will use them. If you see
|
13
27
|
the warning you should move your dependency to the Gemfile or Rakefile.
|
14
|
-
|
28
|
+
|
15
29
|
If you used dependencies to load exact version of the Gem and you have
|
16
30
|
installed multiple versions of the same gem you now get one more DEPRECATED
|
17
31
|
warning. This is because we don't use 'gem' command from RubyGems which was
|
18
32
|
used deep inside to load exact gem version. ALSO THE LATEST VERSION OF THE
|
19
33
|
GEM WILL BE LOADED BECAUSE WE DO SIMPLE 'require'.
|
20
|
-
|
34
|
+
|
21
35
|
Also methods: use_orm, use_test, use_testing_framework and use_template_engine
|
22
36
|
DON'T require any gems now, you must require it in Gemfile.
|
23
|
-
|
37
|
+
|
24
38
|
Merb generators was changed to generate you Gemfile for your application and
|
25
39
|
settings instead of the dependencies.rb.
|
26
|
-
|
40
|
+
|
27
41
|
So what still works? Almost everything except it doesn't defer to the Merb
|
28
42
|
start and doesn't load exact version of gem if more versions are installed:
|
29
|
-
|
43
|
+
|
30
44
|
dependency "json" => works
|
31
45
|
dependency "rspec", :require_as => 'spec' => works try to require 'spec'
|
32
46
|
dependency "json", '1.1.6' => works unless you have
|
33
47
|
>= 1.1.6 installed
|
34
48
|
dependency "json" { } => works but doesn't yield
|
35
|
-
|
49
|
+
|
36
50
|
For more information how to migrate to Bundler see:
|
37
51
|
http://wiki.github.com/merb/merb/howto-using-the-bundler
|
38
52
|
|
53
|
+
=== Bugs fixed
|
54
|
+
|
55
|
+
* [merb-core] #1040 Allow using <%== %> escaped version of <%= %>
|
56
|
+
* [merb-core] #1068 Correctly handle HEAD requests (This requires manual
|
57
|
+
alteration of rack.rb)
|
58
|
+
* [merb-core] #1174 Merb::Config[:use_mutex] issue
|
59
|
+
'sel' to string before comparing to string
|
60
|
+
* [merb-core] #1258 Sessions could be overwritten under certain (rare)
|
61
|
+
situations.
|
62
|
+
* [merb-core] #1288 Fix for run_later in clusters
|
63
|
+
* [merb-core] #1298 Fix potential timing attack on cookie sessions.
|
64
|
+
* [merb-core] #1304 Multipart input parsing produces wrong checkbox input
|
65
|
+
* [merb-core] #1310 Prevent mongrel bloat when streaming files
|
66
|
+
* [merb-core] #1317 Merb now returns correct cookie headers
|
67
|
+
* [merb-core] Improvements to handling of conditional validators
|
68
|
+
|
39
69
|
== 0.9.8 "Time Machine" 2008-06-10
|
40
70
|
|
41
71
|
* Pre-release contributors file update.
|
data/Rakefile
CHANGED
@@ -8,65 +8,8 @@ require "fileutils"
|
|
8
8
|
# Load code annotation support library
|
9
9
|
require File.expand_path("../tools/annotation_extract", __FILE__)
|
10
10
|
|
11
|
-
# Load this library's version information
|
12
|
-
require File.expand_path('../lib/merb-core/version', __FILE__)
|
13
|
-
|
14
11
|
include FileUtils
|
15
12
|
|
16
|
-
begin
|
17
|
-
|
18
|
-
gem 'jeweler', '~> 1.4'
|
19
|
-
require 'jeweler'
|
20
|
-
|
21
|
-
Jeweler::Tasks.new do |gemspec|
|
22
|
-
|
23
|
-
gemspec.version = Merb::VERSION.dup
|
24
|
-
|
25
|
-
gemspec.name = "merb-core"
|
26
|
-
gemspec.description = "Merb. Pocket rocket web framework."
|
27
|
-
gemspec.summary = "Merb plugin that provides caching (page, action, fragment, object)"
|
28
|
-
|
29
|
-
gemspec.authors = [ "Ezra Zygmuntowicz" ]
|
30
|
-
gemspec.email = "ez@engineyard.com"
|
31
|
-
gemspec.homepage = "http://merbivore.com/"
|
32
|
-
|
33
|
-
gemspec.extra_rdoc_files.include [ 'CHANGELOG' ]
|
34
|
-
|
35
|
-
gemspec.files = Dir["{bin,lib,spec,spec10}/**/*"] + [
|
36
|
-
'LICENSE',
|
37
|
-
'README',
|
38
|
-
'Rakefile',
|
39
|
-
'TODO',
|
40
|
-
'CHANGELOG',
|
41
|
-
'PUBLIC_CHANGELOG',
|
42
|
-
'CONTRIBUTORS'
|
43
|
-
]
|
44
|
-
|
45
|
-
# Runtime dependencies
|
46
|
-
gemspec.add_dependency 'bundler', '>= 0.9.3'
|
47
|
-
gemspec.add_dependency 'extlib', '>= 0.9.13'
|
48
|
-
gemspec.add_dependency 'erubis', '>= 2.6.2'
|
49
|
-
gemspec.add_dependency 'rake'
|
50
|
-
gemspec.add_dependency 'rspec'
|
51
|
-
gemspec.add_dependency 'rack'
|
52
|
-
gemspec.add_dependency 'mime-types', '>= 1.16' # supports ruby-1.9
|
53
|
-
|
54
|
-
# Development dependencies
|
55
|
-
gemspec.add_development_dependency 'rspec', '>= 1.2.9'
|
56
|
-
gemspec.add_development_dependency 'webrat', '>= 0.3.1'
|
57
|
-
|
58
|
-
# Executable files
|
59
|
-
gemspec.executables = 'merb'
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
Jeweler::GemcutterTasks.new
|
64
|
-
|
65
|
-
rescue LoadError
|
66
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
13
|
desc "Run the specs."
|
71
14
|
task :default => :specs
|
72
15
|
|
@@ -84,9 +27,8 @@ namespace :doc do
|
|
84
27
|
rdoc.rdoc_files.add(files)
|
85
28
|
rdoc.main = "README"
|
86
29
|
rdoc.title = "Merb Docs"
|
87
|
-
rdoc.template = File.expand_path("../tools/allison-2.0.2/lib/allison.rb", __FILE__)
|
88
30
|
rdoc.rdoc_dir = "doc/rdoc"
|
89
|
-
rdoc.options << "--line-numbers"
|
31
|
+
rdoc.options << "--line-numbers"
|
90
32
|
end
|
91
33
|
|
92
34
|
desc "run webgen"
|
data/lib/merb-core.rb
CHANGED
@@ -580,8 +580,9 @@ module Merb
|
|
580
580
|
# :log_level<Symbol>:: logger level, default is :info
|
581
581
|
#
|
582
582
|
# :disabled_components<Array[Symbol]>::
|
583
|
-
# array of disabled component names
|
584
|
-
#
|
583
|
+
# array of disabled component names,
|
584
|
+
# for instance, to disable json gem,
|
585
|
+
# specify :json. Default is empty array.
|
585
586
|
#
|
586
587
|
# :deferred_actions<Array(Symbol, String)]>::
|
587
588
|
# names of actions that should be deferred
|
data/lib/merb-core/bootloader.rb
CHANGED
@@ -378,6 +378,7 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
378
378
|
load_env_config
|
379
379
|
end
|
380
380
|
expand_ruby_path
|
381
|
+
enable_json_gem unless Merb::disabled?(:json)
|
381
382
|
update_logger
|
382
383
|
nil
|
383
384
|
end
|
@@ -404,6 +405,21 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
404
405
|
nil
|
405
406
|
end
|
406
407
|
|
408
|
+
# Requires json or json_pure.
|
409
|
+
#
|
410
|
+
# ==== Returns
|
411
|
+
# nil
|
412
|
+
#
|
413
|
+
# :api: private
|
414
|
+
def self.enable_json_gem
|
415
|
+
require "json"
|
416
|
+
rescue LoadError
|
417
|
+
Merb.logger.error! "You have enabled JSON but don't have json " \
|
418
|
+
"installed or don't have dependency in the Gemfile. " \
|
419
|
+
"Add \"gem 'json', '>= 1.1.7'\" or " \
|
420
|
+
"\"gem 'json_pure', '>= 1.1.7'\" to your Gemfile."
|
421
|
+
end
|
422
|
+
|
407
423
|
# Resets the logger and sets the log_stream to Merb::Config[:log_file]
|
408
424
|
# if one is specified, falling back to STDOUT.
|
409
425
|
#
|
@@ -1314,7 +1330,7 @@ class Merb::BootLoader::RackUpApplication < Merb::BootLoader
|
|
1314
1330
|
Merb::Config[:app] = eval("::Rack::Builder.new {( #{rackup_code}\n )}.to_app", TOPLEVEL_BINDING, Merb::Config[:rackup])
|
1315
1331
|
else
|
1316
1332
|
Merb::Config[:app] = ::Rack::Builder.new {
|
1317
|
-
use Rack::Head # handle head requests
|
1333
|
+
use Merb::Rack::Head # handle head requests
|
1318
1334
|
use Merb::Rack::ContentLength # report content length
|
1319
1335
|
if prefix = ::Merb::Config[:path_prefix]
|
1320
1336
|
use Merb::Rack::PathPrefix, prefix
|
data/lib/merb-core/config.rb
CHANGED
@@ -287,7 +287,7 @@ module Merb
|
|
287
287
|
adapters = [:mongrel, :emongrel, :thin, :ebb, :fastcgi, :webrick]
|
288
288
|
|
289
289
|
opts.on("-a", "--adapter ADAPTER",
|
290
|
-
"The rack adapter to use to run merb (default is
|
290
|
+
"The rack adapter to use to run merb (default is thin)" \
|
291
291
|
"[#{adapters.join(', ')}]") do |adapter|
|
292
292
|
options[:adapter] ||= adapter
|
293
293
|
end
|
@@ -4,119 +4,108 @@ module Merb
|
|
4
4
|
class Dispatcher
|
5
5
|
class << self
|
6
6
|
include Merb::ControllerExceptions
|
7
|
-
|
8
|
-
#
|
7
|
+
|
8
|
+
# @api private
|
9
9
|
attr_accessor :use_mutex
|
10
|
-
|
10
|
+
|
11
11
|
@@work_queue = Queue.new
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# :api: private
|
12
|
+
|
13
|
+
# @return [Queue] the current queue of dispatch jobs.
|
14
|
+
#
|
15
|
+
# @api private
|
17
16
|
def work_queue
|
18
17
|
@@work_queue
|
19
|
-
end
|
20
|
-
|
21
|
-
# Dispatch the rack environment.
|
22
|
-
# and redispatched.
|
18
|
+
end
|
19
|
+
|
20
|
+
# Dispatch the rack environment.
|
23
21
|
#
|
24
|
-
#
|
25
|
-
# rack_env<Rack::Environment>::
|
26
|
-
# The rack environment, which is used to instantiate a Merb::Request
|
22
|
+
# ControllerExceptions are rescued here and redispatched.
|
27
23
|
#
|
28
|
-
#
|
29
|
-
# Merb::Controller::
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# :api: private
|
24
|
+
# @param rack_env [Rack::Environment] The rack environment, which is used to instantiate a Merb::Request
|
25
|
+
# @return [Merb::Controller] The Merb::Controller that was dispatched to
|
26
|
+
#
|
27
|
+
# @api private
|
33
28
|
def handle(request)
|
34
29
|
request.handle
|
35
30
|
end
|
36
31
|
end
|
37
32
|
end
|
38
|
-
|
33
|
+
|
39
34
|
class Request
|
40
35
|
include Merb::ControllerExceptions
|
41
|
-
|
36
|
+
|
42
37
|
@@mutex = Mutex.new
|
43
|
-
|
38
|
+
|
44
39
|
attr_reader :start
|
45
|
-
|
46
|
-
# Handles request routing and action dispatch
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
# :api: private
|
40
|
+
|
41
|
+
# Handles request routing and action dispatch
|
42
|
+
#
|
43
|
+
# @return [Array[Integer, Hash, #each]] A Rack response
|
44
|
+
#
|
45
|
+
# @api private
|
52
46
|
def handle
|
53
47
|
@start = env["merb.request_start"] = Time.now
|
54
48
|
Merb.logger.info { "Started request handling: #{start.to_s}" }
|
55
|
-
|
49
|
+
|
56
50
|
find_route!
|
57
51
|
return rack_response if handled?
|
58
|
-
|
52
|
+
|
59
53
|
klass = controller
|
60
|
-
|
61
|
-
|
54
|
+
|
62
55
|
unless klass < Controller
|
63
|
-
raise NotFound,
|
56
|
+
raise NotFound,
|
64
57
|
"Controller '#{klass}' not found.\n" \
|
65
58
|
"If Merb tries to find a controller for static files, " \
|
66
59
|
"you may need to check your Rackup file, see the Problems " \
|
67
60
|
"section at: http://wiki.merbivore.com/pages/rack-middleware"
|
68
61
|
end
|
69
|
-
|
62
|
+
|
63
|
+
Merb.logger.debug { "Routed to: #{klass::_filter_params(params).inspect}" }
|
64
|
+
|
70
65
|
if klass.abstract?
|
71
66
|
raise NotFound, "The '#{klass}' controller has no public actions"
|
72
67
|
end
|
73
|
-
|
68
|
+
|
74
69
|
dispatch_action(klass, params[:action])
|
75
70
|
rescue Object => exception
|
76
71
|
dispatch_exception(exception)
|
77
72
|
end
|
78
|
-
|
73
|
+
|
79
74
|
private
|
80
|
-
# Setup the controller and call the chosen action
|
75
|
+
# Setup the controller and call the chosen action
|
76
|
+
#
|
77
|
+
# @param klass [Merb::Controller] The controller class to dispatch to.
|
78
|
+
# @param action [Symbol] The action to dispatch.
|
79
|
+
# @param status [Integer] The status code to respond with.
|
81
80
|
#
|
82
|
-
#
|
83
|
-
# klass<Merb::Controller>:: The controller class to dispatch to.
|
84
|
-
# action<Symbol>:: The action to dispatch.
|
85
|
-
# status<Integer>:: The status code to respond with.
|
81
|
+
# @return [Array[Integer, Hash, #each]] A Rack response
|
86
82
|
#
|
87
|
-
#
|
88
|
-
# Array[Integer, Hash, #each]:: A Rack response
|
89
|
-
#
|
90
|
-
# :api: private
|
83
|
+
# @api private
|
91
84
|
def dispatch_action(klass, action_name, status=200)
|
92
85
|
@env["merb.status"] = status
|
93
86
|
@env["merb.action_name"] = action_name
|
94
|
-
|
87
|
+
|
95
88
|
if Dispatcher.use_mutex
|
96
89
|
@@mutex.synchronize { klass.call(env) }
|
97
90
|
else
|
98
91
|
klass.call(env)
|
99
92
|
end
|
100
93
|
end
|
101
|
-
|
102
|
-
# Re-route the
|
103
|
-
# available, and try to render the exception nicely.
|
94
|
+
|
95
|
+
# Re-route the request to the Exception controller if it is available
|
104
96
|
#
|
105
97
|
# You can handle exceptions by implementing actions for specific
|
106
98
|
# exceptions such as not_found or for entire classes of exceptions
|
107
|
-
# such as client_error. You can also implement handlers for
|
99
|
+
# such as client_error. You can also implement handlers for
|
108
100
|
# exceptions outside the Merb exception hierarchy (e.g.
|
109
101
|
# StandardError is caught in standard_error).
|
110
102
|
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
# The exception object that was created when trying to dispatch the
|
114
|
-
# original controller.
|
103
|
+
# @param exception [Object] The exception object that was created when
|
104
|
+
# trying to dispatch the original controller.
|
115
105
|
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
# :api: private
|
106
|
+
# @return [Array[Integer, Hash, #each]] A Rack response
|
107
|
+
#
|
108
|
+
# @api private
|
120
109
|
def dispatch_exception(exception)
|
121
110
|
if(exception.is_a?(Merb::ControllerExceptions::Base) &&
|
122
111
|
!exception.is_a?(Merb::ControllerExceptions::ServerError))
|
@@ -124,12 +113,12 @@ module Merb
|
|
124
113
|
else
|
125
114
|
Merb.logger.error(Merb.exception(exception))
|
126
115
|
end
|
127
|
-
|
116
|
+
|
128
117
|
exceptions = env["merb.exceptions"] = [exception]
|
129
|
-
|
118
|
+
|
130
119
|
begin
|
131
120
|
e = exceptions.first
|
132
|
-
|
121
|
+
|
133
122
|
if action_name = e.action_name
|
134
123
|
dispatch_action(Exceptions, action_name, e.class.status)
|
135
124
|
else
|
@@ -141,7 +130,7 @@ module Merb
|
|
141
130
|
else
|
142
131
|
Merb.logger.error("Dispatching #{e.class} raised another error.")
|
143
132
|
Merb.logger.error(Merb.exception(dispatch_issue))
|
144
|
-
|
133
|
+
|
145
134
|
exceptions.unshift dispatch_issue
|
146
135
|
retry
|
147
136
|
end
|
@@ -324,7 +324,7 @@ module Merb
|
|
324
324
|
def message
|
325
325
|
return {} unless params[:_message]
|
326
326
|
begin
|
327
|
-
Marshal.load(
|
327
|
+
Marshal.load(params[:_message].unpack("m").first)
|
328
328
|
rescue ArgumentError, TypeError
|
329
329
|
{}
|
330
330
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'merb-core/dispatch/session/container'
|
2
2
|
require 'merb-core/dispatch/session/store_container'
|
3
3
|
|
4
|
+
# Try to require SecureRandom from the Ruby 1.9.x
|
5
|
+
begin
|
6
|
+
require 'securerandom'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
4
10
|
module Merb
|
5
11
|
class Config
|
6
12
|
# Returns stores list constructed from
|
@@ -74,16 +80,20 @@ module Merb
|
|
74
80
|
#
|
75
81
|
# :api: private
|
76
82
|
def rand_uuid
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
if defined?(SecureRandom)
|
84
|
+
SecureRandom.hex(16)
|
85
|
+
else
|
86
|
+
values = [
|
87
|
+
rand(0x0010000),
|
88
|
+
rand(0x0010000),
|
89
|
+
rand(0x0010000),
|
90
|
+
rand(0x0010000),
|
91
|
+
rand(0x0010000),
|
92
|
+
rand(0x1000000),
|
93
|
+
rand(0x1000000),
|
94
|
+
]
|
95
|
+
"%04x%04x%04x%04x%04x%06x%06x" % values
|
96
|
+
end
|
87
97
|
end
|
88
98
|
|
89
99
|
# Marks this session as needing a new cookie.
|