aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/middleware/cookies.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/cookies.rb')
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb62
1 files changed, 31 insertions, 31 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 8c4615c0c1..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,14 +118,9 @@ module ActionDispatch
@delete_cookies = {}
@host = host
@secure = secure
- @closed = false
@cookies = {}
end
- attr_reader :closed
- alias :closed? :closed
- def close!; @closed = true end
-
def each(&block)
@cookies.each(&block)
end
@@ -158,14 +154,13 @@ 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
# Sets the cookie named +name+. The second argument may be the very cookie
# value, or a hash of options as documented above.
def []=(key, options)
- raise ClosedError, :cookies if closed?
if options.is_a?(Hash)
options.symbolize_keys!
value = options[:value]
@@ -174,12 +169,14 @@ module ActionDispatch
options = { :value => value }
end
- value = @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
@@ -187,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)
@@ -196,6 +194,15 @@ module ActionDispatch
value
end
+ # Whether the given cookie is to be deleted by this CookieJar.
+ # Like <tt>[]=</tt>, you can pass in an options hash to test if a
+ # deletion applies to a specific <tt>:path</tt>, <tt>:domain</tt> etc.
+ def deleted?(key, options = {})
+ options.symbolize_keys!
+ handle_options(options)
+ @delete_cookies[key.to_s] == options
+ end
+
# Removes all cookies on the client machine by calling <tt>delete</tt> for each cookie
def clear(options = {})
@cookies.each_key{ |k| delete(k, options) }
@@ -221,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:
#
@@ -243,10 +250,13 @@ module ActionDispatch
@delete_cookies.clear
end
+ mattr_accessor :always_write_cookie
+ self.always_write_cookie = false
+
private
def write_cookie?(cookie)
- @secure || !cookie[:secure] || defined?(Rails.env) && Rails.env.development?
+ @secure || !cookie[:secure] || always_write_cookie
end
end
@@ -256,7 +266,6 @@ module ActionDispatch
end
def []=(key, options)
- raise ClosedError, :cookies if closed?
if options.is_a?(Hash)
options.symbolize_keys!
else
@@ -267,10 +276,6 @@ module ActionDispatch
@parent_jar[key] = options
end
- def signed
- @signed ||= SignedCookieJar.new(self, @secret)
- end
-
def method_missing(method, *arguments, &block)
@parent_jar.send(method, *arguments, &block)
end
@@ -295,7 +300,6 @@ module ActionDispatch
end
def []=(key, options)
- raise ClosedError, :cookies if closed?
if options.is_a?(Hash)
options.symbolize_keys!
options[:value] = @verifier.generate(options[:value])
@@ -338,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']
@@ -349,9 +352,6 @@ module ActionDispatch
end
[status, headers, body]
- ensure
- cookie_jar = ActionDispatch::Request.new(env).cookie_jar unless cookie_jar
- cookie_jar.close!
end
end
end