joebadmo-rack-test 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +4 -0
- data/.gitignore +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +31 -0
- data/History.txt +163 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +60 -0
- data/Rakefile +33 -0
- data/Thorfile +114 -0
- data/lib/rack/mock_session.rb +66 -0
- data/lib/rack/test.rb +302 -0
- data/lib/rack/test/cookie_jar.rb +176 -0
- data/lib/rack/test/methods.rb +82 -0
- data/lib/rack/test/mock_digest_request.rb +29 -0
- data/lib/rack/test/uploaded_file.rb +50 -0
- data/lib/rack/test/utils.rb +136 -0
- data/rack-test.gemspec +80 -0
- data/spec/fixtures/bar.txt +1 -0
- data/spec/fixtures/config.ru +3 -0
- data/spec/fixtures/fake_app.rb +143 -0
- data/spec/fixtures/foo.txt +1 -0
- data/spec/rack/test/cookie_spec.rb +211 -0
- data/spec/rack/test/digest_auth_spec.rb +46 -0
- data/spec/rack/test/multipart_spec.rb +145 -0
- data/spec/rack/test/uploaded_file_spec.rb +22 -0
- data/spec/rack/test/utils_spec.rb +122 -0
- data/spec/rack/test_spec.rb +489 -0
- data/spec/spec_helper.rb +66 -0
- data/spec/support/matchers/body.rb +9 -0
- data/spec/support/matchers/challenge.rb +11 -0
- metadata +110 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module Rack
|
2
|
+
|
3
|
+
class MockSession # :nodoc:
|
4
|
+
attr_writer :cookie_jar
|
5
|
+
attr_reader :default_host
|
6
|
+
|
7
|
+
def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
|
8
|
+
@app = app
|
9
|
+
@after_request = []
|
10
|
+
@default_host = default_host
|
11
|
+
@last_request = nil
|
12
|
+
@last_response = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_request(&block)
|
16
|
+
@after_request << block
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear_cookies
|
20
|
+
@cookie_jar = Rack::Test::CookieJar.new([], @default_host)
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_cookie(cookie, uri = nil)
|
24
|
+
cookie_jar.merge(cookie, uri)
|
25
|
+
end
|
26
|
+
|
27
|
+
def request(uri, env)
|
28
|
+
env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
|
29
|
+
@last_request = Rack::Request.new(env)
|
30
|
+
status, headers, body = @app.call(@last_request.env)
|
31
|
+
|
32
|
+
@last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
|
33
|
+
body.close if body.respond_to?(:close)
|
34
|
+
|
35
|
+
cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
|
36
|
+
|
37
|
+
@after_request.each { |hook| hook.call }
|
38
|
+
|
39
|
+
if @last_response.respond_to?(:finish)
|
40
|
+
@last_response.finish
|
41
|
+
else
|
42
|
+
@last_response
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return the last request issued in the session. Raises an error if no
|
47
|
+
# requests have been sent yet.
|
48
|
+
def last_request
|
49
|
+
raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
|
50
|
+
@last_request
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the last response received in the session. Raises an error if
|
54
|
+
# no requests have been sent yet.
|
55
|
+
def last_response
|
56
|
+
raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
|
57
|
+
@last_response
|
58
|
+
end
|
59
|
+
|
60
|
+
def cookie_jar
|
61
|
+
@cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/rack/test.rb
ADDED
@@ -0,0 +1,302 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "rack"
|
3
|
+
require "rack/mock_session"
|
4
|
+
require "rack/test/cookie_jar"
|
5
|
+
require "rack/test/mock_digest_request"
|
6
|
+
require "rack/test/utils"
|
7
|
+
require "rack/test/methods"
|
8
|
+
require "rack/test/uploaded_file"
|
9
|
+
|
10
|
+
module Rack
|
11
|
+
module Test
|
12
|
+
VERSION = "0.6.1"
|
13
|
+
|
14
|
+
DEFAULT_HOST = "example.org"
|
15
|
+
MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
|
16
|
+
|
17
|
+
# The common base class for exceptions raised by Rack::Test
|
18
|
+
class Error < StandardError; end
|
19
|
+
|
20
|
+
# This class represents a series of requests issued to a Rack app, sharing
|
21
|
+
# a single cookie jar
|
22
|
+
#
|
23
|
+
# Rack::Test::Session's methods are most often called through Rack::Test::Methods,
|
24
|
+
# which will automatically build a session when it's first used.
|
25
|
+
class Session
|
26
|
+
extend Forwardable
|
27
|
+
include Rack::Test::Utils
|
28
|
+
|
29
|
+
def_delegators :@rack_mock_session, :clear_cookies, :set_cookie, :last_response, :last_request
|
30
|
+
|
31
|
+
# Creates a Rack::Test::Session for a given Rack app or Rack::MockSession.
|
32
|
+
#
|
33
|
+
# Note: Generally, you won't need to initialize a Rack::Test::Session directly.
|
34
|
+
# Instead, you should include Rack::Test::Methods into your testing context.
|
35
|
+
# (See README.rdoc for an example)
|
36
|
+
def initialize(mock_session)
|
37
|
+
@headers = {}
|
38
|
+
|
39
|
+
if mock_session.is_a?(MockSession)
|
40
|
+
@rack_mock_session = mock_session
|
41
|
+
else
|
42
|
+
@rack_mock_session = MockSession.new(mock_session)
|
43
|
+
end
|
44
|
+
|
45
|
+
@default_host = @rack_mock_session.default_host
|
46
|
+
end
|
47
|
+
|
48
|
+
# Issue a GET request for the given URI with the given params and Rack
|
49
|
+
# environment. Stores the issues request object in #last_request and
|
50
|
+
# the app's response in #last_response. Yield #last_response to a block
|
51
|
+
# if given.
|
52
|
+
#
|
53
|
+
# Example:
|
54
|
+
# get "/"
|
55
|
+
def get(uri, params = {}, env = {}, &block)
|
56
|
+
env = env_for(uri, env.merge(:method => "GET", :params => params))
|
57
|
+
process_request(uri, env, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Issue a POST request for the given URI. See #get
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
# post "/signup", "name" => "Bryan"
|
64
|
+
def post(uri, params = {}, env = {}, &block)
|
65
|
+
env = env_for(uri, env.merge(:method => "POST", :params => params))
|
66
|
+
process_request(uri, env, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Issue a PUT request for the given URI. See #get
|
70
|
+
#
|
71
|
+
# Example:
|
72
|
+
# put "/"
|
73
|
+
def put(uri, params = {}, env = {}, &block)
|
74
|
+
env = env_for(uri, env.merge(:method => "PUT", :params => params))
|
75
|
+
process_request(uri, env, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Issue a PATCH request for the given URI. See #get
|
79
|
+
#
|
80
|
+
# Example:
|
81
|
+
# patch "/"
|
82
|
+
def patch(uri, params = {}, env = {}, &block)
|
83
|
+
env = env_for(uri, env.merge(:method => "PATCH", :params => params))
|
84
|
+
process_request(uri, env, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Issue a DELETE request for the given URI. See #get
|
88
|
+
#
|
89
|
+
# Example:
|
90
|
+
# delete "/"
|
91
|
+
def delete(uri, params = {}, env = {}, &block)
|
92
|
+
env = env_for(uri, env.merge(:method => "DELETE", :params => params))
|
93
|
+
process_request(uri, env, &block)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Issue an OPTIONS request for the given URI. See #get
|
97
|
+
#
|
98
|
+
# Example:
|
99
|
+
# options "/"
|
100
|
+
def options(uri, params = {}, env = {}, &block)
|
101
|
+
env = env_for(uri, env.merge(:method => "OPTIONS", :params => params))
|
102
|
+
process_request(uri, env, &block)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Issue a HEAD request for the given URI. See #get
|
106
|
+
#
|
107
|
+
# Example:
|
108
|
+
# head "/"
|
109
|
+
def head(uri, params = {}, env = {}, &block)
|
110
|
+
env = env_for(uri, env.merge(:method => "HEAD", :params => params))
|
111
|
+
process_request(uri, env, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Issue a request to the Rack app for the given URI and optional Rack
|
115
|
+
# environment. Stores the issues request object in #last_request and
|
116
|
+
# the app's response in #last_response. Yield #last_response to a block
|
117
|
+
# if given.
|
118
|
+
#
|
119
|
+
# Example:
|
120
|
+
# request "/"
|
121
|
+
def request(uri, env = {}, &block)
|
122
|
+
env = env_for(uri, env)
|
123
|
+
process_request(uri, env, &block)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Set a header to be included on all subsequent requests through the
|
127
|
+
# session. Use a value of nil to remove a previously configured header.
|
128
|
+
#
|
129
|
+
# In accordance with the Rack spec, headers will be included in the Rack
|
130
|
+
# environment hash in HTTP_USER_AGENT form.
|
131
|
+
#
|
132
|
+
# Example:
|
133
|
+
# header "User-Agent", "Firefox"
|
134
|
+
def header(name, value)
|
135
|
+
if value.nil?
|
136
|
+
@headers.delete(name)
|
137
|
+
else
|
138
|
+
@headers[name] = value
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Set the username and password for HTTP Basic authorization, to be
|
143
|
+
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
144
|
+
#
|
145
|
+
# Example:
|
146
|
+
# basic_authorize "bryan", "secret"
|
147
|
+
def basic_authorize(username, password)
|
148
|
+
encoded_login = ["#{username}:#{password}"].pack("m*")
|
149
|
+
header('Authorization', "Basic #{encoded_login}")
|
150
|
+
end
|
151
|
+
|
152
|
+
alias_method :authorize, :basic_authorize
|
153
|
+
|
154
|
+
# Set the username and password for HTTP Digest authorization, to be
|
155
|
+
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
156
|
+
#
|
157
|
+
# Example:
|
158
|
+
# digest_authorize "bryan", "secret"
|
159
|
+
def digest_authorize(username, password)
|
160
|
+
@digest_username = username
|
161
|
+
@digest_password = password
|
162
|
+
end
|
163
|
+
|
164
|
+
# Rack::Test will not follow any redirects automatically. This method
|
165
|
+
# will follow the redirect returned (including setting the Referer header
|
166
|
+
# on the new request) in the last response. If the last response was not
|
167
|
+
# a redirect, an error will be raised.
|
168
|
+
def follow_redirect!
|
169
|
+
unless last_response.redirect?
|
170
|
+
raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
|
171
|
+
end
|
172
|
+
|
173
|
+
get(last_response["Location"], {}, { "HTTP_REFERER" => last_request.url })
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def env_for(path, env)
|
179
|
+
uri = URI.parse(path)
|
180
|
+
uri.path = "/#{uri.path}" unless uri.path[0] == ?/
|
181
|
+
uri.host ||= @default_host
|
182
|
+
|
183
|
+
env = default_env.merge(env)
|
184
|
+
|
185
|
+
env["HTTP_HOST"] ||= [uri.host, uri.port].compact.join(":")
|
186
|
+
|
187
|
+
env.update("HTTPS" => "on") if URI::HTTPS === uri
|
188
|
+
env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" if env[:xhr]
|
189
|
+
|
190
|
+
# TODO: Remove this after Rack 1.1 has been released.
|
191
|
+
# Stringifying and upcasing methods has be commit upstream
|
192
|
+
env["REQUEST_METHOD"] ||= env[:method] ? env[:method].to_s.upcase : "GET"
|
193
|
+
|
194
|
+
if env["REQUEST_METHOD"] == "GET"
|
195
|
+
params = env[:params] || {}
|
196
|
+
params = parse_nested_query(params) if params.is_a?(String)
|
197
|
+
params.update(parse_nested_query(uri.query))
|
198
|
+
uri.query = build_nested_query(params)
|
199
|
+
elsif !env.has_key?(:input)
|
200
|
+
env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded"
|
201
|
+
|
202
|
+
if env[:params].is_a?(Hash)
|
203
|
+
if data = build_multipart(env[:params])
|
204
|
+
env[:input] = data
|
205
|
+
env["CONTENT_LENGTH"] ||= data.length.to_s
|
206
|
+
env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
|
207
|
+
else
|
208
|
+
env[:input] = params_to_string(env[:params])
|
209
|
+
end
|
210
|
+
else
|
211
|
+
env[:input] = env[:params]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
env.delete(:params)
|
216
|
+
|
217
|
+
if env.has_key?(:cookie)
|
218
|
+
set_cookie(env.delete(:cookie), uri)
|
219
|
+
end
|
220
|
+
|
221
|
+
Rack::MockRequest.env_for(uri.to_s, env)
|
222
|
+
end
|
223
|
+
|
224
|
+
def process_request(uri, env)
|
225
|
+
uri = URI.parse(uri)
|
226
|
+
uri.host ||= @default_host
|
227
|
+
|
228
|
+
@rack_mock_session.request(uri, env)
|
229
|
+
|
230
|
+
if retry_with_digest_auth?(env)
|
231
|
+
auth_env = env.merge({
|
232
|
+
"HTTP_AUTHORIZATION" => digest_auth_header,
|
233
|
+
"rack-test.digest_auth_retry" => true
|
234
|
+
})
|
235
|
+
auth_env.delete('rack.request')
|
236
|
+
process_request(uri.path, auth_env)
|
237
|
+
else
|
238
|
+
yield last_response if block_given?
|
239
|
+
|
240
|
+
last_response
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def digest_auth_header
|
245
|
+
challenge = last_response["WWW-Authenticate"].split(" ", 2).last
|
246
|
+
params = Rack::Auth::Digest::Params.parse(challenge)
|
247
|
+
|
248
|
+
params.merge!({
|
249
|
+
"username" => @digest_username,
|
250
|
+
"nc" => "00000001",
|
251
|
+
"cnonce" => "nonsensenonce",
|
252
|
+
"uri" => last_request.fullpath,
|
253
|
+
"method" => last_request.env["REQUEST_METHOD"],
|
254
|
+
})
|
255
|
+
|
256
|
+
params["response"] = MockDigestRequest.new(params).response(@digest_password)
|
257
|
+
|
258
|
+
"Digest #{params}"
|
259
|
+
end
|
260
|
+
|
261
|
+
def retry_with_digest_auth?(env)
|
262
|
+
last_response.status == 401 &&
|
263
|
+
digest_auth_configured? &&
|
264
|
+
!env["rack-test.digest_auth_retry"]
|
265
|
+
end
|
266
|
+
|
267
|
+
def digest_auth_configured?
|
268
|
+
@digest_username
|
269
|
+
end
|
270
|
+
|
271
|
+
def default_env
|
272
|
+
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(headers_for_env)
|
273
|
+
end
|
274
|
+
|
275
|
+
def headers_for_env
|
276
|
+
converted_headers = {}
|
277
|
+
|
278
|
+
@headers.each do |name, value|
|
279
|
+
env_key = name.upcase.gsub("-", "_")
|
280
|
+
env_key = "HTTP_" + env_key unless "CONTENT_TYPE" == env_key
|
281
|
+
converted_headers[env_key] = value
|
282
|
+
end
|
283
|
+
|
284
|
+
converted_headers
|
285
|
+
end
|
286
|
+
|
287
|
+
def params_to_string(params)
|
288
|
+
case params
|
289
|
+
when Hash then build_nested_query(params)
|
290
|
+
when nil then ""
|
291
|
+
else params
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
def self.encoding_aware_strings?
|
298
|
+
defined?(Encoding) && "".respond_to?(:encode)
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "time"
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module Test
|
6
|
+
|
7
|
+
class Cookie # :nodoc:
|
8
|
+
include Rack::Utils
|
9
|
+
|
10
|
+
# :api: private
|
11
|
+
attr_reader :name, :value
|
12
|
+
|
13
|
+
# :api: private
|
14
|
+
def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
|
15
|
+
@default_host = default_host
|
16
|
+
uri ||= default_uri
|
17
|
+
|
18
|
+
# separate the name / value pair from the cookie options
|
19
|
+
@name_value_raw, options = raw.split(/[;,] */n, 2)
|
20
|
+
|
21
|
+
@name, @value = parse_query(@name_value_raw, ';').to_a.first
|
22
|
+
@options = parse_query(options, ';')
|
23
|
+
|
24
|
+
@options["domain"] ||= (uri.host || default_host)
|
25
|
+
@options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
|
26
|
+
end
|
27
|
+
|
28
|
+
def replaces?(other)
|
29
|
+
[name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
|
30
|
+
end
|
31
|
+
|
32
|
+
# :api: private
|
33
|
+
def raw
|
34
|
+
@name_value_raw
|
35
|
+
end
|
36
|
+
|
37
|
+
# :api: private
|
38
|
+
def empty?
|
39
|
+
@value.nil? || @value.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
# :api: private
|
43
|
+
def domain
|
44
|
+
@options["domain"]
|
45
|
+
end
|
46
|
+
|
47
|
+
def secure?
|
48
|
+
@options.has_key?("secure")
|
49
|
+
end
|
50
|
+
|
51
|
+
# :api: private
|
52
|
+
def path
|
53
|
+
@options["path"].strip || "/"
|
54
|
+
end
|
55
|
+
|
56
|
+
# :api: private
|
57
|
+
def expires
|
58
|
+
Time.parse(@options["expires"]) if @options["expires"]
|
59
|
+
end
|
60
|
+
|
61
|
+
# :api: private
|
62
|
+
def expired?
|
63
|
+
expires && expires < Time.now
|
64
|
+
end
|
65
|
+
|
66
|
+
# :api: private
|
67
|
+
def valid?(uri)
|
68
|
+
uri ||= default_uri
|
69
|
+
|
70
|
+
if uri.host.nil?
|
71
|
+
uri.host = @default_host
|
72
|
+
end
|
73
|
+
|
74
|
+
real_domain = domain =~ /^\./ ? domain[1..-1] : domain
|
75
|
+
(!secure? || (secure? && uri.scheme == "https")) &&
|
76
|
+
uri.host =~ Regexp.new("#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE) &&
|
77
|
+
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
78
|
+
end
|
79
|
+
|
80
|
+
# :api: private
|
81
|
+
def matches?(uri)
|
82
|
+
! expired? && valid?(uri)
|
83
|
+
end
|
84
|
+
|
85
|
+
# :api: private
|
86
|
+
def <=>(other)
|
87
|
+
# Orders the cookies from least specific to most
|
88
|
+
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def default_uri
|
94
|
+
URI.parse("//" + @default_host + "/")
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class CookieJar # :nodoc:
|
100
|
+
|
101
|
+
# :api: private
|
102
|
+
def initialize(cookies = [], default_host = DEFAULT_HOST)
|
103
|
+
@default_host = default_host
|
104
|
+
@cookies = cookies
|
105
|
+
@cookies.sort!
|
106
|
+
end
|
107
|
+
|
108
|
+
def [](name)
|
109
|
+
cookies = hash_for(nil)
|
110
|
+
# TODO: Should be case insensitive
|
111
|
+
cookies[name] && cookies[name].value
|
112
|
+
end
|
113
|
+
|
114
|
+
def []=(name, value)
|
115
|
+
merge("#{name}=#{Rack::Utils.escape(value)}")
|
116
|
+
end
|
117
|
+
|
118
|
+
def merge(raw_cookies, uri = nil)
|
119
|
+
return unless raw_cookies
|
120
|
+
|
121
|
+
if raw_cookies.is_a? String
|
122
|
+
raw_cookies = raw_cookies.split("\n")
|
123
|
+
raw_cookies.reject!{|c| c.empty? }
|
124
|
+
end
|
125
|
+
|
126
|
+
raw_cookies.each do |raw_cookie|
|
127
|
+
cookie = Cookie.new(raw_cookie, uri, @default_host)
|
128
|
+
self << cookie if cookie.valid?(uri)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def <<(new_cookie)
|
133
|
+
@cookies.reject! do |existing_cookie|
|
134
|
+
new_cookie.replaces?(existing_cookie)
|
135
|
+
end
|
136
|
+
|
137
|
+
@cookies << new_cookie
|
138
|
+
@cookies.sort!
|
139
|
+
end
|
140
|
+
|
141
|
+
# :api: private
|
142
|
+
def for(uri)
|
143
|
+
hash_for(uri).values.map { |c| c.raw }.join(';')
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_hash
|
147
|
+
cookies = {}
|
148
|
+
|
149
|
+
hash_for(nil).each do |name, cookie|
|
150
|
+
cookies[name] = cookie.value
|
151
|
+
end
|
152
|
+
|
153
|
+
return cookies
|
154
|
+
end
|
155
|
+
|
156
|
+
protected
|
157
|
+
|
158
|
+
def hash_for(uri = nil)
|
159
|
+
cookies = {}
|
160
|
+
|
161
|
+
# The cookies are sorted by most specific first. So, we loop through
|
162
|
+
# all the cookies in order and add it to a hash by cookie name if
|
163
|
+
# the cookie can be sent to the current URI. It's added to the hash
|
164
|
+
# so that when we are done, the cookies will be unique by name and
|
165
|
+
# we'll have grabbed the most specific to the URI.
|
166
|
+
@cookies.each do |cookie|
|
167
|
+
cookies[cookie.name] = cookie if !uri || cookie.matches?(uri)
|
168
|
+
end
|
169
|
+
|
170
|
+
return cookies
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|