merb-core 0.9.13 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/Rakefile +5 -3
  2. data/lib/merb-core.rb +84 -41
  3. data/lib/merb-core/bootloader.rb +71 -60
  4. data/lib/merb-core/config.rb +31 -17
  5. data/lib/merb-core/controller/abstract_controller.rb +35 -35
  6. data/lib/merb-core/controller/exceptions.rb +14 -9
  7. data/lib/merb-core/controller/merb_controller.rb +22 -20
  8. data/lib/merb-core/controller/mime.rb +5 -5
  9. data/lib/merb-core/controller/mixins/authentication.rb +11 -8
  10. data/lib/merb-core/controller/mixins/conditional_get.rb +7 -7
  11. data/lib/merb-core/controller/mixins/controller.rb +15 -15
  12. data/lib/merb-core/controller/mixins/render.rb +16 -16
  13. data/lib/merb-core/controller/mixins/responder.rb +23 -23
  14. data/lib/merb-core/controller/template.rb +17 -17
  15. data/lib/merb-core/core_ext/hash.rb +2 -2
  16. data/lib/merb-core/core_ext/kernel.rb +19 -18
  17. data/lib/merb-core/dispatch/cookies.rb +13 -0
  18. data/lib/merb-core/dispatch/default_exception/default_exception.rb +12 -1
  19. data/lib/merb-core/dispatch/dispatcher.rb +6 -5
  20. data/lib/merb-core/dispatch/request.rb +56 -52
  21. data/lib/merb-core/dispatch/request_parsers.rb +7 -7
  22. data/lib/merb-core/dispatch/router.rb +14 -14
  23. data/lib/merb-core/dispatch/router/behavior.rb +31 -31
  24. data/lib/merb-core/dispatch/router/cached_proc.rb +13 -1
  25. data/lib/merb-core/dispatch/router/resources.rb +9 -9
  26. data/lib/merb-core/dispatch/router/route.rb +60 -7
  27. data/lib/merb-core/dispatch/session.rb +21 -15
  28. data/lib/merb-core/dispatch/session/container.rb +10 -8
  29. data/lib/merb-core/dispatch/session/cookie.rb +12 -11
  30. data/lib/merb-core/dispatch/session/memcached.rb +4 -2
  31. data/lib/merb-core/dispatch/session/memory.rb +8 -6
  32. data/lib/merb-core/dispatch/session/store_container.rb +6 -5
  33. data/lib/merb-core/dispatch/worker.rb +28 -10
  34. data/lib/merb-core/gem_ext/erubis.rb +4 -2
  35. data/lib/merb-core/logger.rb +3 -22
  36. data/lib/merb-core/plugins.rb +5 -5
  37. data/lib/merb-core/rack.rb +1 -1
  38. data/lib/merb-core/rack/adapter.rb +5 -1
  39. data/lib/merb-core/rack/adapter/abstract.rb +15 -10
  40. data/lib/merb-core/rack/adapter/ebb.rb +4 -2
  41. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -1
  42. data/lib/merb-core/rack/adapter/fcgi.rb +3 -1
  43. data/lib/merb-core/rack/adapter/irb.rb +10 -1
  44. data/lib/merb-core/rack/adapter/mongrel.rb +5 -2
  45. data/lib/merb-core/rack/adapter/runner.rb +3 -1
  46. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +2 -1
  47. data/lib/merb-core/rack/adapter/thin.rb +4 -1
  48. data/lib/merb-core/rack/adapter/thin_turbo.rb +1 -0
  49. data/lib/merb-core/rack/adapter/webrick.rb +8 -34
  50. data/lib/merb-core/rack/application.rb +2 -2
  51. data/lib/merb-core/rack/handler/mongrel.rb +7 -0
  52. data/lib/merb-core/rack/helpers.rb +1 -1
  53. data/lib/merb-core/rack/middleware.rb +7 -1
  54. data/lib/merb-core/rack/middleware/conditional_get.rb +3 -0
  55. data/lib/merb-core/rack/middleware/content_length.rb +2 -0
  56. data/lib/merb-core/rack/middleware/path_prefix.rb +4 -0
  57. data/lib/merb-core/rack/middleware/profiler.rb +3 -1
  58. data/lib/merb-core/rack/middleware/static.rb +7 -1
  59. data/lib/merb-core/rack/middleware/tracer.rb +1 -0
  60. data/lib/merb-core/rack/stream_wrapper.rb +35 -30
  61. data/lib/merb-core/server.rb +17 -16
  62. data/lib/merb-core/tasks/gem_management.rb +1 -1
  63. data/lib/merb-core/tasks/merb.rb +3 -1
  64. data/lib/merb-core/tasks/merb_rake_helper.rb +1 -1
  65. data/lib/merb-core/test.rb +8 -8
  66. data/lib/merb-core/test/helpers.rb +1 -1
  67. data/lib/merb-core/test/helpers/cookie_jar.rb +16 -2
  68. data/lib/merb-core/test/helpers/mock_request_helper.rb +13 -13
  69. data/lib/merb-core/test/helpers/request_helper.rb +1 -1
  70. data/lib/merb-core/test/helpers/route_helper.rb +2 -2
  71. data/lib/merb-core/test/matchers.rb +3 -3
  72. data/lib/merb-core/test/matchers/request_matchers.rb +1 -1
  73. data/lib/merb-core/test/run_spec.rb +1 -1
  74. data/lib/merb-core/test/tasks/spectasks.rb +1 -1
  75. data/lib/merb-core/test/test_ext/hpricot.rb +1 -1
  76. data/lib/merb-core/test/test_ext/rspec.rb +2 -2
  77. data/lib/merb-core/test/test_ext/string.rb +1 -1
  78. data/lib/merb-core/version.rb +1 -1
  79. metadata +8 -22
  80. data/lib/merb-core/test/matchers/view_matchers.rb +0 -231
  81. data/lib/merb-core/test/webrat.rb +0 -37
  82. data/lib/merb-core/vendor/nokogiri/css.rb +0 -6
  83. data/lib/merb-core/vendor/nokogiri/css/generated_parser.rb +0 -653
  84. data/lib/merb-core/vendor/nokogiri/css/generated_tokenizer.rb +0 -159
  85. data/lib/merb-core/vendor/nokogiri/css/node.rb +0 -95
  86. data/lib/merb-core/vendor/nokogiri/css/parser.rb +0 -24
  87. data/lib/merb-core/vendor/nokogiri/css/parser.y +0 -198
  88. data/lib/merb-core/vendor/nokogiri/css/tokenizer.rb +0 -9
  89. data/lib/merb-core/vendor/nokogiri/css/tokenizer.rex +0 -63
  90. data/lib/merb-core/vendor/nokogiri/css/xpath_visitor.rb +0 -159
