diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware')
9 files changed, 62 insertions, 47 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 0c717c8503..771f075275 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -2,7 +2,7 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/keys' module ActionDispatch - class Request + class Request < Rack::Request def cookie_jar env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self) end @@ -26,9 +26,9 @@ module ActionDispatch # # Sets a cookie that expires in 1 hour. # cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now } # - # # Sets a signed cookie, which prevents a user from tampering with its value. + # # Sets a signed cookie, which prevents users from tampering with its value. # # The cookie is signed by your app's <tt>config.secret_token</tt> value. - # # Rails generates this value by default when you create a new Rails app. + # # It can be read using the signed method <tt>cookies.signed[:key]</tt> # cookies.signed[:user_id] = current_user.id # # # Sets a "permanent" cookie (which expires in 20 years from now). @@ -39,9 +39,10 @@ module ActionDispatch # # Examples for reading: # - # cookies[:user_name] # => "david" - # cookies.size # => 2 - # cookies[:lat_lon] # => [47.68, -122.37] + # cookies[:user_name] # => "david" + # cookies.size # => 2 + # cookies[:lat_lon] # => [47.68, -122.37] + # cookies.signed[:login] # => "XJ-122" # # Example for deleting: # @@ -82,7 +83,7 @@ module ActionDispatch TOKEN_KEY = "action_dispatch.secret_token".freeze # Raised when storing more than 4K of session data. - class CookieOverflow < StandardError; end + CookieOverflow = Class.new StandardError class CookieJar #:nodoc: include Enumerable @@ -117,7 +118,6 @@ module ActionDispatch @delete_cookies = {} @host = host @secure = secure - @closed = false @cookies = {} end @@ -154,7 +154,7 @@ module ActionDispatch end elsif options[:domain].is_a? Array # if host matches one of the supplied domains without a dot in front of it - options[:domain] = options[:domain].find {|domain| @host.include? domain[/^\.?(.*)$/, 1] } + options[:domain] = options[:domain].find {|domain| @host.include? domain.sub(/^\./, '') } end end @@ -169,12 +169,14 @@ module ActionDispatch options = { :value => value } end - @cookies[key.to_s] = value - handle_options(options) - @set_cookies[key.to_s] = options - @delete_cookies.delete(key.to_s) + if @cookies[key.to_s] != value or options[:expires] + @cookies[key.to_s] = value + @set_cookies[key.to_s] = options + @delete_cookies.delete(key.to_s) + end + value end @@ -182,8 +184,9 @@ module ActionDispatch # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in # an options hash to delete cookies with extra data such as a <tt>:path</tt>. def delete(key, options = {}) - options.symbolize_keys! + return unless @cookies.has_key? key.to_s + options.symbolize_keys! handle_options(options) value = @cookies.delete(key.to_s) @@ -225,7 +228,7 @@ module ActionDispatch # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will # be raised. # - # This jar requires that you set a suitable secret for the verification on your app's config.secret_token. + # This jar requires that you set a suitable secret for the verification on your app's +config.secret_token+. # # Example: # @@ -339,7 +342,6 @@ module ActionDispatch end def call(env) - cookie_jar = nil status, headers, body = @app.call(env) if cookie_jar = env['action_dispatch.cookies'] diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index c0532c80c4..982f6641bf 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -10,6 +10,7 @@ module ActionDispatch 'AbstractController::ActionNotFound' => :not_found, 'ActionController::MethodNotAllowed' => :method_not_allowed, 'ActionController::NotImplemented' => :not_implemented, + 'ActionController::UnknownFormat' => :not_acceptable, 'ActionController::InvalidAuthenticityToken' => :unprocessable_entity ) diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index c92c91df65..17776c2356 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -1,10 +1,10 @@ module ActionDispatch - class Request + class Request < Rack::Request # Access the contents of the flash. Use <tt>flash["notice"]</tt> to # read a notice you put there or <tt>flash["notice"] = "hello"</tt> # to put a new one. def flash - @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new) + @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new).tap(&:sweep) end end @@ -79,7 +79,6 @@ module ActionDispatch def initialize #:nodoc: @discard = Set.new - @closed = false @flashes = {} @now = nil end @@ -217,13 +216,9 @@ module ActionDispatch end def call(env) - if (session = env['rack.session']) && (flash = session['flash']) - flash.sweep - end - @app.call(env) ensure - session = env['rack.session'] || {} + session = Request::Session.find(env) || {} flash_hash = env[KEY] if flash_hash @@ -237,7 +232,8 @@ module ActionDispatch env[KEY] = new_hash end - if session.key?('flash') && session['flash'].empty? + if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?) + session.key?('flash') && session['flash'].empty? session.delete('flash') end end diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb index a0388e0e13..2f6968eb2e 100644 --- a/actionpack/lib/action_dispatch/middleware/reloader.rb +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -18,10 +18,10 @@ module ActionDispatch # classes before they are unloaded. # # By default, ActionDispatch::Reloader is included in the middleware stack - # only in the development environment; specifically, when config.cache_classes + # only in the development environment; specifically, when +config.cache_classes+ # is false. Callbacks may be registered even when it is not included in the - # middleware stack, but are executed only when +ActionDispatch::Reloader.prepare!+ - # or +ActionDispatch::Reloader.cleanup!+ are called manually. + # middleware stack, but are executed only when <tt>ActionDispatch::Reloader.prepare!</tt> + # or <tt>ActionDispatch::Reloader.cleanup!</tt> are called manually. # class Reloader include ActiveSupport::Callbacks diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 6a8e690d18..64159fa8e7 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -2,26 +2,23 @@ require 'rack/utils' require 'rack/request' require 'rack/session/abstract/id' require 'action_dispatch/middleware/cookies' +require 'action_dispatch/request/session' require 'active_support/core_ext/object/blank' module ActionDispatch module Session class SessionRestoreError < StandardError #:nodoc: - end + attr_reader :original_exception + + def initialize(const_error) + @original_exception = const_error - module DestroyableSession - def destroy - clear - options = @env[Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY] if @env - options ||= {} - @by.send(:destroy_session, @env, options[:id], options) if @by - options[:id] = nil - @loaded = false + super("Session contains objects whose class definition isn't available.\n" + + "Remember to require the classes for all objects kept in the session.\n" + + "(Original exception: #{const_error.message} [#{const_error.class}])\n") end end - ::Rack::Session::Abstract::SessionHash.send :include, DestroyableSession - module Compatibility def initialize(app, options = {}) options[:key] ||= '_session_id' @@ -58,11 +55,8 @@ module ActionDispatch begin # Note that the regexp does not allow $1 to end with a ':' $1.constantize - rescue LoadError, NameError => const_error - raise ActionDispatch::Session::SessionRestoreError, - "Session contains objects whose class definition isn't available.\n" + - "Remember to require the classes for all objects kept in the session.\n" + - "(Original exception: #{const_error.message} [#{const_error.class}])\n" + rescue LoadError, NameError => e + raise ActionDispatch::Session::SessionRestoreError, e, e.backtrace end retry else @@ -71,9 +65,27 @@ module ActionDispatch end end + module SessionObject # :nodoc: + def prepare_session(env) + Request::Session.create(self, env, @default_options) + end + + def loaded_session?(session) + !session.is_a?(Request::Session) || session.loaded? + end + end + class AbstractStore < Rack::Session::Abstract::ID include Compatibility include StaleSessionCheck + include SessionObject + + private + + def set_cookie(env, session_id, cookie) + request = ActionDispatch::Request.new(env) + request.cookie_jar[key] = cookie + end end end end diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index a4866f5a8f..dbcf703ec3 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -43,6 +43,7 @@ module ActionDispatch class CookieStore < Rack::Session::Cookie include Compatibility include StaleSessionCheck + include SessionObject private diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index 4dd9a946c2..38a737cd2b 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -6,6 +6,7 @@ module ActionDispatch class MemCacheStore < Rack::Session::Memcache include Compatibility include StaleSessionCheck + include SessionObject def initialize(app, options = {}) require 'memcache' diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb index 0c5bafa666..823f5d25b6 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb @@ -12,8 +12,8 @@ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") - def debug_hash(hash) - hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") + def debug_hash(object) + object.to_hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") end unless self.class.method_defined?(:debug_hash) %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb index f06c07daa5..177d383e94 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb @@ -12,4 +12,6 @@ <% end %> <p> Try running <code>rake routes</code> for more information on available routes. -</p>
\ No newline at end of file +</p> + +<%= render :template => "rescues/_trace" %> |