rack-test 1.1.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/History.md +82 -1
- data/MIT-LICENSE.txt +1 -0
- data/README.md +52 -63
- data/lib/rack/mock_session.rb +2 -63
- data/lib/rack/test/cookie_jar.rb +101 -49
- data/lib/rack/test/methods.rb +57 -45
- data/lib/rack/test/mock_digest_request.rb +11 -1
- data/lib/rack/test/uploaded_file.rb +35 -11
- data/lib/rack/test/utils.rb +75 -61
- data/lib/rack/test/version.rb +1 -1
- data/lib/rack/test.rb +223 -143
- metadata +27 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6f9d525a0e1136056dcc7ebfb288dd4a0f2d82b02bc7f6b4de8a8b1e1b2f653
|
4
|
+
data.tar.gz: 2503679c0681795e9db75ec5963eaea12f2f934b4e5e3d23a30396a318e2ad3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b593ae59ec047f4048c96af421865855129563be719e9a0da088d275f20b3143300d83b4783aa073230bc8cc9118289562f83797682dd1a09073e0cbedc8fcb
|
7
|
+
data.tar.gz: 9f98f0e2d36fe2cf33193a279acca2c62bcf3e5c91bb8adc3a0a71d929ff92b24ab27e7bb826c70cecc52fda5c67c7af57a7d471ff7456c13421d6c719ace434
|
data/History.md
CHANGED
@@ -1,3 +1,84 @@
|
|
1
|
+
## 2.0.0 / 2022-06-24
|
2
|
+
|
3
|
+
* Breaking changes:
|
4
|
+
* Digest authentication support is now deprecated, as it relies on
|
5
|
+
digest authentication support in rack, which has been deprecated
|
6
|
+
(Jeremy Evans #294)
|
7
|
+
* `Rack::Test::Utils.build_primitive_part` no longer handles array
|
8
|
+
values (Jeremy Evans #292)
|
9
|
+
* `Rack::Test::Utils` module methods other than `build_nested_query`
|
10
|
+
and `build_multipart` are now private methods (Jeremy Evans #297)
|
11
|
+
* `Rack::MockSession` has been combined into `Rack::Test::Session`,
|
12
|
+
and remains as an alias to `Rack::Test::Session`, but to keep some
|
13
|
+
backwards compatibility, `Rack::Test::Session.new` will accept a
|
14
|
+
`Rack::Test::Session` instance and return it (Jeremy Evans #297)
|
15
|
+
* Previously protected methods in `Rack::Test::Cookie{,Jar}` are now
|
16
|
+
private methods (Jeremy Evans #297)
|
17
|
+
* `Rack::Test::Methods` no longer defines `build_rack_mock_session`,
|
18
|
+
but for backwards compatibility, `build_rack_test_session` will call
|
19
|
+
`build_rack_mock_session` if it is defined (Jeremy Evans #297)
|
20
|
+
* `Rack::Test::Methods::METHODS` is no longer defined
|
21
|
+
(Jeremy Evans #297)
|
22
|
+
* `Rack::Test::Methods#_current_session_names` has been removed
|
23
|
+
(Jeremy Evans #297)
|
24
|
+
* Headers used/accessed by rack-test are now lower case, for rack 3
|
25
|
+
compliance (Jeremy Evans #295)
|
26
|
+
* Frozen literal strings are now used internally, which may break
|
27
|
+
code that mutates static strings returned by rack-test, if any
|
28
|
+
(Jeremy Evans #304)
|
29
|
+
|
30
|
+
* Minor enhancements:
|
31
|
+
* rack-test now works with the rack main branch (what will be rack 3)
|
32
|
+
(Jeremy Evans #280 #292)
|
33
|
+
* rack-test only loads the parts of rack it uses when running on the
|
34
|
+
rack main branch (what will be rack 3) (Jeremy Evans #292)
|
35
|
+
* Development dependencies have been significantly reduced, and are
|
36
|
+
now a subset of the development dependencies of rack itself
|
37
|
+
(Jeremy Evans #292)
|
38
|
+
* Avoid creating multiple large copies of uploaded file data in
|
39
|
+
memory (Jeremy Evans #286)
|
40
|
+
* Specify HTTP/1.0 when submitting requests, to avoid responses with
|
41
|
+
Transfer-Encoding: chunked (Jeremy Evans #288)
|
42
|
+
* Support `:query_params` in rack environment for parameters that
|
43
|
+
are appended to the query string instead of used in the request
|
44
|
+
body (Jeremy Evans #150 #287)
|
45
|
+
* Reduce required ruby version to 2.0, since tests run fine on
|
46
|
+
Ruby 2.0 (Jeremy Evans #292)
|
47
|
+
* Support :multipart env key for request methods to force multipart
|
48
|
+
input (Jeremy Evans #303)
|
49
|
+
* Force multipart input for request methods if content type starts
|
50
|
+
with multipart (Jeremy Evans #303)
|
51
|
+
* Improve performance of Utils.build_multipart by using an
|
52
|
+
append-only design (Jeremy Evans #304)
|
53
|
+
* Improve performance of Utils.build_nested_query for array values
|
54
|
+
(Jeremy Evans #304)
|
55
|
+
|
56
|
+
* Bug fixes:
|
57
|
+
* The `CONTENT_TYPE` of multipart requests is now respected, if it
|
58
|
+
starts with `multipart/` (Tom Knig #238)
|
59
|
+
* Work correctly with responses that respond to `to_a` but not
|
60
|
+
`to_ary` (Sergio Faria #276)
|
61
|
+
* Raise an ArgumentError instead of a TypeError when providing a
|
62
|
+
StringIO without an original filename when creating an
|
63
|
+
UploadedFile (Nuno Correia #279)
|
64
|
+
* Allow combining both an UploadedFile and a plain string when
|
65
|
+
building a multipart upload (Mitsuhiro Shibuya #278)
|
66
|
+
* Fix the generation of filenames with spaces to use path
|
67
|
+
escaping instead of regular escaping, since path unescaping is
|
68
|
+
used to decode it (Muir Manders, Jeremy Evans #275 #284)
|
69
|
+
* Rewind tempfile used for multipart uploads before it is
|
70
|
+
submitted to the application
|
71
|
+
(Jeremy Evans, Alexander Dervish #261 #268 #286)
|
72
|
+
* Fix Rack::Test.encoding_aware_strings to be true only on rack
|
73
|
+
1.6+ (Jeremy Evans #292)
|
74
|
+
* Make Rack::Test::CookieJar#valid? return true/false
|
75
|
+
(Jeremy Evans #292)
|
76
|
+
* Cookies without a domain attribute no longer are submitted to
|
77
|
+
requests for subdomains of that domain, for RFC 6265
|
78
|
+
compliance (Jeremy Evans #292)
|
79
|
+
* Increase required rack version to 1.3, since tests fail on
|
80
|
+
rack 1.2 and below (Jeremy Evans #293)
|
81
|
+
|
1
82
|
## 1.1.0 / 2018-07-21
|
2
83
|
|
3
84
|
* Breaking changes:
|
@@ -8,7 +89,7 @@
|
|
8
89
|
* follow_direct: Include rack.session.options (Mark Edmondson #233)
|
9
90
|
* [CI] Add simplecov (fatkodima #227)
|
10
91
|
|
11
|
-
Bug fixes:
|
92
|
+
* Bug fixes:
|
12
93
|
* Follow relative locations correctly. (Samuel Williams #230)
|
13
94
|
|
14
95
|
## 1.0.0 / 2018-03-27
|
data/MIT-LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
# Rack::Test
|
2
2
|
[](https://badge.fury.io/rb/rack-test)
|
3
|
-
[<img src="https://travis-ci.org/rack-test/rack-test.svg?branch=master" />](https://travis-ci.org/rack-test/rack-test)
|
4
|
-
[](https://codeclimate.com/github/rack-test/rack-test)
|
5
|
-
[](https://codeclimate.com/github/rack-test/rack-test/coverage)
|
6
3
|
|
7
|
-
Code: https://github.com/rack
|
4
|
+
Code: https://github.com/rack/rack-test
|
8
5
|
|
9
6
|
## Description
|
10
7
|
|
@@ -14,76 +11,66 @@ to build on.
|
|
14
11
|
|
15
12
|
## Features
|
16
13
|
|
14
|
+
* Allows for submitting requests and testing responses
|
17
15
|
* Maintains a cookie jar across requests
|
18
|
-
*
|
19
|
-
*
|
20
|
-
* Small footprint. Approximately 200 LOC
|
21
|
-
|
22
|
-
## Supported platforms
|
23
|
-
|
24
|
-
* 2.2.2+
|
25
|
-
* 2.3
|
26
|
-
* 2.4
|
27
|
-
* JRuby 9.1.+
|
28
|
-
|
29
|
-
If you are using Ruby 1.8, 1.9 or JRuby 1.7, use rack-test 0.6.3.
|
30
|
-
|
31
|
-
## Known incompatibilites
|
32
|
-
|
33
|
-
* `rack-test >= 0.71` _does not_ work with older Capybara versions (`< 2.17`). See [#214](https://github.com/rack-test/rack-test/issues/214) for more details.
|
16
|
+
* Supports request headers used for subsequent requests
|
17
|
+
* Follow redirects when requested
|
34
18
|
|
35
19
|
## Examples
|
36
|
-
|
20
|
+
|
21
|
+
These examples use `test/unit` but it's equally possible to use `rack-test` with
|
22
|
+
other testing frameworks such as `minitest` or `rspec`.
|
37
23
|
|
38
24
|
```ruby
|
39
25
|
require "test/unit"
|
40
26
|
require "rack/test"
|
27
|
+
require "json"
|
41
28
|
|
42
29
|
class HomepageTest < Test::Unit::TestCase
|
43
30
|
include Rack::Test::Methods
|
44
31
|
|
45
32
|
def app
|
46
|
-
|
47
|
-
builder = Rack::Builder.new
|
48
|
-
builder.run app
|
33
|
+
lambda { |env| [200, {'content-type' => 'text/plain'}, ['All responses are OK']] }
|
49
34
|
end
|
50
35
|
|
51
36
|
def test_response_is_ok
|
52
|
-
|
37
|
+
# Optionally set headers used for all requests in this spec:
|
38
|
+
#header 'accept-charset', 'utf-8'
|
53
39
|
|
54
|
-
|
55
|
-
assert_equal last_response.body, 'All responses are OK'
|
56
|
-
end
|
57
|
-
|
58
|
-
def set_request_headers
|
59
|
-
header 'Accept-Charset', 'utf-8'
|
40
|
+
# First argument is treated as the path
|
60
41
|
get '/'
|
61
42
|
|
62
43
|
assert last_response.ok?
|
63
44
|
assert_equal last_response.body, 'All responses are OK'
|
64
45
|
end
|
65
46
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
47
|
+
def delete_with_url_params_and_body
|
48
|
+
# First argument can have a query string
|
49
|
+
#
|
50
|
+
# Second argument is used as the parameters for the request, which will be
|
51
|
+
# included in the request body for non-GET requests.
|
52
|
+
delete '/?foo=bar', JSON.generate('baz' => 'zot')
|
71
53
|
end
|
72
54
|
|
73
55
|
def post_with_json
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
56
|
+
# Third argument is the rack environment to use for the request. The following
|
57
|
+
# entries in the submitted rack environment are treated specially (in addition
|
58
|
+
# to options supported by `Rack::MockRequest#env_for`:
|
59
|
+
#
|
60
|
+
# :cookie : Set a cookie for the current session before submitting the request.
|
61
|
+
#
|
62
|
+
# :query_params : Set parameters for the query string (as opposed to the body).
|
63
|
+
# Value should be a hash of parameters.
|
64
|
+
#
|
65
|
+
# :xhr : Set HTTP_X_REQUESTED_WITH env key to XMLHttpRequest.
|
66
|
+
post(uri, JSON.generate('baz' => 'zot'), 'CONTENT_TYPE' => 'application/json')
|
82
67
|
end
|
83
68
|
end
|
84
69
|
```
|
85
70
|
|
86
|
-
|
71
|
+
`rack-test` will test the app returned by the `app` method. If you are loading middleware
|
72
|
+
in a `config.ru` file, and want to test that, you should load the Rack app created from
|
73
|
+
the `config.ru` file:
|
87
74
|
|
88
75
|
```ruby
|
89
76
|
OUTER_APP = Rack::Builder.parse_file("config.ru").first
|
@@ -102,7 +89,6 @@ class TestApp < Test::Unit::TestCase
|
|
102
89
|
end
|
103
90
|
```
|
104
91
|
|
105
|
-
|
106
92
|
## Install
|
107
93
|
|
108
94
|
To install the latest release as a gem:
|
@@ -111,40 +97,43 @@ To install the latest release as a gem:
|
|
111
97
|
gem install rack-test
|
112
98
|
```
|
113
99
|
|
114
|
-
Or
|
100
|
+
Or add to your `Gemfile`:
|
115
101
|
|
116
102
|
```
|
117
103
|
gem 'rack-test'
|
118
104
|
```
|
119
105
|
|
120
|
-
|
106
|
+
## Contribution
|
121
107
|
|
122
|
-
|
123
|
-
|
124
|
-
|
108
|
+
Contributions are welcome. Please make sure to:
|
109
|
+
|
110
|
+
* Use a regular forking workflow
|
111
|
+
* Write tests for the new or changed behaviour
|
112
|
+
* Provide an explanation/motivation in your commit message / PR message
|
113
|
+
* Ensure `History.md` is updated
|
125
114
|
|
126
115
|
## Authors
|
127
116
|
|
128
|
-
- Contributions from Bryan Helmkamp, Simon Rozet,
|
117
|
+
- Contributions from Bryan Helmkamp, Jeremy Evans, Simon Rozet, and others
|
129
118
|
- Much of the original code was extracted from Merb 1.0's request helper
|
130
119
|
|
131
120
|
## License
|
132
|
-
`rack-test` is released under the [MIT License](MIT-LICENSE.txt).
|
133
121
|
|
134
|
-
|
122
|
+
`rack-test` is released under the [MIT License](MIT-LICENSE.txt).
|
135
123
|
|
136
|
-
|
124
|
+
## Supported platforms
|
137
125
|
|
138
|
-
*
|
139
|
-
*
|
140
|
-
* Provide an explanation/motivation in your commit message / PR message
|
141
|
-
* Ensure History.txt is updated
|
126
|
+
* Ruby 2.0+
|
127
|
+
* JRuby 9.1+
|
142
128
|
|
143
129
|
## Releasing
|
144
130
|
|
145
|
-
* Ensure `History.md` is up-to-date
|
146
131
|
* Bump VERSION in lib/rack/test/version.rb
|
147
|
-
* `
|
132
|
+
* Ensure `History.md` is up-to-date, including correct version and date
|
133
|
+
* `git commit . -m 'Release $VERSION'`
|
148
134
|
* `git push`
|
149
|
-
*
|
150
|
-
*
|
135
|
+
* `git tag -a -m 'Tag the $VERSION release' $VERSION`
|
136
|
+
* `git push --tags`
|
137
|
+
* `gem build rack-test.gemspec`
|
138
|
+
* `gem push rack-test-$VERSION.gem`
|
139
|
+
* Add a discussion post for the release
|
data/lib/rack/mock_session.rb
CHANGED
@@ -1,63 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
attr_writer :cookie_jar
|
4
|
-
attr_reader :default_host
|
5
|
-
|
6
|
-
def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
|
7
|
-
@app = app
|
8
|
-
@after_request = []
|
9
|
-
@default_host = default_host
|
10
|
-
@last_request = nil
|
11
|
-
@last_response = nil
|
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
|
-
|
31
|
-
@last_response = MockResponse.new(status, headers, body, env['rack.errors'].flush)
|
32
|
-
body.close if body.respond_to?(:close)
|
33
|
-
|
34
|
-
cookie_jar.merge(last_response.headers['Set-Cookie'], uri)
|
35
|
-
|
36
|
-
@after_request.each(&:call)
|
37
|
-
|
38
|
-
if @last_response.respond_to?(:finish)
|
39
|
-
@last_response.finish
|
40
|
-
else
|
41
|
-
@last_response
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Return the last request issued in the session. Raises an error if no
|
46
|
-
# requests have been sent yet.
|
47
|
-
def last_request
|
48
|
-
raise Rack::Test::Error, 'No request yet. Request a page first.' unless @last_request
|
49
|
-
@last_request
|
50
|
-
end
|
51
|
-
|
52
|
-
# Return the last response received in the session. Raises an error if
|
53
|
-
# no requests have been sent yet.
|
54
|
-
def last_response
|
55
|
-
raise Rack::Test::Error, 'No response yet. Request a page first.' unless @last_response
|
56
|
-
@last_response
|
57
|
-
end
|
58
|
-
|
59
|
-
def cookie_jar
|
60
|
-
@cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
1
|
+
warn("requiring rack/mock_session is deprecated, require rack/test and use Rack::Test::Session", uplevel: 1)
|
2
|
+
require_relative 'test'
|
data/lib/rack/test/cookie_jar.rb
CHANGED
@@ -1,94 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'time'
|
3
5
|
|
4
6
|
module Rack
|
5
7
|
module Test
|
8
|
+
# Represents individual cookies in the cookie jar. This is considered private
|
9
|
+
# API and behavior of this class can change at any time.
|
6
10
|
class Cookie # :nodoc:
|
7
11
|
include Rack::Utils
|
8
12
|
|
9
|
-
#
|
10
|
-
attr_reader :name
|
13
|
+
# The name of the cookie, will be a string
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# The value of the cookie, will be a string or nil if there is no value.
|
17
|
+
attr_reader :value
|
18
|
+
|
19
|
+
# The raw string for the cookie, without options. Will generally be in
|
20
|
+
# name=value format is name and value are provided.
|
21
|
+
attr_reader :raw
|
11
22
|
|
12
|
-
# :api: private
|
13
23
|
def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
|
14
24
|
@default_host = default_host
|
15
25
|
uri ||= default_uri
|
16
26
|
|
17
27
|
# separate the name / value pair from the cookie options
|
18
|
-
@
|
28
|
+
@raw, options = raw.split(/[;,] */n, 2)
|
19
29
|
|
20
|
-
@name, @value = parse_query(@
|
30
|
+
@name, @value = parse_query(@raw, ';').to_a.first
|
21
31
|
@options = parse_query(options, ';')
|
22
32
|
|
23
|
-
@options['domain']
|
24
|
-
|
33
|
+
if @options['domain']
|
34
|
+
@exact_domain_match = false
|
35
|
+
else
|
36
|
+
# If the domain attribute is not present in the cookie,
|
37
|
+
# the domain must match exactly.
|
38
|
+
@exact_domain_match = true
|
39
|
+
@options['domain'] = (uri.host || default_host)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set the path for the cookie to the directory containing
|
43
|
+
# the request if it isn't set.
|
44
|
+
@options['path'] ||= uri.path.sub(/\/[^\/]*\Z/, '')
|
25
45
|
end
|
26
46
|
|
47
|
+
# Wether the given cookie can replace the current cookie in the cookie jar.
|
27
48
|
def replaces?(other)
|
28
49
|
[name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
|
29
50
|
end
|
30
51
|
|
31
|
-
#
|
32
|
-
def raw
|
33
|
-
@name_value_raw
|
34
|
-
end
|
35
|
-
|
36
|
-
# :api: private
|
52
|
+
# Whether the cookie has a value.
|
37
53
|
def empty?
|
38
54
|
@value.nil? || @value.empty?
|
39
55
|
end
|
40
56
|
|
41
|
-
#
|
57
|
+
# The explicit or implicit domain for the cookie.
|
42
58
|
def domain
|
43
59
|
@options['domain']
|
44
60
|
end
|
45
61
|
|
62
|
+
# Whether the cookie has the secure flag, indicating it can only be sent over
|
63
|
+
# an encrypted connection.
|
46
64
|
def secure?
|
47
65
|
@options.key?('secure')
|
48
66
|
end
|
49
67
|
|
68
|
+
# Whether the cookie has the httponly flag, indicating it is not available via
|
69
|
+
# a javascript API.
|
50
70
|
def http_only?
|
51
|
-
@options.key?('HttpOnly')
|
71
|
+
@options.key?('HttpOnly') || @options.key?('httponly')
|
52
72
|
end
|
53
73
|
|
54
|
-
#
|
74
|
+
# The explicit or implicit path for the cookie.
|
55
75
|
def path
|
56
76
|
([*@options['path']].first.split(',').first || '/').strip
|
57
77
|
end
|
58
78
|
|
59
|
-
#
|
79
|
+
# A Time value for when the cookie expires, if the expires option is set.
|
60
80
|
def expires
|
61
81
|
Time.parse(@options['expires']) if @options['expires']
|
62
82
|
end
|
63
83
|
|
64
|
-
#
|
84
|
+
# Whether the cookie is currently expired.
|
65
85
|
def expired?
|
66
86
|
expires && expires < Time.now
|
67
87
|
end
|
68
88
|
|
69
|
-
#
|
89
|
+
# Whether the cookie is valid for the given URI.
|
70
90
|
def valid?(uri)
|
71
91
|
uri ||= default_uri
|
72
92
|
|
73
93
|
uri.host = @default_host if uri.host.nil?
|
74
94
|
|
75
95
|
real_domain = domain =~ /^\./ ? domain[1..-1] : domain
|
76
|
-
(!secure? || (secure? && uri.scheme == 'https')) &&
|
77
|
-
uri.host =~ Regexp.new("#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE) &&
|
78
|
-
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
96
|
+
!!((!secure? || (secure? && uri.scheme == 'https')) &&
|
97
|
+
uri.host =~ Regexp.new("#{'^' if @exact_domain_match}#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE) &&
|
98
|
+
uri.path =~ Regexp.new("^#{Regexp.escape(path)}"))
|
79
99
|
end
|
80
100
|
|
81
|
-
#
|
101
|
+
# Cookies that do not match the URI will not be sent in requests to the URI.
|
82
102
|
def matches?(uri)
|
83
103
|
!expired? && valid?(uri)
|
84
104
|
end
|
85
105
|
|
86
|
-
#
|
106
|
+
# Order cookies by name, path, and domain.
|
87
107
|
def <=>(other)
|
88
|
-
# Orders the cookies from least specific to most
|
89
108
|
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
90
109
|
end
|
91
110
|
|
111
|
+
# A hash of cookie options, including the cookie value, but excluding the cookie name.
|
92
112
|
def to_h
|
93
113
|
@options.merge(
|
94
114
|
'value' => @value,
|
@@ -98,43 +118,62 @@ module Rack
|
|
98
118
|
end
|
99
119
|
alias to_hash to_h
|
100
120
|
|
101
|
-
|
121
|
+
private
|
102
122
|
|
123
|
+
# The default URI to use for the cookie, including just the host.
|
103
124
|
def default_uri
|
104
125
|
URI.parse('//' + @default_host + '/')
|
105
126
|
end
|
106
127
|
end
|
107
128
|
|
129
|
+
# Represents all cookies for a session, handling adding and
|
130
|
+
# removing cookies, and finding which cookies apply to a given
|
131
|
+
# request. This is considered private API and behavior of this
|
132
|
+
# class can change at any time.
|
108
133
|
class CookieJar # :nodoc:
|
109
134
|
DELIMITER = '; '.freeze
|
110
135
|
|
111
|
-
# :api: private
|
112
136
|
def initialize(cookies = [], default_host = DEFAULT_HOST)
|
113
137
|
@default_host = default_host
|
114
|
-
@cookies = cookies
|
115
|
-
@cookies.sort!
|
138
|
+
@cookies = cookies.sort!
|
116
139
|
end
|
117
140
|
|
141
|
+
# Return the value for first cookie with the given name, or nil
|
142
|
+
# if no such cookie exists.
|
118
143
|
def [](name)
|
119
|
-
|
120
|
-
|
121
|
-
|
144
|
+
name = name.to_s
|
145
|
+
@cookies.each do |cookie|
|
146
|
+
return cookie.value if cookie.name == name
|
147
|
+
end
|
148
|
+
nil
|
122
149
|
end
|
123
150
|
|
151
|
+
# Set a cookie with the given name and value in the
|
152
|
+
# cookie jar.
|
124
153
|
def []=(name, value)
|
125
154
|
merge("#{name}=#{Rack::Utils.escape(value)}")
|
126
155
|
end
|
127
156
|
|
157
|
+
# Return the first cookie with the given name, or nil if
|
158
|
+
# no such cookie exists.
|
128
159
|
def get_cookie(name)
|
129
|
-
|
160
|
+
@cookies.each do |cookie|
|
161
|
+
return cookie if cookie.name == name
|
162
|
+
end
|
163
|
+
nil
|
130
164
|
end
|
131
165
|
|
166
|
+
# Delete all cookies with the given name from the cookie jar.
|
132
167
|
def delete(name)
|
133
168
|
@cookies.reject! do |cookie|
|
134
169
|
cookie.name == name
|
135
170
|
end
|
171
|
+
nil
|
136
172
|
end
|
137
173
|
|
174
|
+
# Add a string of raw cookie information to the cookie jar,
|
175
|
+
# if the cookie is valid for the given URI.
|
176
|
+
# Cookies should be separated with a newline.
|
138
177
|
def merge(raw_cookies, uri = nil)
|
139
178
|
return unless raw_cookies
|
140
179
|
|
@@ -149,6 +188,7 @@ module Rack
|
|
149
188
|
end
|
150
189
|
end
|
151
190
|
|
191
|
+
# Add a Cookie to the cookie jar.
|
152
192
|
def <<(new_cookie)
|
153
193
|
@cookies.reject! do |existing_cookie|
|
154
194
|
new_cookie.replaces?(existing_cookie)
|
@@ -158,36 +198,48 @@ module Rack
|
|
158
198
|
@cookies.sort!
|
159
199
|
end
|
160
200
|
|
161
|
-
#
|
201
|
+
# Return a raw cookie string for the cookie header to
|
202
|
+
# use for the given URI.
|
162
203
|
def for(uri)
|
163
|
-
|
204
|
+
buf = String.new
|
205
|
+
delimiter = nil
|
206
|
+
|
207
|
+
each_cookie_for(uri) do |cookie|
|
208
|
+
if delimiter
|
209
|
+
buf << delimiter
|
210
|
+
else
|
211
|
+
delimiter = DELIMITER
|
212
|
+
end
|
213
|
+
buf << cookie.raw
|
214
|
+
end
|
215
|
+
|
216
|
+
buf
|
164
217
|
end
|
165
218
|
|
219
|
+
# Return a hash cookie names and cookie values for cookies in the jar.
|
166
220
|
def to_hash
|
167
221
|
cookies = {}
|
168
222
|
|
169
|
-
|
170
|
-
cookies[name] = cookie.value
|
223
|
+
@cookies.each do |cookie|
|
224
|
+
cookies[cookie.name] = cookie.value
|
171
225
|
end
|
172
226
|
|
173
227
|
cookies
|
174
228
|
end
|
175
229
|
|
176
|
-
|
230
|
+
private
|
177
231
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
232
|
+
# Yield each cookie that matches for the URI.
|
233
|
+
#
|
234
|
+
# The cookies are sorted by most specific first. So, we loop through
|
235
|
+
# all the cookies in order and add it to a hash by cookie name if
|
236
|
+
# the cookie can be sent to the current URI. It's added to the hash
|
237
|
+
# so that when we are done, the cookies will be unique by name and
|
238
|
+
# we'll have grabbed the most specific to the URI.
|
239
|
+
def each_cookie_for(uri)
|
186
240
|
@cookies.each do |cookie|
|
187
|
-
|
241
|
+
yield cookie if !uri || cookie.matches?(uri)
|
188
242
|
end
|
189
|
-
|
190
|
-
cookies
|
191
243
|
end
|
192
244
|
end
|
193
245
|
end
|