@@ -5,7 +5,9 @@ module Merb
5
5
  cattr_accessor :subclasses
6
6
  self.subclasses = []
7
7
 
8
+ # :api: private
8
9
  attr_reader :session_id
10
+ # :api: private
9
11
  attr_accessor :needs_new_cookie
10
12
 
11
13
  class << self
@@ -21,7 +23,7 @@ module Merb
21
23
  # ==== Returns
22
24
  # SessionContainer:: The new session.
23
25
  #
24
- # @api private
26
+ # :api: private
25
27
  def generate
26
28
  end
27
29
 
@@ -34,7 +36,7 @@ module Merb
34
36
  # ==== Returns
35
37
  # SessionContainer:: a SessionContainer.
36
38
  #
37
- # @api private
39
+ # :api: private
38
40
  def setup(request)
39
41
  end
40
42
 
@@ -43,7 +45,7 @@ module Merb
43
45
  # ==== Parameters
44
46
  # session_id<String>:: A unique identifier for this session.
45
47
  #
46
- # @api private
48
+ # :api: private
47
49
  def initialize(session_id)
48
50
  @_destroy = false
49
51
  self.session_id = session_id
@@ -54,7 +56,7 @@ module Merb
54
56
  # Recreates the cookie with the default expiration time. Useful during log
