Skip to content

Commit

Permalink
Allow proc for per-request cookie domain
Browse files Browse the repository at this point in the history
Per-request cookie domain set through proc
  • Loading branch information
RobL committed Dec 22, 2022
1 parent 95fb5b4 commit 83da2e9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
4 changes: 4 additions & 0 deletions actionpack/CHANGELOG.md
@@ -1,3 +1,7 @@
* Allow cookie options[:domain] to accept a proc to set the cookie domain on a more flexible per-request basis

*RobL*

* When a host is not specified for an `ActionController::Renderer`'s env,
the host and related options will now be derived from the routes'
`default_url_options` and `ActionDispatch::Http::URL.secure_protocol`.
Expand Down
9 changes: 8 additions & 1 deletion actionpack/lib/action_dispatch/middleware/cookies.rb
Expand Up @@ -160,13 +160,18 @@ def use_cookies_with_metadata
# to <tt>:all</tt>. To support multiple domains, provide an array, and
# the first domain matching <tt>request.host</tt> will be used. Make
# sure to specify the <tt>:domain</tt> option with <tt>:all</tt> or
# <tt>Array</tt> again when deleting cookies.
# <tt>Array</tt> again when deleting cookies. For more flexibility you
# can set the domain on a per-request basis by specifying <tt>:domain</tt>
# with a proc.
#
# domain: nil # Does not set cookie domain. (default)
# domain: :all # Allow the cookie for the top most level
# # domain and subdomains.
# domain: %w(.example.com .example.org) # Allow the cookie
# # for concrete domain names.
# domain: proc { Tenant.current.cookie_domain } # Set cookie domain dynamically
# domain: proc { |req| ".sub.#{req.host}" } # Set cookie domain dynamically based on request
#
#
# * <tt>:tld_length</tt> - When using <tt>:domain => :all</tt>, this option can be used to explicitly
# set the TLD length when using a short (<= 3 character) domain that is being interpreted as part of a TLD.
Expand Down Expand Up @@ -472,6 +477,8 @@ def handle_options(options)
domain = domain.delete_prefix(".")
request.host == domain || request.host.end_with?(".#{domain}")
end
elsif options[:domain].respond_to?(:call)
options[:domain] = options[:domain].call(request)
end
end
end
Expand Down
22 changes: 22 additions & 0 deletions actionpack/test/dispatch/cookies_test.rb
Expand Up @@ -232,6 +232,16 @@ def set_cookie_with_domain_all_as_string
head :ok
end

def set_cookie_with_domain_proc
cookies[:user_name] = { value: "braindeaf", domain: proc { ".sub.www.nextangle.com" } }
head :ok
end

def set_cookie_with_domain_proc_with_request
cookies[:user_name] = { value: "braindeaf", domain: proc { |req| ".sub.#{req.host}" } }
head :ok
end

def delete_cookie_with_domain
cookies.delete(:user_name, domain: :all)
head :ok
Expand Down Expand Up @@ -1222,6 +1232,18 @@ def test_cookie_with_several_preset_domains_using_shared_domain
assert_cookie_header "user_name=rizwanreza; domain=.example3.com; path=/; SameSite=Lax"
end

def test_cookie_with_domain_proc
get :set_cookie_with_domain_proc
assert_response :success
assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax"
end

def test_cookie_with_domain_proc_with_request
get :set_cookie_with_domain_proc_with_request
assert_response :success
assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax"
end

def test_deleting_cookie_with_several_preset_domains_using_one_of_these_domains
@request.host = "example2.com"
request.cookies[:user_name] = "Joe"
Expand Down

0 comments on commit 83da2e9

Please sign in to comment.