middleman 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/middleman.gemspec +65 -6
- data/pkg/middleman-0.2.1.gem +0 -0
- data/rdoc/classes/Middleman.html +164 -0
- data/rdoc/created.rid +1 -0
- data/rdoc/files/README_rdoc.html +114 -0
- data/rdoc/files/lib/middleman_rb.html +111 -0
- data/rdoc/fr_class_index.html +27 -0
- data/rdoc/fr_file_index.html +28 -0
- data/rdoc/fr_method_index.html +27 -0
- data/rdoc/index.html +24 -0
- data/rdoc/rdoc-style.css +208 -0
- data/vendor/rack-test/History.txt +64 -0
- data/vendor/rack-test/MIT-LICENSE.txt +19 -0
- data/vendor/rack-test/README.rdoc +57 -0
- data/vendor/rack-test/Rakefile +62 -0
- data/vendor/rack-test/lib/rack/mock_session.rb +57 -0
- data/vendor/rack-test/lib/rack/test.rb +246 -0
- data/vendor/rack-test/lib/rack/test/cookie_jar.rb +169 -0
- data/vendor/rack-test/lib/rack/test/methods.rb +73 -0
- data/vendor/rack-test/lib/rack/test/mock_digest_request.rb +27 -0
- data/vendor/rack-test/lib/rack/test/uploaded_file.rb +36 -0
- data/vendor/rack-test/lib/rack/test/utils.rb +75 -0
- data/vendor/rack-test/spec/fixtures/config.ru +3 -0
- data/vendor/rack-test/spec/fixtures/fake_app.rb +109 -0
- data/vendor/rack-test/spec/fixtures/foo.txt +1 -0
- data/vendor/rack-test/spec/rack/test/cookie_spec.rb +176 -0
- data/vendor/rack-test/spec/rack/test/digest_auth_spec.rb +48 -0
- data/vendor/rack-test/spec/rack/test/multipart_spec.rb +85 -0
- data/vendor/rack-test/spec/rack/test/utils_spec.rb +44 -0
- data/vendor/rack-test/spec/rack/test_spec.rb +363 -0
- data/vendor/rack-test/spec/rcov.opts +1 -0
- data/vendor/rack-test/spec/spec.opts +1 -0
- data/vendor/rack-test/spec/spec_helper.rb +48 -0
- data/vendor/sinatra-markaby/CHANGES +7 -0
- data/vendor/sinatra-markaby/LICENSE +20 -0
- data/vendor/sinatra-markaby/README.rdoc +33 -0
- data/vendor/sinatra-markaby/Rakefile +45 -0
- data/vendor/sinatra-markaby/TODO +3 -0
- data/vendor/sinatra-markaby/VERSION.yml +4 -0
- data/vendor/sinatra-markaby/lib/sinatra/markaby.rb +31 -0
- data/vendor/sinatra-markaby/sinatra-markaby.gemspec +49 -0
- data/vendor/sinatra-markaby/test/sinatra_markaby_test.rb +72 -0
- data/vendor/sinatra-markaby/test/test_helper.rb +19 -0
- data/vendor/sinatra-markaby/test/views/hello.mab +1 -0
- data/vendor/sinatra-markaby/test/views/html.mab +4 -0
- data/vendor/sinatra-maruku/LICENSE +22 -0
- data/vendor/sinatra-maruku/README.markdown +85 -0
- data/vendor/sinatra-maruku/Rakefile +34 -0
- data/vendor/sinatra-maruku/VERSION.yml +4 -0
- data/vendor/sinatra-maruku/examples/app.rb +8 -0
- data/vendor/sinatra-maruku/examples/config.ru +4 -0
- data/vendor/sinatra-maruku/examples/mapp.rb +15 -0
- data/vendor/sinatra-maruku/examples/public/javascripts/application.js +0 -0
- data/vendor/sinatra-maruku/examples/public/stylesheets/application.css +23 -0
- data/vendor/sinatra-maruku/examples/public/stylesheets/print.css +0 -0
- data/vendor/sinatra-maruku/examples/views/index.maruku +32 -0
- data/vendor/sinatra-maruku/examples/views/layout.maruku +9 -0
- data/vendor/sinatra-maruku/lib/sinatra/maruku.rb +25 -0
- data/vendor/sinatra-maruku/sinatra-maruku.gemspec +70 -0
- data/vendor/sinatra-maruku/test/sinatra_maruku_test.rb +91 -0
- data/vendor/sinatra-maruku/test/test_helper.rb +21 -0
- data/vendor/sinatra-maruku/test/views/hello.maruku +1 -0
- data/vendor/sinatra-maruku/test/views/layout2.maruku +2 -0
- metadata +63 -4
- data/.document +0 -5
- data/.gitignore +0 -6
- data/.gitmodules +0 -9
@@ -0,0 +1,62 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require "rake/clean"
|
5
|
+
require "spec/rake/spectask"
|
6
|
+
require File.expand_path("./lib/rack/test")
|
7
|
+
|
8
|
+
Spec::Rake::SpecTask.new do |t|
|
9
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run all specs in spec directory with RCov"
|
13
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
14
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
15
|
+
t.rcov = true
|
16
|
+
t.rcov_opts = lambda do
|
17
|
+
IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Run the specs"
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
spec = Gem::Specification.new do |s|
|
25
|
+
s.name = "rack-test"
|
26
|
+
s.version = Rack::Test::VERSION
|
27
|
+
s.author = "Bryan Helmkamp"
|
28
|
+
s.email = "bryan" + "@" + "brynary.com"
|
29
|
+
s.homepage = "http://github.com/brynary/rack-test"
|
30
|
+
s.summary = "Simple testing API built on Rack"
|
31
|
+
s.description = s.summary
|
32
|
+
s.files = %w[History.txt Rakefile README.rdoc] + Dir["lib/**/*"]
|
33
|
+
|
34
|
+
# rdoc
|
35
|
+
s.has_rdoc = true
|
36
|
+
s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt)
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::GemPackageTask.new(spec) do |package|
|
40
|
+
package.gem_spec = spec
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Delete generated RDoc"
|
44
|
+
task :clobber_docs do
|
45
|
+
FileUtils.rm_rf("doc")
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Generate RDoc"
|
49
|
+
task :docs => :clobber_docs do
|
50
|
+
system "hanna --title 'Rack::Test #{Rack::Test::VERSION} API Documentation'"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Install the package as a gem.'
|
54
|
+
task :install => [:clean, :package] do
|
55
|
+
gem = Dir['pkg/*.gem'].first
|
56
|
+
sh "sudo gem install --no-rdoc --no-ri --local #{gem}"
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Removes trailing whitespace'
|
60
|
+
task :whitespace do
|
61
|
+
sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
|
62
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Rack
|
2
|
+
|
3
|
+
class MockSession
|
4
|
+
attr_writer :cookie_jar
|
5
|
+
attr_reader :last_response
|
6
|
+
attr_reader :default_host
|
7
|
+
|
8
|
+
def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
|
9
|
+
@app = app
|
10
|
+
@after_request = []
|
11
|
+
@default_host = default_host
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_request(&block)
|
15
|
+
@after_request << block
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear_cookies
|
19
|
+
@cookie_jar = Rack::Test::CookieJar.new([], @default_host)
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_cookie(cookie, uri = nil)
|
23
|
+
cookie_jar.merge(cookie, uri)
|
24
|
+
end
|
25
|
+
|
26
|
+
def request(uri, env)
|
27
|
+
env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
|
28
|
+
@last_request = Rack::Request.new(env)
|
29
|
+
status, headers, body = @app.call(@last_request.env)
|
30
|
+
@last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
|
31
|
+
cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
|
32
|
+
|
33
|
+
@after_request.each { |hook| hook.call }
|
34
|
+
@last_response
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return the last request issued in the session. Raises an error if no
|
38
|
+
# requests have been sent yet.
|
39
|
+
def last_request
|
40
|
+
raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
|
41
|
+
@last_request
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return the last response received in the session. Raises an error if
|
45
|
+
# no requests have been sent yet.
|
46
|
+
def last_response
|
47
|
+
raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
|
48
|
+
@last_response
|
49
|
+
end
|
50
|
+
|
51
|
+
def cookie_jar
|
52
|
+
@cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
|
3
|
+
end
|
4
|
+
|
5
|
+
require "uri"
|
6
|
+
require "rack"
|
7
|
+
require "rack/mock_session"
|
8
|
+
require "rack/test/cookie_jar"
|
9
|
+
require "rack/test/mock_digest_request"
|
10
|
+
require "rack/test/utils"
|
11
|
+
require "rack/test/methods"
|
12
|
+
require "rack/test/uploaded_file"
|
13
|
+
|
14
|
+
module Rack
|
15
|
+
module Test
|
16
|
+
|
17
|
+
VERSION = "0.4.0"
|
18
|
+
|
19
|
+
DEFAULT_HOST = "example.org"
|
20
|
+
MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
|
21
|
+
|
22
|
+
# The common base class for exceptions raised by Rack::Test
|
23
|
+
class Error < StandardError; end
|
24
|
+
|
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
|
+
# Initialize a new session for the given Rack app
|
32
|
+
def initialize(mock_session)
|
33
|
+
@headers = {}
|
34
|
+
|
35
|
+
if mock_session.is_a?(MockSession)
|
36
|
+
@rack_mock_session = mock_session
|
37
|
+
else
|
38
|
+
@rack_mock_session = MockSession.new(mock_session)
|
39
|
+
end
|
40
|
+
|
41
|
+
@default_host = @rack_mock_session.default_host
|
42
|
+
end
|
43
|
+
|
44
|
+
# Issue a GET request for the given URI with the given params and Rack
|
45
|
+
# environment. Stores the issues request object in #last_request and
|
46
|
+
# the app's response in #last_response. Yield #last_response to a block
|
47
|
+
# if given.
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
# get "/"
|
51
|
+
def get(uri, params = {}, env = {}, &block)
|
52
|
+
env = env_for(uri, env.merge(:method => "GET", :params => params))
|
53
|
+
process_request(uri, env, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Issue a POST request for the given URI. See #get
|
57
|
+
#
|
58
|
+
# Example:
|
59
|
+
# post "/signup", "name" => "Bryan"
|
60
|
+
def post(uri, params = {}, env = {}, &block)
|
61
|
+
env = env_for(uri, env.merge(:method => "POST", :params => params))
|
62
|
+
process_request(uri, env, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Issue a PUT request for the given URI. See #get
|
66
|
+
#
|
67
|
+
# Example:
|
68
|
+
# put "/"
|
69
|
+
def put(uri, params = {}, env = {}, &block)
|
70
|
+
env = env_for(uri, env.merge(:method => "PUT", :params => params))
|
71
|
+
process_request(uri, env, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Issue a DELETE request for the given URI. See #get
|
75
|
+
#
|
76
|
+
# Example:
|
77
|
+
# delete "/"
|
78
|
+
def delete(uri, params = {}, env = {}, &block)
|
79
|
+
env = env_for(uri, env.merge(:method => "DELETE", :params => params))
|
80
|
+
process_request(uri, env, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Issue a HEAD request for the given URI. See #get
|
84
|
+
#
|
85
|
+
# Example:
|
86
|
+
# head "/"
|
87
|
+
def head(uri, params = {}, env = {}, &block)
|
88
|
+
env = env_for(uri, env.merge(:method => "HEAD", :params => params))
|
89
|
+
process_request(uri, env, &block)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Issue a request to the Rack app for the given URI and optional Rack
|
93
|
+
# environment. Stores the issues request object in #last_request and
|
94
|
+
# the app's response in #last_response. Yield #last_response to a block
|
95
|
+
# if given.
|
96
|
+
#
|
97
|
+
# Example:
|
98
|
+
# request "/"
|
99
|
+
def request(uri, env = {}, &block)
|
100
|
+
env = env_for(uri, env)
|
101
|
+
process_request(uri, env, &block)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Set a header to be included on all subsequent requests through the
|
105
|
+
# session. Use a value of nil to remove a previously configured header.
|
106
|
+
#
|
107
|
+
# Example:
|
108
|
+
# header "User-Agent", "Firefox"
|
109
|
+
def header(name, value)
|
110
|
+
if value.nil?
|
111
|
+
@headers.delete(name)
|
112
|
+
else
|
113
|
+
@headers[name] = value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Set the username and password for HTTP Basic authorization, to be
|
118
|
+
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
119
|
+
#
|
120
|
+
# Example:
|
121
|
+
# basic_authorize "bryan", "secret"
|
122
|
+
def basic_authorize(username, password)
|
123
|
+
encoded_login = ["#{username}:#{password}"].pack("m*")
|
124
|
+
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
125
|
+
end
|
126
|
+
|
127
|
+
alias_method :authorize, :basic_authorize
|
128
|
+
|
129
|
+
def digest_authorize(username, password)
|
130
|
+
@digest_username = username
|
131
|
+
@digest_password = password
|
132
|
+
end
|
133
|
+
|
134
|
+
# Rack::Test will not follow any redirects automatically. This method
|
135
|
+
# will follow the redirect returned in the last response. If the last
|
136
|
+
# response was not a redirect, an error will be raised.
|
137
|
+
def follow_redirect!
|
138
|
+
unless last_response.redirect?
|
139
|
+
raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
|
140
|
+
end
|
141
|
+
|
142
|
+
get(last_response["Location"])
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def env_for(path, env)
|
148
|
+
uri = URI.parse(path)
|
149
|
+
uri.host ||= @default_host
|
150
|
+
|
151
|
+
env = default_env.merge(env)
|
152
|
+
|
153
|
+
env.update("HTTPS" => "on") if URI::HTTPS === uri
|
154
|
+
env["X-Requested-With"] = "XMLHttpRequest" if env[:xhr]
|
155
|
+
|
156
|
+
if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST" ||
|
157
|
+
env[:method] == "PUT" || env["REQUEST_METHOD"] == "PUT") && !env.has_key?(:input)
|
158
|
+
env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded"
|
159
|
+
|
160
|
+
multipart = (Hash === env[:params]) &&
|
161
|
+
env[:params].any? { |_, v| UploadedFile === v }
|
162
|
+
|
163
|
+
if multipart
|
164
|
+
env[:input] = multipart_body(env.delete(:params))
|
165
|
+
env["CONTENT_LENGTH"] ||= env[:input].length.to_s
|
166
|
+
env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
|
167
|
+
else
|
168
|
+
env[:input] = params_to_string(env.delete(:params))
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
params = env[:params] || {}
|
173
|
+
params.update(parse_query(uri.query))
|
174
|
+
|
175
|
+
uri.query = requestify(params)
|
176
|
+
|
177
|
+
if env.has_key?(:cookie)
|
178
|
+
set_cookie(env.delete(:cookie), uri)
|
179
|
+
end
|
180
|
+
|
181
|
+
Rack::MockRequest.env_for(uri.to_s, env)
|
182
|
+
end
|
183
|
+
|
184
|
+
def process_request(uri, env)
|
185
|
+
uri = URI.parse(uri)
|
186
|
+
uri.host ||= @default_host
|
187
|
+
|
188
|
+
@rack_mock_session.request(uri, env)
|
189
|
+
|
190
|
+
if retry_with_digest_auth?(env)
|
191
|
+
auth_env = env.merge({
|
192
|
+
"HTTP_AUTHORIZATION" => digest_auth_header,
|
193
|
+
"rack-test.digest_auth_retry" => true
|
194
|
+
})
|
195
|
+
auth_env.delete('rack.request')
|
196
|
+
process_request(uri.path, auth_env)
|
197
|
+
else
|
198
|
+
yield last_response if block_given?
|
199
|
+
|
200
|
+
last_response
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def digest_auth_header
|
205
|
+
challenge = last_response["WWW-Authenticate"].split(" ", 2).last
|
206
|
+
params = Rack::Auth::Digest::Params.parse(challenge)
|
207
|
+
|
208
|
+
params.merge!({
|
209
|
+
"username" => @digest_username,
|
210
|
+
"nc" => "00000001",
|
211
|
+
"cnonce" => "nonsensenonce",
|
212
|
+
"uri" => last_request.path_info,
|
213
|
+
"method" => last_request.env["REQUEST_METHOD"],
|
214
|
+
})
|
215
|
+
|
216
|
+
params["response"] = MockDigestRequest.new(params).response(@digest_password)
|
217
|
+
|
218
|
+
"Digest #{params}"
|
219
|
+
end
|
220
|
+
|
221
|
+
def retry_with_digest_auth?(env)
|
222
|
+
last_response.status == 401 &&
|
223
|
+
digest_auth_configured? &&
|
224
|
+
!env["rack-test.digest_auth_retry"]
|
225
|
+
end
|
226
|
+
|
227
|
+
def digest_auth_configured?
|
228
|
+
@digest_username
|
229
|
+
end
|
230
|
+
|
231
|
+
def default_env
|
232
|
+
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers)
|
233
|
+
end
|
234
|
+
|
235
|
+
def params_to_string(params)
|
236
|
+
case params
|
237
|
+
when Hash then requestify(params)
|
238
|
+
when nil then ""
|
239
|
+
else params
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require "uri"
|
2
|
+
module Rack
|
3
|
+
module Test
|
4
|
+
|
5
|
+
class Cookie
|
6
|
+
include Rack::Utils
|
7
|
+
|
8
|
+
# :api: private
|
9
|
+
attr_reader :name, :value
|
10
|
+
|
11
|
+
# :api: private
|
12
|
+
def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
|
13
|
+
@default_host = default_host
|
14
|
+
uri ||= default_uri
|
15
|
+
|
16
|
+
# separate the name / value pair from the cookie options
|
17
|
+
@name_value_raw, options = raw.split(/[;,] */n, 2)
|
18
|
+
|
19
|
+
@name, @value = parse_query(@name_value_raw, ';').to_a.first
|
20
|
+
@options = parse_query(options, ';')
|
21
|
+
|
22
|
+
@options["domain"] ||= (uri.host || default_host)
|
23
|
+
@options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
|
24
|
+
end
|
25
|
+
|
26
|
+
def replaces?(other)
|
27
|
+
[name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
|
28
|
+
end
|
29
|
+
|
30
|
+
# :api: private
|
31
|
+
def raw
|
32
|
+
@name_value_raw
|
33
|
+
end
|
34
|
+
|
35
|
+
# :api: private
|
36
|
+
def empty?
|
37
|
+
@value.nil? || @value.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
# :api: private
|
41
|
+
def domain
|
42
|
+
@options["domain"]
|
43
|
+
end
|
44
|
+
|
45
|
+
def secure?
|
46
|
+
@options.has_key?("secure")
|
47
|
+
end
|
48
|
+
|
49
|
+
# :api: private
|
50
|
+
def path
|
51
|
+
@options["path"].strip || "/"
|
52
|
+
end
|
53
|
+
|
54
|
+
# :api: private
|
55
|
+
def expires
|
56
|
+
Time.parse(@options["expires"]) if @options["expires"]
|
57
|
+
end
|
58
|
+
|
59
|
+
# :api: private
|
60
|
+
def expired?
|
61
|
+
expires && expires < Time.now
|
62
|
+
end
|
63
|
+
|
64
|
+
# :api: private
|
65
|
+
def valid?(uri)
|
66
|
+
uri ||= default_uri
|
67
|
+
|
68
|
+
if uri.host.nil?
|
69
|
+
uri.host = @default_host
|
70
|
+
end
|
71
|
+
|
72
|
+
(!secure? || (secure? && uri.scheme == "https")) &&
|
73
|
+
uri.host =~ Regexp.new("#{Regexp.escape(domain)}$", Regexp::IGNORECASE) &&
|
74
|
+
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
75
|
+
end
|
76
|
+
|
77
|
+
# :api: private
|
78
|
+
def matches?(uri)
|
79
|
+
! expired? && valid?(uri)
|
80
|
+
end
|
81
|
+
|
82
|
+
# :api: private
|
83
|
+
def <=>(other)
|
84
|
+
# Orders the cookies from least specific to most
|
85
|
+
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def default_uri
|
91
|
+
URI.parse("//" + @default_host + "/")
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
class CookieJar
|
97
|
+
|
98
|
+
# :api: private
|
99
|
+
def initialize(cookies = [], default_host = DEFAULT_HOST)
|
100
|
+
@default_host = default_host
|
101
|
+
@cookies = cookies
|
102
|
+
@cookies.sort!
|
103
|
+
end
|
104
|
+
|
105
|
+
def [](name)
|
106
|
+
cookies = hash_for(nil)
|
107
|
+
# TODO: Should be case insensitive
|
108
|
+
cookies[name] && cookies[name].value
|
109
|
+
end
|
110
|
+
|
111
|
+
def []=(name, value)
|
112
|
+
# TODO: needs proper escaping
|
113
|
+
merge("#{name}=#{value}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def merge(raw_cookies, uri = nil)
|
117
|
+
return unless raw_cookies
|
118
|
+
|
119
|
+
Array(raw_cookies).join("\n").split("\n").each do |raw_cookie|
|
120
|
+
cookie = Cookie.new(raw_cookie, uri, @default_host)
|
121
|
+
self << cookie if cookie.valid?(uri)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def <<(new_cookie)
|
126
|
+
@cookies.reject! do |existing_cookie|
|
127
|
+
new_cookie.replaces?(existing_cookie)
|
128
|
+
end
|
129
|
+
|
130
|
+
@cookies << new_cookie
|
131
|
+
@cookies.sort!
|
132
|
+
end
|
133
|
+
|
134
|
+
# :api: private
|
135
|
+
def for(uri)
|
136
|
+
hash_for(uri).values.map { |c| c.raw }.join(';')
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_hash
|
140
|
+
cookies = {}
|
141
|
+
|
142
|
+
hash_for(nil).each do |name, cookie|
|
143
|
+
cookies[name] = cookie.value
|
144
|
+
end
|
145
|
+
|
146
|
+
return cookies
|
147
|
+
end
|
148
|
+
|
149
|
+
protected
|
150
|
+
|
151
|
+
def hash_for(uri = nil)
|
152
|
+
cookies = {}
|
153
|
+
|
154
|
+
# The cookies are sorted by most specific first. So, we loop through
|
155
|
+
# all the cookies in order and add it to a hash by cookie name if
|
156
|
+
# the cookie can be sent to the current URI. It's added to the hash
|
157
|
+
# so that when we are done, the cookies will be unique by name and
|
158
|
+
# we'll have grabbed the most specific to the URI.
|
159
|
+
@cookies.each do |cookie|
|
160
|
+
cookies[cookie.name] = cookie if cookie.matches?(uri)
|
161
|
+
end
|
162
|
+
|
163
|
+
return cookies
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|