55
57
  # in for pushing back the expiration date.
56
58
  #
57
- # @api private
59
+ # :api: private
58
60
  def session_id=(sid)
59
61
  self.needs_new_cookie = (@session_id && @session_id != sid)
60
62
  @session_id = sid
@@ -68,13 +70,13 @@ module Merb
68
70
  # ==== Parameters
69
71
  # request<Merb::Request>:: The Merb::Request that came in from Rack.
70
72
  #
71
- # @api private
73
+ # :api: private
72
74
  def finalize(request)
73
75
  end
74
76
 
75
77
  # Destroy the current session - clears data and removes session cookie.
76
78
  #
77
- # @api private
79
+ # :api: private
78
80
  def clear!
79
81
  @_destroy = true
80
82
  self.clear
@@ -82,9 +84,9 @@ module Merb
82
84
 
83
85
  # Regenerate the session_id.
84
86
  #
85
- # @api private
87
+ # :api: private
86
88
  def regenerate
87
89
  end
88
90
 
89
91
  end
90
- end
92
+ end
@@ -14,7 +14,7 @@ module Merb
14
14
  #
15
15
  # To use Cookie Sessions, set in config/merb.yml
16
16
  # :session_secret_key - your secret digest key
17
- # :session_store: cookie
17
+ # :session_store - cookie
18
18
  class CookieSession < SessionContainer
19
19
  # TODO (maybe):
20
20
  # include request ip address
@@ -30,6 +30,7 @@ module Merb
30
30
  MAX = 4096
31
31
  DIGEST = OpenSSL::Digest::Digest.new('SHA1') # or MD5, RIPEMD160, SHA256?
32
32
 
33
+ # :api: private
33
34
  attr_accessor :_original_session_data
34
35
 
35
36
  # The session store type
@@ -41,7 +42,7 @@ module Merb
41
42
  # ==== Returns
42
43
  # SessionContainer:: The new session.
43
44
  #
44
- # @api private
45
+ # :api: private
45
46
  def generate
46
47
  self.new(Merb::SessionMixin.rand_uuid, "", Merb::Request._session_secret_key)
47
48
  end
@@ -55,7 +56,7 @@ module Merb
55
56
  # SessionContainer:: a SessionContainer. If no sessions were found,
56
57
  # a new SessionContainer will be generated.
57
58
  #
58
- # @api private
59
+ # :api: private
59
60
  def setup(request)
60
61
  session = self.new(Merb::SessionMixin.rand_uuid,
61
62
  request.session_cookie_value, request._session_secret_key)
@@ -73,7 +74,7 @@ module Merb
73
74
  # ==== Raises
74
75
  # ArgumentError:: blank or insufficiently long secret.
75
76
  #
76
- # @api private
77
+ # :api: private
77
78
  def initialize(session_id, cookie, secret)
78
79
  super session_id
79
80
  if secret.blank? || secret.length < 16
@@ -93,7 +94,7 @@ module Merb
93
94
  # ==== Parameters
94
95
  # request<Merb::Request>:: request object created from Rack environment.
95
96
  #
96
- # @api private
97
+ # :api: private
97
98
  def finalize(request)
98
99
  if @_destroy
99
100
  request.destroy_session_cookie
@@ -104,7 +105,7 @@ module Merb
104
105
 
105
106
  # Regenerate the session_id.
106
107
  #
107
- # @api private
108
+ # :api: private
108
109
  def regenerate
109
110
  self.session_id = Merb::SessionMixin.rand_uuid
110
111
  end
