middleman 0.2.1 → 0.2.2
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/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
|