summary refs log tree commit
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-04-12 02:04:32 +1200
committerGitHub <noreply@github.com>2022-04-11 07:04:32 -0700
commit0493142d9a472249383c72d6d7e1195b3ca38df0 (patch)
tree97ca6d67868be30bfbc34499662075547d06a1d9
parentc0bf85f5ed49eb952619ed2705c3b49e5310d237 (diff)
downloadrack-0493142d9a472249383c72d6d7e1195b3ca38df0.tar.gz
Add documentation to key `Rack::Utils` cookie methods. (#1850)
-rw-r--r--lib/rack/utils.rb102
1 files changed, 90 insertions, 12 deletions
diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb
index ee1f93a5..7f402d93 100644
--- a/lib/rack/utils.rb
+++ b/lib/rack/utils.rb
@@ -219,17 +219,20 @@ module Rack
       (encoding_candidates & available_encodings)[0]
     end
 
-    def parse_cookies(env)
-      parse_cookies_header env[HTTP_COOKIE]
-    end
+    # :call-seq:
+    #   parse_cookies_header(value) -> hash
+    #
+    # Parse cookies from the provided header +value+ according to RFC6265. The
+    # syntax for cookie headers only supports semicolons. Returns a map of
+    # cookie +key+ to cookie +value+.
+    #
+    #   parse_cookies_header('myname=myvalue; max-age=0')
+    #   # => {"myname"=>"myvalue", "max-age"=>"0"}
+    #
+    def parse_cookies_header(value)
+      return {} unless value
 
-    def parse_cookies_header(header)
-      # According to RFC 6265:
-      # The syntax for cookie headers only supports semicolons
-      # User Agent -> Server ==
-      # Cookie: SID=31d4d96e407aad42; lang=en-US
-      return {} unless header
-      header.split(/[;] */n).each_with_object({}) do |cookie, cookies|
+      value.split(/[;] */n).each_with_object({}) do |cookie, cookies|
         next if cookie.empty?
         key, value = cookie.split('=', 2)
         cookies[key] = (unescape(value) rescue value) unless cookies.key?(key)
@@ -251,6 +254,42 @@ module Rack
       end
     end
 
+    # :call-seq:
+    #   parse_cookies(env) -> hash
+    #
+    # Parse cookies from the provided request environment using
+    # parse_cookies_header. Returns a map of cookie +key+ to cookie +value+.
+    #
+    #   parse_cookies({'HTTP_COOKIE' => 'myname=myvalue'})
+    #   # => {'myname' => 'myvalue'}
+    #
+    def parse_cookies(env)
+      parse_cookies_header env[HTTP_COOKIE]
+    end
+
+    # :call-seq:
+    #   set_cookie_header(key, value) -> encoded string
+    #
+    # Generate an encoded string using the provided +key+ and +value+ suitable
+    # for the +set-cookie+ header according to RFC6265. The +value+ may be an
+    # instance of either +String+ or +Hash+.
+    #
+    # If the cookie +value+ is an instance of +Hash+, it considers the following
+    # cookie attribute keys: +domain+, +max_age+, +expires+ (must be instance
+    # of +Time+), +secure+, +http_only+, +same_site+ and +value+. For more
+    # details about the interpretation of these fields, consult
+    # [RFC6265 Section 5.2](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2).
+    #
+    # An extra cookie attribute +escape_key+ can be provided to control whether
+    # or not the cookie key is URL encoded. If explicitly set to +false+, the
+    # cookie key name will not be url encoded (escaped). The default is +true+.
+    #
+    #   set_cookie_header("myname", "myvalue")
+    #   # => "myname=myvalue"
+    #
+    #   set_cookie_header("myname", {value: "myvalue", max_age: 10})
+    #   # => "myname=myvalue; max-age=10"
+    #
     def set_cookie_header(key, value)
       case value
       when Hash
@@ -278,12 +317,21 @@ module Rack
       else
         key = escape(key)
       end
+
       value = [value] unless Array === value
 
       return "#{key}=#{value.map { |v| escape v }.join('&')}#{domain}" \
         "#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
     end
 
+    # :call-seq:
+    #   set_cookie_header!(headers, key, value) -> header value
+    #
+    # Append a cookie in the specified headers with the given cookie +key+ and
+    # +value+ using set_cookie_header.
+    #
+    # If the headers already contains a +set-cookie+ key, it will be converted
+    # to an +Array+ if not already, and appended to.
     def set_cookie_header!(headers, key, value)
       if header = headers[SET_COOKIE]
         if header.is_a?(Array)
@@ -296,8 +344,20 @@ module Rack
       end
     end
 
-    # Adds a cookie that will *remove* a cookie from the client.  Hence the
-    # strange method name.
+    # :call-seq:
+    #   delete_set_cookie_header(key, value = {}) -> encoded string
+    #
+    # Generate an encoded string based on the given +key+ and +value+ using
+    # set_cookie_header for the purpose of causing the specified cookie to be
+    # deleted. The +value+ may be an instance of +Hash+ and can include
+    # attributes as outlined by set_cookie_header. The encoded cookie will have
+    # a +max_age+ of 0 seconds, an +expires+ date in the past and an empty
+    # +value+. When used with the +set-cookie+ header, it will cause the client
+    # to *remove* any matching cookie.
+    #
+    #   delete_set_cookie_header("myname")
+    #   # => "myname=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"
+    #
     def delete_set_cookie_header(key, value = {})
       set_cookie_header(key, {
         value: '', path: nil, domain: nil,
@@ -324,6 +384,24 @@ module Rack
       delete_set_cookie_header!(header, key, value)
     end
 
+    # :call-seq:
+    #   delete_set_cookie_header!(header, key, value = {}) -> header value
+    #
+    # Set an expired cookie in the specified headers with the given cookie
+    # +key+ and +value+ using delete_set_cookie_header. This causes
+    # the client to immediately delete the specified cookie.
+    #
+    #   delete_set_cookie_header!(nil, "mycookie")
+    #   # => "mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"
+    #
+    # If the header is non-nil, it will be modified in place.
+    #
+    #   header = []
+    #   delete_set_cookie_header!(header, "mycookie")
+    #   # => ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"]
+    #   header
+    #   # => ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"]
+    #
     def delete_set_cookie_header!(header, key, value = {})
       if header
         header = Array(header)