@@ -122,7 +123,7 @@ module Merb
122
123
  # choose to marshal it, which would make it persist
123
124
  # attributes like 'needs_new_cookie', which it shouldn't.
124
125
  #
125
- # @api private
126
+ # :api: private
126
127
  def to_cookie
127
128
  unless self.empty?
128
129
  data = self.serialize
@@ -143,7 +144,7 @@ module Merb
143
144
  # ==== Returns
144
145
  # String:: an HMAC digest of the cookie data.
145
146
  #
146
- # @api private
147
+ # :api: private
147
148
  def generate_digest(data)
148
149
  OpenSSL::HMAC.hexdigest(DIGEST, @secret, data)
149
150
  end
@@ -159,7 +160,7 @@ module Merb
159
160
  # ==== Returns
160
161
  # Hash:: The stored session data.
161
162
  #
162
- # @api private
163
+ # :api: private
163
164
  def unmarshal(cookie)
164
165
  if cookie.blank?
165
166
  {}
@@ -184,7 +185,7 @@ module Merb
184
185
  # ==== Returns
185
186
  # String:: Base64 encoded dump of the session hash.
186
187
  #
187
- # @api private
188
+ # :api: private
188
189
  def serialize
189
190
  Base64.encode64(Marshal.dump(self.to_hash)).chop
190
191
  end
@@ -194,7 +195,7 @@ module Merb
194
195
  # ==== Returns
195
196
  # Hash:: the session hash Base64 decoded from the data dump.
196
197
  #
197
- # @api private
198
+ # :api: private
198
199
  def unserialize(data)
199
200
  Marshal.load(Base64.decode64(data)) rescue {}
200
201
  end
@@ -37,7 +37,7 @@ module Merb
37
37
  # ==== Returns
38
38
  # ContainerSession:: The session corresponding to the ID.
39
39
  #
40
- # @api private
40
+ # :api: private
41
41
  def retrieve_session(session_id)
42
42
  get("session:#{session_id}")
43
43
  end
@@ -46,13 +46,15 @@ module Merb
46
46
  # session_id<String>:: ID of the session to set.
47
47
  # data<ContainerSession>:: The session to set.
48
48
  #
49
- # @api private
49
+ # :api: private
50
50
  def store_session(session_id, data)
51
51
  set("session:#{session_id}", data)
52
52
  end
53
53
 
54
54
  # ==== Parameters
55
55
  # session_id<String>:: ID of the session to delete.
56
+ #
57
+ # :api: private
56
58
  def delete_session(session_id)
57
59
  delete("session:#{session_id}")
58
60
  end
@@ -21,11 +21,13 @@ module Merb
21
21
  self.session_store_type = :memory
22
22
 
23
23
  # Bypass normal implicit class attribute reader - see below.
24
+ # :api: private
24
25
  def store
25
26
  self.class.store
26
27
  end
27
28
 
28
29
  # Lazy load/setup of MemorySessionStore.
30
+ # :api: private
29
31
  def self.store
30
32
  @_store ||= MemorySessionStore.new(Merb::Config[:memory_session_ttl])
31
33
  end
@@ -38,7 +40,7 @@ module Merb
38
40
  # ==== Parameters
39
41
  # ttl<Fixnum>:: Session validity time in seconds. Defaults to 1 hour.
40
42
  #
41
- # @api private
43
+ # :api: private
42
44
  def initialize(ttl=nil)
43
45
  @sessions = Hash.new
44
46
  @timestamps = Hash.new
@@ -53,7 +55,7 @@ module Merb
53
55
  # ==== Returns
54
56
  # ContainerSession:: The session corresponding to the ID.
55
57
  #
56
- # @api private
58
+ # :api: private
57
59
  def retrieve_session(session_id)
