module HTTPX::Plugins::Cookies::SetCookieParser

  1. lib/httpx/plugins/cookies/set_cookie_parser.rb

Methods

Public Instance

  1. call
  2. scan_dquoted
  3. scan_name_value
  4. scan_value

Constants

RE_BAD_CHAR = /([\x00-\x20\x7F",;\\])/.freeze  
RE_COOKIE_COMMA = /,(?=#{RE_WSP}?#{RE_NAME}=)/.freeze  

A pattern that matches the comma in a (typically date) value.

RE_NAME = /(?!#{RE_WSP})[^,;\\"=]*/.freeze  

A pattern that matches a cookie name or attribute name which may be empty, capturing trailing whitespace.

RE_WSP = /[ \t]+/.freeze  

Whitespace.

Public Instance methods

call(set_cookie)
[show source]
    # File lib/httpx/plugins/cookies/set_cookie_parser.rb
 75 def call(set_cookie)
 76   scanner = StringScanner.new(set_cookie)
 77 
 78   # RFC 6265 4.1.1 & 5.2
 79   until scanner.eos?
 80     start = scanner.pos
 81     len = nil
 82 
 83     scanner.skip(RE_WSP)
 84 
 85     name, value = scan_name_value(scanner, true)
 86     value = nil if name.empty?
 87 
 88     attrs = {}
 89 
 90     until scanner.eos?
 91       if scanner.skip(/,/)
 92         # The comma is used as separator for concatenating multiple
 93         # values of a header.
 94         len = (scanner.pos - 1) - start
 95         break
 96       elsif scanner.skip(/;/)
 97         scanner.skip(RE_WSP)
 98 
 99         aname, avalue = scan_name_value(scanner, true)
100 
101         next if aname.empty? || value.nil?
102 
103         aname.downcase!
104 
105         case aname
106         when "expires"
107           # RFC 6265 5.2.1
108           (avalue &&= Time.parse(avalue)) || next
109         when "max-age"
110           # RFC 6265 5.2.2
111           next unless /\A-?\d+\z/.match?(avalue)
112 
113           avalue = Integer(avalue)
114         when "domain"
115           # RFC 6265 5.2.3
116           # An empty value SHOULD be ignored.
117           next if avalue.nil? || avalue.empty?
118         when "path"
119           # RFC 6265 5.2.4
120           # A relative path must be ignored rather than normalizing it
121           # to "/".
122           next unless avalue.start_with?("/")
123         when "secure", "httponly"
124           # RFC 6265 5.2.5, 5.2.6
125           avalue = true
126         end
127         attrs[aname] = avalue
128       end
129     end
130 
131     len ||= scanner.pos - start
132 
133     next if len > Cookie::MAX_LENGTH
134 
135     yield(name, value, attrs) if name && !name.empty? && value
136   end
137 end
scan_dquoted(scanner)
[show source]
   # File lib/httpx/plugins/cookies/set_cookie_parser.rb
23 def scan_dquoted(scanner)
24   s = +""
25 
26   until scanner.eos?
27     break if scanner.skip(/"/)
28 
29     if scanner.skip(/\\/)
30       s << scanner.getch
31     elsif scanner.scan(/[^"\\]+/)
32       s << scanner.matched
33     end
34   end
35 
36   s
37 end
scan_name_value(scanner, comma_as_separator = false)
[show source]
   # File lib/httpx/plugins/cookies/set_cookie_parser.rb
62 def scan_name_value(scanner, comma_as_separator = false)
63   name = scanner.scan(RE_NAME)
64   name.rstrip! if name
65 
66   if scanner.skip(/=/)
67     value = scan_value(scanner, comma_as_separator)
68   else
69     scan_value(scanner, comma_as_separator)
70     value = nil
71   end
72   [name, value]
73 end
scan_value(scanner, comma_as_separator = false)
[show source]
   # File lib/httpx/plugins/cookies/set_cookie_parser.rb
39 def scan_value(scanner, comma_as_separator = false)
40   value = +""
41 
42   until scanner.eos?
43     if scanner.scan(/[^,;"]+/)
44       value << scanner.matched
45     elsif scanner.skip(/"/)
46       # RFC 6265 2.2
47       # A cookie-value may be DQUOTE'd.
48       value << scan_dquoted(scanner)
49     elsif scanner.check(/;/)
50       break
51     elsif comma_as_separator && scanner.check(RE_COOKIE_COMMA)
52       break
53     else
54       value << scanner.getch
55     end
56   end
57 
58   value.rstrip!
59   value
60 end