merb-core 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,18 @@
1
- == 1.1.0 "" 2009-11-
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" << "--inline-source"
31
+ rdoc.options << "--line-numbers"
90
32
  end
91
33
 
92
34
  desc "run webgen"
@@ -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
- # Default is empty array.
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
@@ -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
@@ -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 mongrel)" \
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
- # :api: private
7
+
8
+ # @api private
9
9
  attr_accessor :use_mutex
10
-
10
+
11
11
  @@work_queue = Queue.new
12
-
13
- # ==== Returns
14
- # Queue:: the current queue of dispatch jobs.
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. ControllerExceptions are rescued here
22
- # and redispatched.
18
+ end
19
+
20
+ # Dispatch the rack environment.
23
21
  #
24
- # ==== Parameters
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
- # ==== Returns
29
- # Merb::Controller::
30
- # The Merb::Controller that was dispatched to
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
- # ==== Returns
49
- # Array[Integer, Hash, #each]:: A Rack response
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
- Merb.logger.debug { "Routed to: #{klass::_filter_params(params).inspect}" }
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
- # ==== Parameters
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
- # ==== Returns
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 current request to the Exception controller if it is
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
- # ==== Parameters
112
- # exception<Object>::
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
- # ==== Returns
117
- # Array[Integer, Hash, #each]:: A Rack response
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(Merb::Parse.unescape(params[:_message]).unpack("m").first)
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
- values = [
78
- rand(0x0010000),
79
- rand(0x0010000),
80
- rand(0x0010000),
81
- rand(0x0010000),
82
- rand(0x0010000),
83
- rand(0x1000000),
84
- rand(0x1000000),
85
- ]
86
- "%04x%04x%04x%04x%04x%06x%06x" % values
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.