58
60
  @mutex.synchronize {
59
61
  @timestamps[session_id] = Time.now
@@ -65,7 +67,7 @@ module Merb
65
67
  # session_id<String>:: ID of the session to set.
66
68
  # data<ContainerSession>:: The session to set.
67
69
  #
68
- # @api private
70
+ # :api: private
69
71
  def store_session(session_id, data)
70
72
  @mutex.synchronize {
71
73
  @timestamps[session_id] = Time.now
@@ -76,7 +78,7 @@ module Merb
76
78
  # ==== Parameters
77
79
  # session_id<String>:: ID of the session to delete.
78
80
  #
79
- # @api private
81
+ # :api: private
80
82
  def delete_session(session_id)
81
83
  @mutex.synchronize {
82
84
  @timestamps.delete(session_id)
@@ -86,7 +88,7 @@ module Merb
86
88
 
87
89
  # Deletes any sessions that have reached their maximum validity.
88
90
  #
89
- # @api private
91
+ # :api: private
90
92
  def reap_expired_sessions
91
93
  @timestamps.each do |session_id,stamp|
92
94
  delete_session(session_id) if (stamp + @session_ttl) < Time.now
@@ -96,7 +98,7 @@ module Merb
96
98
 
97
99
  # Starts the timer that will eventually reap outdated sessions.
98
100
  #
99
- # @api private
101
+ # :api: private
100
102
  def start_timer
101
103
  Thread.new do
102
104
  loop {
@@ -3,6 +3,7 @@ module Merb
3
3
  class SessionStoreContainer < SessionContainer
4
4
 
5
5
  class_inheritable_accessor :store
6
+ # :api: private
6
7
  attr_accessor :_fingerprint
7
8
 
8
9
  # The class attribute :store holds a reference to an object that implements
@@ -51,7 +52,7 @@ module Merb
51
52
  # ==== Returns
52
53
  # SessionStoreContainer:: The new session.
53
54
  #
54
- # @api private
55
+ # :api: private
55
56
  def generate
56
57
  session = new(Merb::SessionMixin.rand_uuid)
57
58
  session.needs_new_cookie = true
@@ -69,7 +70,7 @@ module Merb
69
70
  # ==== Returns
70
71
  # SessionContainer:: a SessionContainer.
71
72
  #
72
- # @api private
73
+ # :api: private
73
74
  def setup(request)
74
75
  session = retrieve(request.session_id)
75
76
  request.session = session
@@ -91,7 +92,7 @@ module Merb
91
92
  # If there are persisted exceptions callbacks to execute, they all get executed
92
93
  # when Memcache library raises an exception.
93
94
  #
94
- # @api private
95
+ # :api: private
95
96
  def retrieve(session_id)
96
97
  unless session_id.blank?
97
98
  begin
@@ -130,7 +131,7 @@ module Merb
130
131
  # choose to do a full Marshal on the data, which would make it persist
131
132
  # attributes like 'needs_new_cookie', which it shouldn't.
132
133
  #
133
- # @api private
134
+ # :api: private
134
135
  def finalize(request)
135
136
  if @_destroy
136
137
  store.delete_session(self.session_id)
@@ -151,7 +152,7 @@ module Merb
151
152
 
152
153
  # Regenerate the session ID.
153
154
  #
154
- # @api private
155
+ # :api: private
155
156
  def regenerate
156
157
  store.delete_session(self.session_id)
157
158
  self.session_id = Merb::SessionMixin.rand_uuid
@@ -1,26 +1,43 @@
1
1
  module Merb
2
2
  class Worker
3
3
 
4
+ # :api: private
4
5
  attr_accessor :thread
5
6
 
6
- # ==== Returns
7
- # Merb::Worker:: instance of a worker.
8
- #
9
- # @api private
10
- def self.start
11
- new
7
+ class << self
8
+ # ==== Returns
9
+ # Merb::Worker:: instance of a worker.
10
+ #
11
+ # :api: private
12
+ def start
13
+ @worker ||= new
14
+ Merb.at_exit do
15
+ if Merb::Dispatcher.work_queue.empty?
16
+ @worker.thread.abort_on_exception = false
17
+ @worker.thread.raise
18
+ else
19
+ @worker.thread.join
20
+ end
21
+ end
22
+ @worker
23
+ end
12
24
  end
13
25
 
14
26
  # Creates a new worker thread that loops over the work queue.
15
27
  #
16
- # @api private
28
+ # :api: private
17
29
  def initialize
18
- @thread = Thread.new { loop { process_queue } }
30
+ @thread = Thread.new do
31
+ loop do
32
+ process_queue
33
+ break if Merb::Dispatcher.work_queue.empty? && Merb.exiting
34
+ end
35
+ end
19
36
  end
20
37
 
21
38
  # Processes tasks in the Merb::Dispatcher.work_queue.
22
39
  #
23
- # @api private
40
+ # :api: private
24
41
  def process_queue
25
42
  begin
26
43
  while blk = Merb::Dispatcher.work_queue.pop
@@ -31,6 +48,7 @@ module Merb
31
48
  # it's own processing
32
49
  Thread.pass
33
50
  blk.call
51
+ break if Merb::Dispatcher.work_queue.empty? && Merb.exiting
34
52
  end
35
53
  rescue Exception => e
36
54
  Merb.logger.warn! %Q!Worker Thread Crashed with Exception:\n#{Merb.exception(e)}\nRestarting Worker Thread!
@@ -39,4 +57,4 @@ module Merb
39
57
  end
40
58
 
41
59
  end
42
- end
60
+ end
@@ -3,7 +3,7 @@ module Erubis
3
3
  # This adds support for embedding the return value of a block call:
4
4
  # <%= foo do %>...<% end =%>
5
5
  #
6
- # @api private
6
+ # :api: private
7
7
  module Basic::Converter
8
8
  def convert_input(src, input)
9
9
  pat = @pattern
@@ -75,7 +75,9 @@ module Erubis
75
75
  # binding<Binding>::
76
76
  # The binding to use when evaluating the ERB tags. Defaults to the current
77
77
  # binding.
78
+ #
79
+ # :api: private
78
80
  def self.load_yaml_file(file, binding = binding)
79
81
  YAML::load(Erubis::MEruby.new(IO.read(File.expand_path(file))).result(binding))
80
82
  end
81
- end
83
+ end
@@ -1,10 +1,12 @@
1
1
  # Merb::Logger = Extlib::Logger
2
2
 
3
3
  class Merb::Logger < Extlib::Logger
4
+ # :api: public
4
5
  def verbose!(message, level = :warn)
5
6
  send("#{level}!", message) if Merb::Config[:verbose]
6
7
  end
7
8
 
9
+ # :api: public
8
10
  def verbose(message, level = :warn)
9
11
  send(level, message) if Merb::Config[:verbose]
10
12
  end
@@ -71,28 +73,6 @@ module Merb
71
73
 
72
74
  @@mutex = {}
73
75
 
74
- private
75
-
76
- # Readies a log for writing.
77
- #
78
- # ==== Parameters
79
- # log<IO, String>:: Either an IO object or a name of a logfile.
80
- def initialize_log(log)
81
- close if @log # be sure that we don't leave open files laying around.
82
-
83
- if log.respond_to?(:write)
84
- @log = log
85
- elsif File.exist?(log)
86
- @log = open(log, (File::WRONLY | File::APPEND))
87
- @log.sync = true
88
- else
89
- FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
90
- @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
91
- @log.sync = true
92
- @log.write("#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n")
93
- end
94
- end
95
-
96
76
  public
97
77
 
98
78
  # To initialize the logger you create a new object, proxies to set_log.
@@ -131,6 +111,7 @@ module Merb
131
111
  end
132
112
 
133
113
  @log = stream
114
+ @log.sync = true
134
115
  @mutex = (@@mutex[@log] ||= Mutex.new)
135
116
  end
136
117