1
- require 'stringio'
2
-
3
1
module Browser
4
2
5
3
# Allows manipulation of browser cookies.
@@ -8,10 +6,19 @@ module Browser
8
6
#
9
7
# Usage:
10
8
#
11
- # cookies = Browser::Cookies.new(` document`)
9
+ # cookies = $ document.cookies
12
10
# cookies["my-cookie"] = "monster"
13
11
# cookies.delete("my-cookie")
14
12
#
13
+ # By default, cookies are stored JSON-encoded. You can supply a `raw:` option
14
+ # whenever you need to access/write the cookies in a raw way, eg.
15
+ #
16
+ # cookies["my-other-cookie", raw: true] = 123
17
+ #
18
+ # You can also set this option while referencing $document.cookies, eg.
19
+ #
20
+ # cookies = $document.cookies(raw: true)
21
+ # cookies["my-other-cookie"] = 123
15
22
class Cookies
16
23
# Default cookie options.
17
24
DEFAULT = {
@@ -26,24 +33,34 @@ class Cookies
26
33
# Create a new {Cookies} wrapper.
27
34
#
28
35
# @param document [native] the native document object
29
- def initialize ( document )
36
+ # @param options [Hash] the default cookie options
37
+ def initialize ( document , options = { } )
30
38
@document = document
31
- @options = DEFAULT . dup
39
+ @options = DEFAULT . merge ( options )
32
40
end
33
41
34
42
# Access the cookie with the given name.
35
43
#
36
44
# @param name [String] the name of the cookie
45
+ # @param options [Hash] the options for the cookie
46
+ #
47
+ # @option options [Boolean] :raw get a raw cookie value, don't encode it with JSON
37
48
#
38
49
# @return [Object]
39
- def []( name )
50
+ def []( name , options = { } )
51
+ options = @options . merge ( options )
52
+
40
53
matches = `#@document .cookie` . scan ( /#{ Regexp . escape ( FormData . encode ( name ) ) } =([^;]*)/ )
41
54
42
55
return if matches . empty?
43
56
44
- result = matches . flatten . map { |value |
45
- JSON . parse ( FormData . decode ( value ) )
46
- }
57
+ result = matches . flatten . map do |value |
58
+ if options [ :raw ]
59
+ FormData . decode ( value )
60
+ else
61
+ JSON . parse ( FormData . decode ( value ) )
62
+ end
63
+ end
47
64
48
65
result . length == 1 ? result . first : result
49
66
end
@@ -54,70 +71,82 @@ def [](name)
54
71
# @param value [Object] the data to set
55
72
# @param options [Hash] the options for the cookie
56
73
#
74
+ # @option options [Boolean] :raw don't encode a value with JSON
57
75
# @option options [Integer] :max_age the max age of the cookie in seconds
58
76
# @option options [Time] :expires the expire date
59
77
# @option options [String] :path the path the cookie is valid on
60
78
# @option options [String] :domain the domain the cookie is valid on
61
79
# @option options [Boolean] :secure whether the cookie is secure or not
62
- def []=( name , value , options = { } )
63
- string = value . is_a? ( String ) ? value : JSON . dump ( value )
64
- encoded_value = encode ( name , string , @options . merge ( options ) )
80
+ def []=( name , options = { } , value )
81
+ options = @options . merge ( options )
82
+ if options [ :raw ]
83
+ string = value . to_s
84
+ else
85
+ string = JSON . dump ( value )
86
+ end
87
+ encoded_value = encode ( name , string , options )
65
88
`#@document .cookie = #{ encoded_value } `
66
89
end
67
90
68
91
# Delete a cookie.
69
92
#
70
93
# @param name [String] the name of the cookie
71
- def delete ( name )
94
+ def delete ( name , _options = { } )
72
95
`#@document .cookie = #{ encode name , '' , expires : Time . now } `
73
96
end
74
97
75
98
# @!attribute [r] keys
76
99
# @return [Array<String>] all the cookie names
77
- def keys
78
- Array ( `#@document .cookie.split(/; /)` ) . map { |cookie |
100
+ def keys ( _options = { } )
101
+ Array ( `#@document .cookie.split(/; /)` ) . map do |cookie |
79
102
cookie . split ( /\s *=\s */ ) . first
80
- }
103
+ end
81
104
end
82
105
83
106
# @!attribute [r] values
84
107
# @return [Array] all the cookie values
85
- def values
86
- keys . map { |key |
87
- self [ key ]
88
- }
108
+ def values ( options = { } )
109
+ options = @options . merge ( options )
110
+ keys . map do |key |
111
+ self [ key , options ]
112
+ end
89
113
end
90
114
91
115
# Enumerate the cookies.
92
116
#
93
117
# @yieldparam key [String] the name of the cookie
94
118
# @yieldparam value [String] the value of the cookie
95
119
#
120
+ # @param options [Hash] the options for the cookie
121
+ #
122
+ # @option options [Boolean] :raw don't encode a value with JSON
123
+ #
96
124
# @return [self]
97
- def each ( &block )
98
- return enum_for :each unless block
125
+ def each ( options = { } , &block )
126
+ return enum_for :each , options unless block
127
+ options = @options . merge ( options )
99
128
100
- keys . each { |key |
101
- yield key , self [ key ]
102
- }
129
+ keys . each do |key |
130
+ yield key , self [ key , options ]
131
+ end
103
132
104
133
self
105
134
end
106
135
107
136
# Delete all the cookies
108
137
#
109
138
# @return [self]
110
- def clear
111
- keys . each { |key |
139
+ def clear ( _options = { } )
140
+ keys . each do |key |
112
141
delete key
113
- }
142
+ end
114
143
115
144
self
116
145
end
117
146
118
147
protected
119
148
def encode ( key , value , options = { } )
120
- io = StringIO . new
149
+ io = [ ]
121
150
122
151
io << FormData . encode ( key ) << ?= << FormData . encode ( value ) << '; '
123
152
@@ -127,15 +156,15 @@ def encode(key, value, options = {})
127
156
io << 'domain=' << options [ :domain ] << '; ' if options [ :domain ]
128
157
io << 'secure' if options [ :secure ]
129
158
130
- io . string
159
+ io . join
131
160
end
132
161
end
133
162
134
163
class DOM ::Document < DOM ::Element
135
164
# @!attribute [r] cookies
136
165
# @return [Cookies] the cookies for the document
137
- def cookies
138
- Cookies . new ( @native ) if defined? ( `#@native .cookie` )
166
+ def cookies ( options = { } )
167
+ Cookies . new ( @native , options ) if defined? ( `#@native .cookie` )
139
168
end
140
169
end
141
170
0 commit comments