Skip to content

Commit 9589ef3

Browse files
authored
Merge pull request rails#46726 from braindeaf/dynamic_cookie_domain_per_request
Dynamic cookie domain per request
2 parents 95fb5b4 + 83da2e9 commit 9589ef3

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

actionpack/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Allow cookie options[:domain] to accept a proc to set the cookie domain on a more flexible per-request basis
2+
3+
*RobL*
4+
15
* When a host is not specified for an `ActionController::Renderer`'s env,
26
the host and related options will now be derived from the routes'
37
`default_url_options` and `ActionDispatch::Http::URL.secure_protocol`.

actionpack/lib/action_dispatch/middleware/cookies.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,18 @@ def use_cookies_with_metadata
160160
# to <tt>:all</tt>. To support multiple domains, provide an array, and
161161
# the first domain matching <tt>request.host</tt> will be used. Make
162162
# sure to specify the <tt>:domain</tt> option with <tt>:all</tt> or
163-
# <tt>Array</tt> again when deleting cookies.
163+
# <tt>Array</tt> again when deleting cookies. For more flexibility you
164+
# can set the domain on a per-request basis by specifying <tt>:domain</tt>
165+
# with a proc.
164166
#
165167
# domain: nil # Does not set cookie domain. (default)
166168
# domain: :all # Allow the cookie for the top most level
167169
# # domain and subdomains.
168170
# domain: %w(.example.com .example.org) # Allow the cookie
169171
# # for concrete domain names.
172+
# domain: proc { Tenant.current.cookie_domain } # Set cookie domain dynamically
173+
# domain: proc { |req| ".sub.#{req.host}" } # Set cookie domain dynamically based on request
174+
#
170175
#
171176
# * <tt>:tld_length</tt> - When using <tt>:domain => :all</tt>, this option can be used to explicitly
172177
# set the TLD length when using a short (<= 3 character) domain that is being interpreted as part of a TLD.
@@ -472,6 +477,8 @@ def handle_options(options)
472477
domain = domain.delete_prefix(".")
473478
request.host == domain || request.host.end_with?(".#{domain}")
474479
end
480+
elsif options[:domain].respond_to?(:call)
481+
options[:domain] = options[:domain].call(request)
475482
end
476483
end
477484
end

actionpack/test/dispatch/cookies_test.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,16 @@ def set_cookie_with_domain_all_as_string
232232
head :ok
233233
end
234234

235+
def set_cookie_with_domain_proc
236+
cookies[:user_name] = { value: "braindeaf", domain: proc { ".sub.www.nextangle.com" } }
237+
head :ok
238+
end
239+
240+
def set_cookie_with_domain_proc_with_request
241+
cookies[:user_name] = { value: "braindeaf", domain: proc { |req| ".sub.#{req.host}" } }
242+
head :ok
243+
end
244+
235245
def delete_cookie_with_domain
236246
cookies.delete(:user_name, domain: :all)
237247
head :ok
@@ -1222,6 +1232,18 @@ def test_cookie_with_several_preset_domains_using_shared_domain
12221232
assert_cookie_header "user_name=rizwanreza; domain=.example3.com; path=/; SameSite=Lax"
12231233
end
12241234

1235+
def test_cookie_with_domain_proc
1236+
get :set_cookie_with_domain_proc
1237+
assert_response :success
1238+
assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax"
1239+
end
1240+
1241+
def test_cookie_with_domain_proc_with_request
1242+
get :set_cookie_with_domain_proc_with_request
1243+
assert_response :success
1244+
assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax"
1245+
end
1246+
12251247
def test_deleting_cookie_with_several_preset_domains_using_one_of_these_domains
12261248
@request.host = "example2.com"
12271249
request.cookies[:user_name] = "Joe"

0 commit comments

Comments
 (0)